c - 读取图像时使用getc?

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

佐久

最佳答案

我无法在 Unix 下重现,但在 Windows 下可以轻松重现。问题是字符 Ctrl-Z(代码 0x1A)在 Windows 下代表文本文件的文件结束。

问题是 getc 通常用于文本文件,因为一些旧的编辑器习惯于明确编写 Ctrl-Z 来分隔文本文件的末尾,getc 仍然认为它是一个真正的 EOF - 顺便说一句,这与Klas Lindbä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。

关于c - 读取图像时使用getc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30782214/

相关文章:

c - setsockopt SO_SNDBUF 及其在 unix 域中的行为

c - 为什么 p 不显示与 a 相同的地址?

c - 第 25 行中的运行时错误 : Char 35: runtime error: member access within null pointer of type 'struct HASH_TABLE' (solution. c)

android - 某些设备上的 Unity 2D,所有图像都变成粉红色

html - 表格列宽百分比编辑图片

html - 将图像大小调整为 div

c - 返回 64 位整数中所有设置位的位置的最快方法是什么?

c - 释放空指针

mysql - Linux - Docker MySQL 镜像 - 创建 MYSQL_USER

iOS Swift 在 WebView 中显示 Xcassets 图像