在阅读图像时使用getc?

时间:2015-06-11 13:29:56

标签: c image

我对以下简单的读取功能有一个小问题:

    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的组合解决了问题:)

佐久

2 个答案:

答案 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;
     }