Инвертирование битов изображения PBM, в то время как для цикла

Я пытаюсь перевернуть цвет пикселей простого изображения в формате pbm, которое имеет только чистый черный и чистый белый. Я сам генерирую изображение и затем читаю его, а затем переворачиваю биты и сохраняю как сгенерированное изображение, так и инвертированное изображение.

Вот мой код (write_pbm.cpp) -

#include "headers/write_pbm.h"

int width_pbm, height_pbm;

void input_sample_dim(){
    printf("Enter the width and height of image to create = ");
    scanf("%d %d", &width_pbm, &height_pbm);
}

void create_sample_image(){
    FILE *fp;
    fp = fopen("sample.pbm", "wb");

    fprintf(fp, "P1\n");
    fprintf(fp, "# myfile.pbm\n");
    fprintf(fp, "%d %d\n", width_pbm, height_pbm);

    for (int i = 1; i <= height_pbm; i++)
    {
        for (int j = 1; j <= width_pbm; j++)
        {
            if (j == i || (width_pbm - j + 1 == i))
                fprintf(fp, "0");
            else
                fprintf(fp, "1");

            if (j == width_pbm)
                fprintf(fp, "\n");
            else
                fprintf(fp, " ");
        }
    }

    fclose(fp);
}

void invert (){
    printf("\tinverting the image\nturning black pixels white and white pixels black\n");

    FILE *fp = fopen("sample.pbm", "rb");
    while(fgetc(fp) != '\n');
    while(fgetc(fp) != '\n');
    while(fgetc(fp) != '\n');

    FILE *fp_inv;
    fp_inv = fopen("inverted.pbm", "wb");

    fprintf(fp_inv, "P1\n");
    fprintf(fp_inv, "# inverted.pbm\n");
    fprintf(fp_inv, "%d %d\n", width_pbm, height_pbm);


    for (int i = 1; i <= height_pbm; i++){
        for (int j = 1; j <= width_pbm; j++){
            char ch = fgetc(fp);

            if (ch == '1')
                fputc('0', fp_inv);
            else if (ch == '0')
                fputc('1', fp_inv);
            else
                fputc(ch, fp_inv);
        }}
    fclose(fp);
    fclose(fp_inv);

}

Ниже приведен заголовок, который я включаю (write_pbm.h)

#ifndef Write_PBM_H
#define Write_PBM_H

#include <cstdio>
#include <iostream>

void create_sample_image(void);

void input_sample_dim(void);

void invert (void);

extern int width_pbm, height_pbm;

#endif

Ниже мой главный -

#include "write/PBM/headers/write_pbm.h"

int main(){
    input_sample_dim();

    printf("writing sample image\n");
    create_sample_image();
    printf("sample image with dimenstions %d by %d created\n", width_pbm, height_pbm);
    invert();
}

Таким образом, я делаю V-образный вид шаблона, а затем инвертирую цвета и сохраняю как созданное изображение, так и инвертированное изображение.

Предположим, мы предоставляем вход 10 10

тогда файл sample.pbm похоже

P1
# myfile.pbm
10 10
0 1 1 1 1 1 1 1 1 0
1 0 1 1 1 1 1 1 0 1
1 1 0 1 1 1 1 0 1 1
1 1 1 0 1 1 0 1 1 1
1 1 1 1 0 0 1 1 1 1
1 1 1 1 0 0 1 1 1 1
1 1 1 0 1 1 0 1 1 1
1 1 0 1 1 1 1 0 1 1
1 0 1 1 1 1 1 1 0 1
0 1 1 1 1 1 1 1 1 0

а также inverted.pbm выглядит так

P1
# inverted.pbm
10 10
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0

как вы можете видеть, что только половина строк печатается в перевернутом изображении.

Если я заменю вложенные циклы invert() из write_pbm.cpp с

char ch;
while(!feof(fp))
    {
        char ch = fgetc(fp);
        if (ch == '1')
            fputc('0', fp_inv);
        else if (ch == '0')
            fputc('1', fp_inv);
        else
            fputc(ch, fp_inv);
    }

тогда это дает правильный вывод в inverted.pbm файл, который

P1
# inverted.pbm
10 10
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 0 0 1 0 0 0
0 0 1 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 1
\FF

Я делаю то же самое через вложенные циклы и цикл while, тогда почему он дает неправильный вывод в случае вложенных циклов for?

Спасибо, что прочитали это, пожалуйста, предоставьте ваш ценный ответ.

1 ответ

Решение

Глядя на ваш входной файл, кажется, что каждый значащий символ (т.е. '0' или же '1') следует пробел.

в while Цикл, который работает, вы читаете столько символов, сколько нужно, до конца файла, просто инвертируя правильные символы и копируя неожиданные символы. Так что все обрабатывается.

Во вложенном for циклы, вы читаете точное количество символов, соответствующее размерам изображения, так что 10*10. Принимая во внимание структуру входного файла, вы, следовательно, читаете только 100 символов, поэтому 50 '1' или же '0' и 50 мест. Таким образом, вы обрабатываете только половину ввода.

Несвязанный: ваш код использует заголовок C++, но все остальное - просто C. В C++ вы должны рассмотреть возможность использования fstream читать ваши файлы, а не наследие CFILE* API.

Другие вопросы по тегам