【问题标题】:What is wrong with my manually made .tga file?我手动制作的 .tga 文件有什么问题?
【发布时间】:2020-05-07 23:13:42
【问题描述】:

我正在尝试用 C 语言制作一个基本的光线追踪器,并决定使用 .tga 文件作为输出渲染文件。但无论出于何种原因,创建的文件在我能找到的每个 tga 文件查看器中都显示为纯白色。我写给 is here 的文件的 hexdump 的开头,很明显图像的大片区域应该是黑色的。

写入文件的循环是:

void raycast(uint16_t width, uint16_t height, FILE* file, Sphere* sphere) {
    Vec3* camera = makeVec3(0, 0, 0);
    Vec3* light = makeVec3(1, -1, -1);
    int count = 0;
    double zMax = 1 / cos(toRads(vFOV) / 2.0);
    double yMax = 1 / cos(toRads(hFOV) / 2.0);
    for (uint16_t i = 0; i < height; i++) {
        for (uint16_t j = 0; j < width; j++) {
            int16_t zOffset = (height / 2 - i);
            double zprop = zOffset / (height / 2.0);
            double zCoord = zMax * zprop;
            int16_t yOffset = (width / 2 - j);
            double yprop = yOffset / (width / 2.0);
            double yCoord = yMax * yprop;
            Vec3* coord = makeVec3(1, yCoord, zCoord);
            normalize(coord);
            Ray* ray = makeRay(camera, coord);
            Vec3* intersect = sphereIntersect(sphere, ray);
            if (intersect == NULL) {
                fputc(255, file);
                fputc(255, file);
                fputc(255, file);
            } else {
                printf("disp black\n");
                fputc(0x00, file);
                fputc(0x00, file);
                fputc(0x00, file);
                count++;
            }
        }
    }
    printf("%d\n", count);
}

我看到disp black 打印到控制台,count 增加到超过 300,000,因此将零写入文件显然没有任何问题。我尽力遵循我找到的标题格式here,有问题吗?

我还注意到,我在 if 块中放入的任何内容的图像都是纯色的,就好像总是采用 if 语句一样。

编辑:编写标题的代码

static void writeHeader(FILE* file) {
    static uint16_t width = 800;
    static uint16_t height = 600;
    // 800x600 image, 24 bits per pixel
    unsigned char header[18] = {
        0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00,
        (unsigned char)(width & 0x00FF), (unsigned char)((width & 0xFF00) / 256),
        (unsigned char)(height & 0x00FF), (unsigned char)((height & 0xFF00) / 256),
        0x08, 0x00
    };
    fwrite(header, sizeof(char), 18, file);
}

【问题讨论】:

  • 问题很可能出在标题中,这就是为什么您没有看到预期的结果。如果标头错误,则数据将被错误解释。贴出写头的代码。
  • @gavinb 更新了!它基本上是一个被写入的硬编码数组。

标签: c image file-writing tga


【解决方案1】:

标题错误。您发布的代码正在写入 RGB 数据,但将十六进制转储与您链接的页面中的规范相匹配,我们看到:

Identification Field | 00 = No ID field
Colour Map Type      | 01 = CMap Included
Image Type Code      | 01 = Type 1: Colour Mapped
Colour Map Spec      | 00 00 00 01 18 ...
Image Spec
X Origin             | 00 00 = 0
Y Origin             | 00 00 = 0
Width                | 20 03 = 800px
Height               | 58 02 = 600px
Bits/Pixel           | 08    = 8bpp
Descriptor           | 00...

你的标题说文件是彩色映射的。由于标头与数据不匹配,因此会被误解,无法显示您希望看到的内容。

您几乎肯定需要 Type 2 'Unmapped RGB' 来匹配您正在写入的数据,因此第 2 个字节应该是 0x00(您不提供颜色图),第 3 个字节应该是 0x02(表示 RGB) .然后应该忽略颜色映射规范,以便可以填充零。大小等看起来不错。

我不建议像这样简单地将固定标头编写为字节数组。它容易出错且不灵活。定义一个定义标题的struct 非常容易,然后如果为图像类型代码等定义enum,您将获得标记字段、正确类型和符号常量的优势。

链接的文章已经提供了这个,你只需要确保它没有被编译器通过编译指示填充,以确保布局与描述的完全相同:

#pragma pack(push, 1)
typedef struct {
   char  idlength;
   char  colourmaptype;
   char  datatypecode;
   short int colourmaporigin;
   short int colourmaplength;
   char  colourmapdepth;
   short int x_origin;
   short int y_origin;
   short width;
   short height;
   char  bitsperpixel;
   char  imagedescriptor;
} HEADER;
#pragma pack(pop)

【讨论】:

  • 感谢您的帮助!我没有完全理解标题中的所有字段,我想在制作结构之前让一些东西工作。我做了你的更改,当我在 windows 上的 tgaviewer 中打开它时,它不再是纯白色。但是当我尝试在 Linux 中使用eog 打开它时,它说不支持 TGA 图像类型。有什么想法吗?
  • 那么当你用 tgaviewer 查看图像时,它看起来像你期望的那样吗?至于在日志中查看,取决于实际的标头字节。可以是任何东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多