【问题标题】:TGA File Header is not correct on WindowsTGA 文件头在 Windows 上不正确
【发布时间】:2017-08-23 14:58:22
【问题描述】:

我正在尝试读取我在 Paint.net 中创建的文件的 TGA 标头。它似乎有什么问题。如果我使用规范中的标头结构,例如:

typedef struct {
    CHAR  idlength;
    CHAR  colourmaptype;
    CHAR  datatypecode;
    WORD colourmaporigin;
    WORD colourmaplength;
    CHAR  colourmapdepth;
    WORD x_origin;
    WORD y_origin;
    WORD width;
    WORD height;
    CHAR  bitsperpixel;
    CHAR  imagedescriptor;
} TGAHEADER;

我明白了:

Data size: 0
Color Map type: 0
Data Type code: 2
Bits per-pixel: 0
Size: 501 x 2080

这是错误的,因为我的图像是 501x501,每像素 32 位。但是,如果我从结构中注释掉两个字节,f.e.这个colourmaporigin,我明白了:

Data size: 0
Color Map type: 0
Data Type code: 2
Bits per-pixel: 32
Size: 501 x 501

这是正确的。我正在阅读我在这种文件格式上找到的所有内容。它从不说这些字段中的任何一个都是可选的。

我怎么会得到这样的结果?

读取数据的代码如下:

void Image::readTGA()
{
    TGAHEADER fileHeader;

    std::ifstream fileHandle(fileName, std::ios::binary);
    if (fileHandle.is_open())
    {
        fileHandle.read((char*)(&fileHeader), sizeof(TGAHEADER));
        fileHandle.close();
    }
    else
    {
        std::cout << "An error occured when opening a file." << std::endl;
    }
}

我正在使用 VS2015,针对 x86 平台。

【问题讨论】:

  • 这可能是一个填充问题。根据您的编译器,您可以使用禁用结构填充的特定#pragma,但这可能是某些架构的问题,因为大于 1 字节的数据的未对齐内存访问可能不起作用。告诉我们您的目标平台以及您使用的编译器。请阅读thisthis
  • 我正在使用 VS2015,针对 x86 平台。我在考虑填充,但是如果您考虑一下,填充只会使数据更远,但在这种情况下,它们最终会“更早”,对吗?换句话说,如果这是填充问题,解决方法是在结构中添加一些字段,但在这里我必须删除一个字段
  • 请通过editing 在您的问题中添加补充信息。尝试#pragma pack(1) 并阅读this
  • 这完全有效...谢谢!一般来说,我理解填充,但我不理解这种特殊情况,填充通常会添加“空”字节,所以快速的解决方案是将模型字段添加到结构中,但在这里我必须删除一个......无论如何,再次感谢您的帮助!
  • 如果你有一个带填充的结构,并且以不考虑填充的方式将数据读入其中,那么数据将更早移动。例如,假设您有一个包含 char、short 和 char 的结构。您认为那是 4 个字节,然后您将 4 个字节 a、b、c、d 读入其中。您希望 d 将在最终字符中,但由于 b 进入填充字节,c 和 d 进入短字节。

标签: c++ c++11 directx directx-11 tga


【解决方案1】:

这是一个填充问题。在 Visual Studio 中,您可以使用 #pragma pack(1) 编译器指令禁用任何结构填充。

演示

#include<stdio.h>
#include<windows.h>

// Default packing of structure with padding

typedef struct {
  CHAR  idlength;
  CHAR  colourmaptype;
  CHAR  datatypecode;
  WORD colourmaporigin;
  WORD colourmaplength;
  CHAR  colourmapdepth;
  WORD x_origin;
  WORD y_origin;
  WORD width;
  WORD height;
  CHAR  bitsperpixel;
  CHAR  imagedescriptor;
} TGAHEADER;


#pragma pack(1) // structure fields are aligned to byte boundary (no padding)

typedef struct {
  CHAR  idlength;
  CHAR  colourmaptype;
  CHAR  datatypecode;
  WORD colourmaporigin;
  WORD colourmaplength;
  CHAR  colourmapdepth;
  WORD x_origin;
  WORD y_origin;
  WORD width;
  WORD height;
  CHAR  bitsperpixel;
  CHAR  imagedescriptor;
} TGAHEADER_PACKED;

int main()
{
  printf("Offset of field bitsperpixel in TGAHEADER structure %d\n", offsetof(TGAHEADER, bitsperpixel));
  printf("Offset of field bitsperpixel in packed TGAHEADER structure %d\n", offsetof(TGAHEADER_PACKED, bitsperpixel));
}

输出:

Offset of field bitsperpixel in TGAHEADER structure 18
Offset of field bitsperpixel in packed TGAHEADER structure 16

【讨论】:

  • 只是一个commen,使用#pragma pack(1) 可能是有风险的,在我的项目中它会导致一些奇怪的地方崩溃。更好的解决方案是用#pragma pack(push,1) 和#pragma pack(pop) 覆盖你不想填充的结构
  • @BartoszBoczula 好点,请随时改进我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-29
  • 2016-08-05
相关资源
最近更新 更多