我对以下简单的读取功能有一个小问题:
printf("File to be opened: ");
scanf("%s", input);
if ((fp = fopen(input, "r")) == NULL) {
printf("ERROR: can't open %s!", input);
}
else {
if (read_pgm_hdr(fp, &w, &h) != -1) {
printf("*** SUCCESS --%s-- opened ***\n", input);
printf("*** PGM file recognized, reading data into image struct ***\n");
for (i = 0; i < w * h; i++) {
img_data[i] = getc(fp);
}
}
在循环中,img_data数组填充了.pgm中图像的8位灰度值。当w = 300且h = 300时,阵列具有正确的大小。 在大多数情况下,它工作正常。但有时在图像中间,getc()开始用255填充我的数组。
我发现当灰度值为19时会发生这种情况。这个值出现的地方并不重要。如果第3个像素为19,则第3个值和后续每个为255.如果第127个像素为19,则第127个值和后面的每个值为255.
我真的不知道,为什么会这样。我希望任何人都可以提供帮助。
更新:好的,谢谢。以二进制模式打开并使用fread而不是getc的组合解决了问题:)
佐久
答案 0 :(得分:3)
我无法在Unix下重现,但可以轻松地在Windows下重现。问题是字符Ctrl-Z(代码0x1A),它在windows下表示文本文件的结尾。
问题是getc通常用于文本文件,而且一些旧的编辑用来明确地写一个Ctrl-Z来分隔文本文件的结尾,getc仍然认为它是一个真正的EOF - BTW这是连贯的KlasLindbäck的回答。当您在"r"
模式下打开文件时,它会被隐含地打开为文本文件。
修复很简单:将文件作为二进制文件打开。
if ((fp = fopen(input, "rb")) == NULL) ...
(注意 b )应该足够了。
对于引用的字符19,我使用ASCII字符表进行测试,最后一个正确的是... Ctrl-Y = 0x19 ...但罪魁祸首确实是Ctrl-Z = 0x1A。
无论如何,你应该一次更换一个字符的循环:
for (i = 0; i < w * h; i++) {
img_data[i] = getc(fp);
}
带着一个简单的恐惧:
n = fread(img_data, w, h, fp); // or fread(img_data, 1, w * h, fp);
并控制n在第一种方式为h或在第二种方式为n * h。
答案 1 :(得分:0)
255将是getc
返回EOF
的结果。
要测试EOF
,您需要将值存储在int
:
for (i = 0; i < w * h; i++) {
int tmp = getc(fp);
if (tmp == EOF) {
/* Handle EOF */
printf("EOF after readin %d bytes out of %d!!!\n", i, w*h);
break;
}
img_data[i] = tmp;
}