【问题标题】:Writing a 1D binary array of size N to a (N/2, N/2) size PPM image将大小为 N 的一维二进制数组写入 (N/2, N/2) 大小的 PPM 图像
【发布时间】:2020-11-23 16:07:59
【问题描述】:

我有以下代码 '''

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void main()
{
    int n = 32;
    int* img = malloc(sizeof(int)*n*n);
    for(int i = 0; i < n*n; i++) { 
        if(i%n < n/2) { 
            img[i] =   0;
        }
        else { 
            img[i] = 255;
        }
    }
    FILE *fp = fopen("img.ppm", "wb"); /* b - binary mode */
    fprintf(fp, "P6\n%d %d\n255\n", n, n);
    fwrite(img, sizeof(img), 1, fp);
    fclose(fp);
    free(img);
}

但这只是生成一个空白图像。我不确定问题出在哪里。

【问题讨论】:

  • P6 PPM NetPBM 图像的每个像素由 3 个字节组成。您正在编写一堆 ints,大概每个 4 或 8 个字节。这可能不是你想要的。此外,我怀疑您误解了 sizeof(img) 的作用。
  • 另请注意,32x32 字节内存块的字节数是16x16 2D 网格的 4 倍。现在,如果您在16x16 网格中为每个元素写入 4 字节,这可能就是您所需要的,但您必须确保这是您所需要的。有关图像格式的详细信息,请参阅PPM Format Specification

标签: c ppm


【解决方案1】:

您的代码存在几个问题。 P6 型 NetPBM 对每个像素使用 3 个字节(红、绿、蓝各一个字节)。您可能正在编写一个 32×32 的图像,因此您需要的值比您拥有的值多 3 倍(好吧,除非有意使用 ints,在这种情况下,您的值太多价值观——我们会回到那个)。我假设您实际上想要灰度图像,所以我们将切换到 P5 型 图像。此外,您正在编写ints,它们大概有 4 或 8 个字节长。这是故意的吗?最后,sizeof(img) 为您提供img 类型的大小,即指向int 的指针,即4 或8 个字节,具体取决于您的系统。它不是数组的大小。

这里有一个建议:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h> // I'll use uint8_t for the pixel bytes. That's personal preference, you can also stick with chars if you want.

int main() // Not relevant, but main should return int
{
    int n = 32;
    uint8_t * img = malloc(n*n); // Each pixel is a byte, an 8-bit unsigned integer.
    for(int i = 0; i < n*n; i++) { 
        if(i%n < n/2) { 
            img[i] =   0;
        }
        else { 
            img[i] = 255;
        }
    }
    FILE *fp = fopen("img.ppm", "wb");
    fprintf(fp, "P5\n%d %d\n255\n", n, n); // P5 mode for grayscale, since you don't specify in your question what you want to do with colors.
    fwrite(img, 1, n*n, fp); // n*n pixel values, each 1 byte long.
    fclose(fp);
    free(img);
    return 0;
}

【讨论】:

  • 我唯一要补充的是询问他使用的是什么硬件。 void main() 可能是完全正确的,如果 OP 在定义了程序启动的 独立环境 中的微控制器上编写代码(不能保证启动函数将事件命名为 main())否则你是对的。请参阅C11 Standard - §5.1.2.1 Freestanding environmentC11 Standard - §5.1.2.2.1 Program startup
  • 是的,你是对的。感谢您指出了这一点。无论如何,我不应该通过提出无关的话题来混淆这个问题。
  • 嗯...总是值得一提 - 永远不知道 OP 是否使用了 30 年前的文档,但现在严重不正确:)
  • @David C. Rankin 有趣的一点。我的物理学背景(辅修 CS)和这种可视化是针对流行模型的蒙特卡罗模拟来研究相变的。因此,如果我最近学习 C 时做了一些愚蠢的事情,我深表歉意。我的代码在我的大学运营的超级计算机上运行(不确定这些信息是否足够)。这个问题现在已经解决了,但是,我想确保我没有在现代 C 标准方面做任何违法的事情,所以感谢分享资源。
  • @thedeathstar1997 不不,你没有做任何导致未定义行为的事情。我赞扬您选择 C。您无法选择更好的语言来提供对您碰巧使用的任何硬件的完全低级控制。比大多数语言更重要的是,由于您作为程序员的控制权,C 需要更长的时间才能精通——这些时间是值得的。祝你编码好运!
猜你喜欢
  • 2018-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 1970-01-01
  • 2013-02-21
相关资源
最近更新 更多