反转 PBM 图像的位 while vs for 循环
Inverting bits of PBM image while vs for loop
我正在尝试翻转只有纯黑色和纯白色的简单 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);
}
下面是我包括的 header (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
如您所见,倒置图像中仅打印了一半行。
如果我用
替换 write_pbm.cpp
的 invert()
的嵌套循环
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 循环的情况下给出错误的输出?
感谢阅读本文,请提供您宝贵的回复。
查看您的输入文件,似乎每个有意义的字符(即 '0'
或 '1'
)后跟一个 space。
在正在运行的 while
循环中,您可以根据需要读取尽可能多的字符,直到文件末尾,只需反转正确的字符并复制意外的字符。所以一切都被处理了。
在嵌套的 for
循环中,您正在读取与图片尺寸相对应的确切字符数,即 10*10。考虑到输入文件的布局,您因此只能读取 100 个字符,即 50 '1'
或 '0'
和 50 spaces。所以你只处理一半的输入。
不相关: 你的代码使用了 C++ 头文件,但其余的只是普通的 C。在 C++ 中,你应该考虑使用 fstream
读取您的文件,而不是 C 遗留文件 FILE*
API.
我正在尝试翻转只有纯黑色和纯白色的简单 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);
}
下面是我包括的 header (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
如您所见,倒置图像中仅打印了一半行。
如果我用
替换write_pbm.cpp
的 invert()
的嵌套循环
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 循环的情况下给出错误的输出?
感谢阅读本文,请提供您宝贵的回复。
查看您的输入文件,似乎每个有意义的字符(即 '0'
或 '1'
)后跟一个 space。
在正在运行的 while
循环中,您可以根据需要读取尽可能多的字符,直到文件末尾,只需反转正确的字符并复制意外的字符。所以一切都被处理了。
在嵌套的 for
循环中,您正在读取与图片尺寸相对应的确切字符数,即 10*10。考虑到输入文件的布局,您因此只能读取 100 个字符,即 50 '1'
或 '0'
和 50 spaces。所以你只处理一半的输入。
不相关: 你的代码使用了 C++ 头文件,但其余的只是普通的 C。在 C++ 中,你应该考虑使用 fstream
读取您的文件,而不是 C 遗留文件 FILE*
API.