Инвертирование битов изображения PBM, в то время как для цикла - PullRequest
1 голос
/ 25 марта 2019

Я пытаюсь перевернуть цвет пикселей простого изображения в формате 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, затем why это дает неправильный вывод в случае вложенных циклов?

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

1 Ответ

1 голос
/ 25 марта 2019

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

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

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

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

...