jpeg图像压缩c++代码
时间: 2023-12-09 09:02:23 浏览: 204
JPEG 图像压缩C++实现
4星 · 用户满意度95%
以下是一个使用C++实现的JPEG图像压缩的代码示例:
```cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;
// 定义常量
const int BLOCK_SIZE = 8;
const int Q[8][8] = {
{16, 11, 10, 16, 24, 40, 51, 61},
{12, 12, 14, 19, 26, 58, 60, 55},
{14, 13, 16, 24, 40, 57, 69, 56},
{14, 17, 22, 29, 51, 87, 80, 62},
{18, 22, 37, 56, 68, 109, 103, 77},
{24, 35, 55, 64, 81, 104, 113, 92},
{49, 64, 78, 87, 103, 121, 120, 101},
{72, 92, 95, 98, 112, 100, 103, 99}
};
// 定义结构体
struct RGB {
int r, g, b;
};
struct YCbCr {
double y, cb, cr;
};
// 定义函数
vector<vector<RGB>> readBmp(string filename, int &width, int &height);
void writeBmp(string filename, vector<vector<RGB>> &bmpData);
vector<vector<YCbCr>> rgb2ycbcr(vector<vector<RGB>> &rgbData);
vector<vector<YCbCr>> dct(vector<vector<YCbCr>> &ycbcrData);
vector<vector<YCbCr>> quantize(vector<vector<YCbCr>> &dctData);
vector<vector<int>> zigzag(vector<vector<YCbCr>> &quantizeData);
vector<int> rle(vector<vector<int>> &zigzagData);
vector<int> huffman(vector<int> &rleData);
vector<int> compress(vector<vector<RGB>> &bmpData, int width, int height);
vector<vector<RGB>> decompress(vector<int> &compressedData, int width, int height);
vector<vector<YCbCr>> dehuffman(vector<int> &huffmanData);
vector<vector<int>> dezigzag(vector<int> &zigzagData);
vector<vector<YCbCr>> dequantize(vector<vector<int>> &zigzagData);
vector<vector<YCbCr>> idct(vector<vector<YCbCr>> &dctData);
vector<vector<RGB>> ycbcr2rgb(vector<vector<YCbCr>> &ycbcrData);
int main() {
// 读取bmp文件
int width, height;
vector<vector<RGB>> bmpData = readBmp("test.bmp", width, height);
// 压缩
vector<int> compressedData = compress(bmpData, width, height);
// 解压缩
vector<vector<RGB>> decompressedData = decompress(compressedData, width, height);
// 写入bmp文件
writeBmp("test_compressed.bmp", decompressedData);
return 0;
}
// 读取bmp文件
vector<vector<RGB>> readBmp(string filename, int &width, int &height) {
vector<vector<RGB>> bmpData;
ifstream file(filename, ios::binary);
if (!file) {
cout << "Error: cannot open file " << filename << endl;
return bmpData;
}
// 读取bmp文件头
char header[54];
file.read(header, 54);
// 获取图像宽度和高度
width = *(int*)&header[18];
height = *(int*)&header[22];
// 计算每行像素所占字节数
int rowSize = (width * 3 + 3) / 4 * 4;
// 读取像素数据
for (int i = 0; i < height; i++) {
vector<RGB> row;
for (int j = 0; j < width; j++) {
RGB pixel;
file.read((char*)&pixel, 3);
row.push_back(pixel);
}
// 跳过每行末尾的填充字节
file.seekg(rowSize - width * 3, ios::cur);
bmpData.push_back(row);
}
file.close();
return bmpData;
}
// 写入bmp文件
void writeBmp(string filename, vector<vector<RGB>> &bmpData) {
int width = bmpData[0].size();
int height = bmpData.size();
// 计算每行像素所占字节数
int rowSize = (width * 3 + 3) / 4 * 4;
// 计算文件大小
int fileSize = 54 + rowSize * height;
// 写入bmp文件头
char header[54] = {
0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
54, 0, 0, 0, 40, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
24, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
*(int*)&header[2] = fileSize;
*(int*)&header[18] = width;
*(int*)&header[22] = height;
*(int*)&header[34] = rowSize * height;
ofstream file(filename, ios::binary);
if (!file) {
cout << "Error: cannot open file " << filename << endl;
return;
}
file.write(header, 54);
// 写入像素数据
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
file.write((char*)&bmpData[i][j], 3);
}
// 写入每行末尾的填充字节
char padding[4] = {0, 0, 0, 0};
file.write(padding, rowSize - width * 3);
}
file.close();
}
// RGB转YCbCr
vector<vector<YCbCr>> rgb2ycbcr(vector<vector<RGB>> &rgbData) {
vector<vector<YCbCr>> ycbcrData;
for (int i = 0; i < rgbData.size(); i++) {
vector<YCbCr> row;
for (int j = 0; j < rgbData[i].size(); j++) {
YCbCr pixel;
pixel.y = 0.299 * rgbData[i][j].r + 0.587 * rgbData[i][j].g + 0.114 * rgbData[i][j].b;
pixel.cb = -0.1687 * rgbData[i][j].r - 0.3313 * rgbData[i][j].g + 0.5 * rgbData[i][j].b + 128;
pixel.cr = 0.5 * rgbData[i][j].r - 0.4187 * rgbData[i][j].g - 0.0813 * rgbData[i][j].b + 128;
row.push_back(pixel);
}
ycbcrData.push_back(row);
}
return ycbcrData;
}
// DCT变换
vector<vector<YCbCr>> dct(vector<vector<YCbCr>> &ycbcrData) {
vector<vector<YCbCr>> dctData;
for (int i = 0; i < ycbcrData.size(); i += BLOCK_SIZE) {
vector<YCbCr> row;
for (int j = 0; j < ycbcrData[i].size(); j += BLOCK_SIZE) {
vector<vector<double>> block(BLOCK_SIZE, vector<double>(BLOCK_SIZE));
for (int u = 0; u < BLOCK_SIZE; u++) {
for (int v = 0; v < BLOCK_SIZE; v++) {
double sum = 0;
for (int x = 0; x < BLOCK_SIZE; x++) {
for (int y = 0; y < BLOCK_SIZE; y++) {
sum += cos((2 * x + 1) * u * M_PI / 16) * cos((2 * y + 1) * v * M_PI / 16) * ycbcrData[i + x][j + y].y;
}
}
if (u == 0 && v == 0) {
block[u][v] = sum / 8;
} else if (u == 0 || v == 0) {
block[u][v] = sum * sqrt(2) / 8;
} else {
block[u][v] = sum / 4;
}
}
}
row.push_back({block[0][0], block[0][1], block[0][2], block[0][3], block[1][0], block[1][1], block[1][2], block[1][3], block[2][0], block[2][1], block[2][2], block[2][3], block[3][0], block[3][1], block[3][2], block[3][3]});
}
dctData.push_back(row);
}
return dctData;
}
// 量化
vector<vector<YCbCr>> quantize(vector<vector<YCbCr>> &dctData) {
vector<vector<YCbCr>> quantizeData;
for (int i = 0; i < dctData.size(); i++) {
vector<YCbCr> row;
for (int j = 0; j < dctData[i].size(); j++) {
YCbCr pixel;
pixel.y = round(dctData[i][j].y / Q[i % BLOCK_SIZE][j % BLOCK_SIZE]);
pixel.cb = round(dctData[i][j].cb / Q[i % BLOCK_SIZE][j % BLOCK_SIZE]);
pixel.cr = round(dctData[i][j].cr / Q[i % BLOCK_SIZE][j % BLOCK_SIZE]);
row.push_back(pixel);
}
quantizeData.push_back(row);
}
return quantizeData;
}
// Zigzag扫描
vector<vector<int>> zigzag(vector<vector<YCbCr>> &quantizeData) {
vector<vector<int>> zigzagData;
for (int i = 0; i < quantizeData.size(); i++) {
vector<int> row;
for (int j = 0; j < quantizeData[i].size(); j++) {
row.push_back(quantizeData[i][j].y);
row.push_back(quantizeData[i][j].cb);
row.push_back(quantizeData[i][j].cr);
}
zigzagData.push_back(row);
}
return zigzagData;
}
// RLE编码
vector<int> rle(vector<vector<int>> &zigzagData) {
vector<int> rleData;
for (int i = 0; i < zigzagData.size(); i++) {
int count = 0;
for (int j = 0; j < zigzagData[i].size(); j++) {
if (zigzagData[i][j] == 0) {
count++;
} else {
rleData.push_back(count);
rleData.push_back(zigzagData[i][j]);
count = 0;
}
}
rleData.push_back(count);
rleData.push_back(0);
}
return rleData;
}
// Huffman编码
vector<int> huffman(vector<int> &rleData) {
vector<int> huffmanData;
// TODO: Huffman编码
return huffmanData;
}
// 压缩
vector<int> compress(vector<vector<RGB>> &bmpData, int width, int height) {
vector<vector<YCbCr>> ycbcrData = rgb2ycbcr(bmpData);
vector<vector<YCbCr>> dctData = dct(ycbcrData);
vector<vector<YCbCr>> quantizeData = quantize(dctData);
vector<vector<int>> zigzagData = zigzag(quantizeData);
vector<int> rleData = rle(zigzagData);
vector<int> huffmanData = huffman(rleData);
return huffmanData;
}
// 解压缩
vector<vector<RGB>> decompress(vector<int> &compressedData, int width, int height) {
vector<int> huffmanData = compressedData;
vector<int> rleData = huffmanData;
vector<vector<int>> zigzagData = dezigzag(rleData);
vector<vector<YCbCr>> quantizeData = dequantize(zigzagData);
vector<vector<YCbCr>> dctData = idct(quantizeData);
vector<vector<RGB>> rgbData = ycbcr2rgb(dctData);
return rgbData;
}
// Huffman解码
vector<vector<YCbCr>> dehuffman(vector<int> &huffmanData) {
vector<vector<YCbCr>> quantizeData;
// TODO: Huffman解码
return quantizeData;
}
// Zigzag逆扫
阅读全文