Targa运行长度编码

时间:2017-04-07 15:57:55

标签: c++ c++11 compression textures

我目前正在尝试解压缩targa(RGB24_RLE)图像数据。

我的算法如下所示:

static constexpr size_t kPacketHeaderSize = sizeof(char);

        //http://paulbourke.net/dataformats/tga/
        inline void DecompressRLE(unsigned int a_BytePerPixel, std::vector<CrByte>& a_In, std::vector<CrByte>& a_Out)
        {
            for (auto it = a_In.begin(); it != a_In.end();)
            {
                //Read packet header
                int header = *it & 0xFF;
                int count = (header & 0x7F) + 1;

                if ((header & 0x80) != 0) //packet type
                {
                    //For the run length packet, the header is followed by
                    //a single color value, which is assumed to be repeated
                    //the number of times specified in the header.

                    auto paStart = it + kPacketHeaderSize;
                    auto paEnd = paStart + a_BytePerPixel;

                    //Insert packets into output buffer
                    for (size_t pk = 0; pk < count; ++pk)
                    {
                        a_Out.insert(a_Out.end(), paStart, paEnd);
                    }

                    //Jump to next header
                    std::advance(it, kPacketHeaderSize + a_BytePerPixel);
                }
                else
                {
                    //For the raw packet, the header s followed by
                    //the number of color values specified in the header.

                    auto paStart = it + kPacketHeaderSize;
                    auto paEnd = paStart + count * a_BytePerPixel;

                    //Insert packets into output buffer
                    a_Out.insert(a_Out.end(), paStart, paEnd);

                    //Jump to next header
                    std::advance(it, kPacketHeaderSize + count * a_BytePerPixel);
                }
            }
        }

在这里被称为:

//Read compressed data
std::vector<CrByte> compressed(imageSize);
ifs.seekg(sizeof(Header), std::ifstream::beg);
ifs.read(reinterpret_cast<char*>(compressed.data()), imageSize);

//Decompress
std::vector<CrByte> decompressed(imageSize);
DecompressRLE(bytePerPixel, compressed, decompressed);

imageSize的定义如下:

size_t imageSize = hd.width * hd.height * bytePerPixel

但是,在DecompressRLE()完成后(使用2048x2048纹理需要很长时间),解压缩仍为空/仅包含零。也许我错过了一些东西。

count有时似乎过高,我认为这是不正常的。 compressedSize 小于imageSize,否则不会压缩。但是,使用ifstream::tellg()会给我错误的结果。 有什么帮助吗?

1 个答案:

答案 0 :(得分:1)

如果仔细查看调试器中的变量,您会看到std::vector<CrByte> decompressed(imageSize);声明了一个包含imageSize元素的向量。然后在DecompressRLE中插入该向量的末尾,使其生长。这就是为什么你的解压缩图像充满了零,以及为什么它需要这么长时间(因为矢量将定期调整大小)。

您要做的是保留空间:

std::vector<CrByte> decompressed;
decompressed.reserve(imageSize);

您的压缩缓冲区看起来比文件内容大,因此您仍然要解压缩到文件末尾。压缩文件大小应为Header。使用它。