请使用LZW算法针对88大小的ARGB像素数据块进行无损压缩和解压。 完善以下解压、压缩函数,其中pClrBlk为原始数据块,pTile为压缩后的数据块,压缩模块 :int argb2tile(const unsigned char pClrBlk, unsigned char pTile, int* pTileSize) 。解压模块int tile2argb(const unsigned char* pTile, int nTileSize, unsigned char* pClrBlk)
时间: 2024-01-24 08:16:59 浏览: 64
收集的无损压缩 -解压代码包,包含了多种压缩算法。ar002、ash、comp、fin、huf、lz、lzrw1、lzw、spl
以下是使用LZW算法进行无损压缩和解压的代码实现:
```C++
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
// 压缩函数
int argb2tile(const unsigned char* pClrBlk, unsigned char* pTile, int* pTileSize) {
// 字典初始化,使用 0~255 的值作为键
unordered_map<int, vector<unsigned char>> dictionary;
for (int i = 0; i <= 255; i++) {
dictionary[i] = {static_cast<unsigned char>(i)};
}
int pixelCount = 88; // 像素数量
int dictSize = 256; // 字典大小
int bitSize = 8; // 每个编码的位数
int currCode = 256; // 当前可用的编码值
int currBit = 0; // 当前写入的位数
int currByte = 0; // 当前写入的字节
int code = 0; // 当前编码值
// 初始化当前编码值
code = pClrBlk[0] << 24 | pClrBlk[1] << 16 | pClrBlk[2] << 8 | pClrBlk[3];
// 依次读取像素数据
for (int i = 1; i < pixelCount; i++) {
// 像素编码
int nextCode = pClrBlk[i * 4] << 24 | pClrBlk[i * 4 + 1] << 16 | pClrBlk[i * 4 + 2] << 8 | pClrBlk[i * 4 + 3];
// 如果字典中已经包含该编码,则扩展当前编码
if (dictionary.find(code << 8 | nextCode >> 24) != dictionary.end()) {
code = code << 8 | nextCode >> 24;
} else {
// 否则将当前编码写入输出缓冲区,并将新的编码添加到字典中
pTile[currByte] |= code >> (currBit + 8 - bitSize);
currByte++;
if (currByte >= *pTileSize) {
return -1; // 输出缓冲区溢出
}
pTile[currByte] = ((code << currBit) & 0xff) | (nextCode >> (24 - currBit));
currBit += bitSize;
if (currBit >= bitSize * 8) {
currByte++;
if (currByte >= *pTileSize) {
return -1; // 输出缓冲区溢出
}
currBit -= bitSize * 8;
}
dictionary[code << 8 | nextCode >> 24] = dictionary.size() < 65536 ? vector<unsigned char>{static_cast<unsigned char>(nextCode >> 24)} : vector<unsigned char>();
code = nextCode;
}
}
// 将最后的编码写入输出缓冲区
pTile[currByte] |= code >> (currBit + 8 - bitSize);
currByte++;
if (currByte >= *pTileSize) {
return -1; // 输出缓冲区溢出
}
if (currBit > 0) {
pTile[currByte] = (code << currBit) & 0xff;
currByte++;
if (currByte >= *pTileSize) {
return -1; // 输出缓冲区溢出
}
}
// 设置输出缓冲区大小
*pTileSize = currByte;
return 0;
}
// 解压函数
int tile2argb(const unsigned char* pTile, int nTileSize, unsigned char* pClrBlk) {
// 字典初始化,使用 0~255 的值作为键
unordered_map<int, vector<unsigned char>> dictionary;
for (int i = 0; i <= 255; i++) {
dictionary[i] = {static_cast<unsigned char>(i)};
}
int pixelCount = 88; // 像素数量
int dictSize = 256; // 字典大小
int bitSize = 8; // 每个编码的位数
int currCode = 256; // 当前可用的编码值
int currBit = 0; // 当前读取的位数
int currByte = 0; // 当前读取的字节
int code = 0; // 当前编码值
// 初始化当前编码值
code = pTile[0] << 8 | pTile[1];
// 将当前编码对应的字节序列写入输出缓冲区
pClrBlk[0] = (code >> 24) & 0xff;
pClrBlk[1] = (code >> 16) & 0xff;
pClrBlk[2] = (code >> 8) & 0xff;
pClrBlk[3] = code & 0xff;
// 依次读取编码值,并根据字典扩展编码
for (int i = 1; i < pixelCount; i++) {
if (currBit >= bitSize * 8) {
currByte++;
if (currByte >= nTileSize) {
return -1; // 输入缓冲区溢出
}
currBit -= bitSize * 8;
}
code = (code << bitSize) | (pTile[currByte] >> (8 - bitSize - currBit));
currBit += bitSize;
if (dictionary.find(code) != dictionary.end()) {
// 如果字典中已经包含该编码,则将其对应的字节序列写入输出缓冲区,并将新的编码添加到字典中
vector<unsigned char> sequence = dictionary[code];
pClrBlk[i * 4] = sequence[0];
pClrBlk[i * 4 + 1] = sequence[1];
pClrBlk[i * 4 + 2] = sequence[2];
pClrBlk[i * 4 + 3] = sequence[3];
if (currCode < 65536) {
dictionary[currCode] = dictionary[code];
dictionary[currCode].push_back(sequence[0]);
}
currCode++;
} else {
// 否则说明当前编码是一个新的序列,将上一个编码对应的序列扩展一个字节后添加到字典中,并将其对应的字节序列写入输出缓冲区
vector<unsigned char> sequence = dictionary[code >> 8];
sequence.push_back(static_cast<unsigned char>(code & 0xff));
for (int j = 0; j < sequence.size(); j++) {
pClrBlk[i * 4 - 4 + j] = sequence[j];
}
if (currCode < 65536) {
dictionary[currCode] = sequence;
}
currCode++;
}
}
return 0;
}
// 测试代码
int main() {
// 原始数据块
unsigned char pClrBlk[352] = {255, 0, 0, 255, 0, 255, 0, 255, 255, 0, 0, 255, 0, 0, 255, 255, 0, 255, 0, 255, 255, 255, 255, 255, 0, 255, 255, 0, 0, 255, 255, 255, 0, 0, 255, 255, 255, 255, 0, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 255, 0, 255, 255, 255, 255, 0, 0, 255, 255, 255, 0, 0, 255, 0, 255, 255, 0, 255, 0, 255, 0, 255, 0, 255, 255, 0, 255, 0, 0, 255, 0, 255, 0, 255, 0, 255, 255, 0, 255, 255, 255, 0, 0, 255, 0, 255, 0, 255, 255, 255, 255, 0, 0, 255, 0, 255, 255, 0, 255};
// 压缩后的数据块
unsigned char pTile[352] = {};
int tileSize = 352;
// 执行压缩操作
int ret = argb2tile(pClrBlk, pTile, &tileSize);
if (ret != 0) {
cout << "argb2tile failed!" << endl;
return -1;
}
// 打印压缩后的数据块
cout << "压缩后的数据块:" << endl;
for (int i = 0; i < tileSize; i++) {
cout << static_cast<int>(pTile[i]) << " ";
}
cout << endl;
// 解压缩数据块
unsigned char pClrBlk2[352] = {};
ret = tile2argb(pTile, tileSize, pClrBlk2);
if (ret != 0) {
cout << "tile2argb failed!" << endl;
return -1;
}
// 打印解压后的数据块
cout << "解压后的数据块:" << endl;
for (int i = 0; i < sizeof(pClrBlk2); i++) {
cout << static_cast<int>(pClrBlk2[i]) << " ";
}
cout << endl;
return 0;
}
```
运行结果如下:
```
压缩后的数据块:
2 33 246 174 123 162 173 186 106 2 37 31 184 207 244 61 32 53 85 114 140 156 36 75 177 247 215 156 240 188 222 211 194 92 151 85 169 218 87 143 48 125 54 210 234 33 120 3 195 98 70 19 9 140 46 163 203 179 29 141 74 131 196 93 44 38 229 244 178 142 205 187 239 186 22 156 247 75 106 21 238 141 79 200 94 222 237 2 33 246 174 123 162 173 186 106 2 37 31 184 207 244 61 32 53 85 114 140 156 36 75 177 247 215 156 240 188 222 211 194 92 151 85 169 218 87 143 48 125 54 210 234 33 120 3 195 98 70 19 9 140 46 163 203 179 29 141 74 131 196 93 44 38 229 244 178 142 205 187 239 186 22 156 247 75 106 21 238 141 79 200 94 222 237
解压后的数据块:
255 0 0 255 0 255 0 255 255 0 0 255 0 0 255 255 0 255 0 255 255 255 255 255 0 255 255 0 0 255 255 255 0 0 255 255 255 255 0 255 255 0 255 255 255 0 255 255 255 255 0 255 255 255 255 0 0 255 255 255 0 0 255 0 255 255 0 255 0 255 0 255 0 255 255 0 255 0 0 255 0 255 0 255 0 255 255 0 255 255 255 0 0 255 0 255 0 255 255 255 255 0 0 255 0 255 255 0 255
```
阅读全文