gpt4 book ai didi

c++ - 显示 Targa/TGA 的问题

转载 作者:行者123 更新时间:2023-11-30 04:22:01 26 4
gpt4 key购买 nike

我的 Targa 阅读器有非常非常小的问题。一个像素关闭,另外 2 个像素为黑色 :S

我正在加载的 24 位 targa 文件如下所示: enter image description here

请注意左上角的白色像素。左上角的第一个像素是白色的。

但是当我将文件像素保存回 24 位位图时,它看起来像: enter image description here

请注意,白色像素位于右上角,其上方还有 2 个黑色像素。

我这辈子都弄不明白为什么除此之外其他一切都是正确的。这让我很困扰,因为我离加载 TGA 已经很近了。

知道我下面的代码有什么问题吗?我正在为使用 Photoshop 创建的 16、24 和 32 位 TGA 文件编写 TGA 阅读器。

typedef union RGB   //Struct which will hold all pixels.
{
uint32_t Color;
struct
{
unsigned char B, G, R, A;
} RGBA;
} *PRGB;



class Tga //My Targa class that will load the TGA file.
{
private:
std::vector<RGB> Pixels;
uint32_t width, height, size, BitsPerPixel;

public:
Tga(const char* FilePath);
};


Tga::Tga(const char* FilePath)
{
//Open the file for reading..
std::fstream hFile(FilePath, std::ios::in | std::ios::binary);
if (!hFile.is_open()){throw std::invalid_argument("File Not Found.");}

//The header is 12 bytes. By reading it, I can tell if the TGA is compressed or not.

byte Header[12] = {0};
byte DeCompressed[12] = {0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
byte IsCompressed[12] = {0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};


hFile.read(reinterpret_cast<char*>(&Header), sizeof(Header)); //Read the header.

if (memcmp(DeCompressed, &Header, sizeof(Header)) == 0) //If it is not compressed.
{
hFile.read(reinterpret_cast<char*>(&Header), sizeof(Header));

BitsPerPixel = Header[4]; //Displays correctly.
width = Header[1] * 256 + Header[0]; //Displays correctly.
height = Header[3] * 256 + Header[2]; //Displays correctly.
size = ((width * BitsPerPixel + 31) / 32) * 4 * height; //Same algorithm for bitmaps. width * height * 3 OR width * height * 4. Taken from MSDN.

if ((BitsPerPixel != 24) && (BitsPerPixel != 32) && ((width < 1) || (height < 1)))
{
hFile.close();
throw std::logic_error("Error: Invalid TGA File. Width And Height cannot be less than 0. BitsPerPixel must be 24 or 32 bits.");
}

std::vector<unsigned char> ImageData(size); //An array for holding the image data.
hFile.read(reinterpret_cast<char*>(ImageData.data()), size);

unsigned char* BuffPos = ImageData.data();
Pixels.resize(width * height); //A vector holding my structs that will hold the pxiels.


//The following is supposed to flip the Image and copy it into my struct vector.
for (int I = 0; I < height; I++)
{
for (int J = 0; J < width; J++)
{
Pixels[(height - 1 - I) * width + J].RGBA.B = *(BuffPos++);
Pixels[(height - 1 - I) * width + J].RGBA.G = *(BuffPos++);
Pixels[(height - 1 - I) * width + J].RGBA.R = *(BuffPos++);
Pixels[(height - 1 - I) * width + J].RGBA.A = (BitsPerPixel > 24 ? *(BuffPos++) : 0xFF);
}
if(BitsPerPixel == 24) //Has padding?
BuffPos += (4 - ((width * 3) % 4)) % 4;
}
}
else if (memcmp(IsCompressed, &Header, sizeof(Header)) == 0) //The TGA is compressed..
{
hFile.read(reinterpret_cast<char*>(&Header), sizeof(Header));

BitsPerPixel = Header[4];
height = Header[1] * 256 + Header[0];
width = Header[3] * 256 + Header[2];
size = ((width * BitsPerPixel + 31) / 32) * 4 * height;

if ((BitsPerPixel != 24) && (BitsPerPixel != 32) && ((width < 1) || (height < 1)))
{
hFile.close();
throw std::logic_error("Error: Invalid TGA File. Width And Height cannot be less than 0. BitsPerPixel must be 24 or 32 bits.");
}

RGB Pixel = {0};
char* BuffPos = reinterpret_cast<char*>(&Pixel);
int CurrentByte = 0, CurrentPixel = 0;
int BytesPerPixel = (BitsPerPixel / 8);
Pixels.resize(width * height * sizeof(RGB));
do
{
byte ChunkHeader = 0;
hFile.read(reinterpret_cast<char*>(&ChunkHeader), sizeof(byte));
if (ChunkHeader < 128)
{
++ChunkHeader;
for (int I = 0; I < ChunkHeader; ++I)
{
hFile.read(BuffPos, BytesPerPixel);
Pixels[CurrentByte].RGBA.B = Pixel.RGBA.B;
Pixels[CurrentByte].RGBA.G = Pixel.RGBA.G;
Pixels[CurrentByte].RGBA.R = Pixel.RGBA.R;
Pixels[CurrentByte].RGBA.A = (BitsPerPixel > 24) ? Pixel.RGBA.A : 0xFF;
CurrentByte += BytesPerPixel;
++CurrentPixel;
}
}
else
{
ChunkHeader -= 127;
hFile.read(BuffPos, BytesPerPixel);
for (int I = 0; I < ChunkHeader; ++I)
{
Pixels[CurrentByte].RGBA.B = Pixel.RGBA.B;
Pixels[CurrentByte].RGBA.G = Pixel.RGBA.G;
Pixels[CurrentByte].RGBA.R = Pixel.RGBA.R;
Pixels[CurrentByte].RGBA.A = (BitsPerPixel > 24) ? Pixel.RGBA.A : 0xFF;
CurrentByte += BytesPerPixel;
++CurrentPixel;
}
}
} while(CurrentPixel < (width * height));
}
hFile.close();


//I can guarantee nothing is wrong with the bitmap creator.

Bitmap BMP(width, height, 24); //Take the pixels structure and create a 24 bit bitmap. This works 100% of the time for PNG and Bitmap using the same structure.
BMP.Set(Pixels);
BMP.Save("C:/Foo.bmp");
}

int main()
{
Tga F("C:/Foo.tga");
}

最佳答案

我认为您的 header 大小有误。各个位定义如下;断言只是为了确保编译器正确打包结构。

typedef uint8_t byte;

enum class color_map_type : byte {
absent = 0,
present = 1,
};

enum class image_type : byte {
none = 0,
color_mapped = 1,
true_color = 2,
black_white = 3,
rle_color_mapped = 9,
rle_true_color = 10,
rle_black_white = 11,
};

struct color_map_spec {
uint16_t first_entry_index;
uint16_t length;
byte entry_size;
};
static_assert(sizeof(color_map_spec) == 5, "bad size");

struct image_descriptor {
byte alpha : 4;
byte right : 1;
byte top : 1;
byte reserved : 2;
};
static_assert(sizeof(image_descriptor) == 1, "bad size");

struct image_spec {
uint16_t x_origin;
uint16_t y_origin;
uint16_t width;
uint16_t height;
byte depth;
image_descriptor descriptor;
};
static_assert(sizeof(image_spec) == 10, "bad size");

struct header {
byte id_length;
color_map_type color_map_type;
image_type image_type;
color_map_spec color_map_spec;
image_spec image_spec;
};
static_assert(sizeof(header) == 18, "bad size");

struct footer {
uint32_t ext_area_offset;
uint32_t dev_dir_offset;
char signature[16];
char dot_terminator;
char null_terminator;
}

关于c++ - 显示 Targa/TGA 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14025735/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com