纯手写,jpeg压缩流程上传到资源资源下载
#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include
#include
#include
#include
#include
#include
using namespace std;
int getArange(int a){//获得VLC映射
if (a < 0) a = -1 * a;
int b = 1;
while (pow(2, b) < a) {
b++;
}
return b;
}
//计算一个正数的二进制字符串
string toBinary(int a) {
string str = "";
vector seq;
while (a != 0) {
seq.push_back(a % 2);
a /= 2;
}
for (int i = seq.size() - 1; i >= 0; i--) {
str += seq[i] + '0';
}
if (str == "") str = "0";
return str;
}
//计算一个负数的VLI码
string getVLI(int a) {
string str = "";
vector seq;
a = -1 * a;
while (a != 0) {
int q = a % 2;
if (q == 1) q = 0;
else q = 1;
seq.push_back(q);
a /= 2;
}
for (int i = seq.size() - 1; i >= 0; i--) {
str += seq[i] + '0';
}
return str;
}
struct code { //熵编码的结构
string ssss;
string diff;
code(string ss, string dif) {
ssss = ss;
diff = dif;
}
};
struct midsyn { //cd 的中间符号(sssrrr,ac)
int a, b, c;
midsyn(int a1, int a2, int a3) {
a = a1;
b = a2;
c = a3;
}
};
class code_block
{
public:
vector vc;
code_block() { //默认构造方法
}
private:
};
//定义8x8 的图像块类
class pixel_block
{
public:
double matrix[8][8];
pixel_block() { //默认构造方法
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++) {
matrix[i][j] = 0.0;
}
}
//正向离散余弦变换
double dct(int u, int v) {
double re_value=0;
if (u == 0 && v == 0) {
double result = 0;
double cv = 1 / sqrt(2);
for(int i=0;i<8;i++)
for (int j = 0; j < 8; j++) {
result += matrix[i][j];
}
re_value = 1.0 / 4.0 * cv * cv * result;
}
else {
double result = 0;
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++) {
result += matrix[i][j]*cos((2*i+1)*u*M_PI/16)* cos((2 * j + 1) * v * M_PI / 16.0);
}
re_value = 1.0 / 4.0 * result;
}
return re_value;
}
private:
};
int main()
{
FILE* file = fopen("d03.data", "rb");
int h, w;
fread(&h, sizeof(int), 1, file); // 高度
fread(&w, sizeof(int), 1, file); // 宽度
unsigned char* pixels = new unsigned char[h * w];
fread(pixels, sizeof(unsigned char), h * w, file);
fclose(file);
int width = w / 8;//8x8 像素矩阵的一行块数
int height = h / 8; // 8x8 像素矩阵的一列块数
//cout << width << " " << height;
//8x8像素块的划分
vector> blocks;
vector temp(width);
blocks.resize(height, temp);
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
double value = pixels[i*w + j];
blocks[i / 8][j / 8].matrix[i % 8][j % 8] = value;
}
}
//FDCT的结果矩阵
vector> DCT;
vector temp1(width);
DCT.resize(height, temp1);
//FDCT 正向离散余弦变换
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
//blocks[i][j] 8x8像素
for (int u = 0; u < 8; u++) {
for (int v = 0; v < 8; v++) {
DCT[i][j].matrix[u][v] = blocks[i][j].dct(u, v);
}
}
}
}
//量化
//对经过FDCT变换后的频率系数进行量化
//目的:降低非0系数的幅度,增加0值系数的数目
//定义量化表
int quantity[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} };
//量化操作
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
//DCT[i][j] 8x8像素
for (int u = 0; u < 8; u++) {
for (int v = 0; v < 8; v++) {
//cout << DCT[i][j].matrix[u][v] << " ";
//cout << DCT[i][j].matrix[u][v] / quantity[u][v] << " ";
DCT[i][j].matrix[u][v] = round(DCT[i][j].matrix[u][v]/quantity[u][v]);
//if(u==0&&v==0)
//cout << DCT[i][j].matrix[u][v]<<" "; //输出dc系数
}
}
}
}
//熵编码
vector> entropy;
vector temp2(width);
entropy.resize(height, temp2);
/// 对 dc系数的 dpcm编码
for (int i = 0; i < height; i++) {
for (int j = 1; j < width; j++) {
//DCT[i][j] 8x8像素
DCT[i][j].matrix[0][0] = DCT[i][j].matrix[0][0] - DCT[i][j - 1].matrix[0][0];
}
}
//霍夫曼映射表
string huffman[12] = { "00","010","011","100","101","110","1110","11110","111110","1111110","11111110","111111110" };
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
string sss = huffman[getArange(DCT[i][j].matrix[0][0])];
string diff;
//DCT[i][j] 8x8像素
if (DCT[i][j].matrix[0][0] >= 0)
diff = toBinary(DCT[i][j].matrix[0][0]);
else
diff = getVLI(DCT[i][j].matrix[0][0]);
code c(sss, diff);
entropy[i][j].vc.push_back(c);
//cout << diff << endl << sss << endl;
}
}
//ac系数的编码 游程长度编码
//(RLE)
//生成中间符号
//亮度ac编码表
string AcHuff[16][11] =
{ {"1010","00","01","100","1011","11010","1111000","11111000","1111110110","1111111110000010","1111111110000011" }
,{"1100","11011","1111001","111110110","11111110110","1111111110000100","1111111110000101","1111111110000110","1111111110000111","1111111110001000"}
,{"11100","11111001","1111110111","1111111110001001","1111111110001010","1111111110001011","1111111110001100","1111111110001101","1111111110001110"}
,{"111010","111110111","111111110101","1111111110001111","1111111110010000","1111111110010001","1111111110010010","1111111110010011","1111111110010100","1111111110010101"}
,{"111011","1111111000","1111111110010110","1111111110010111","1111111110011000","1111111110011001","1111111110011010","1111111110011011","1111111110011100","1111111110011101"}
,{"1111010","11111110111","1111111110011110","1111111110011111","1111111110100000","1111111110100001","1111111110100010","1111111110100011","1111111110100100","1111111110100101"}
,{"1111011","111111110110","1111111110100110","1111111110100111","1111111110101000","1111111110101001","1111111110101010","1111111110101011","1111111110101100","1111111110101101"}
,{"11111010","111111110111","1111111110101110","1111111110101111","11111111101100000","1111111110110001","1111111110110010","1111111110110011","1111111110110100","1111111110110101"}
,{"111111000","111111111000000","1111111110110110","1111111110110111","1111111110111000","1111111110111001","1111111110111010","1111111110111011","1111111110111100","1111111110111101"}
,{"111111001","1111111110111110","1111111110111111","1111111111000000","1111111111000001","1111111111000010","1111111111000011","1111111111000100","1111111111000101","1111111111000110"}
,{"111111010","1111111111000111","1111111111001000","1111111111001001","1111111111001010","1111111111001011","1111111111001100","1111111111001101","1111111111001110","1111111111001111"}
,{"1111111001","1111111111010000","1111111111010001","1111111111010010","1111111111010011","1111111111010100","1111111111010101","1111111111010110","1111111111010111","1111111111011000"}
,{"1111111010","1111111111011001","1111111111011010","1111111111011011","1111111111011100","1111111111011101","1111111111011110","1111111111011111","1111111111100000","1111111111100001"}
,{"11111111000","1111111111100010","1111111111100011","1111111111100100","1111111111100101","1111111111100110","1111111111100111","1111111111101000","1111111111101001","1111111111101010"}
,{"1111111111101011","1111111111101100","1111111111101101","1111111111101110","1111111111101111","1111111111110000","1111111111110001","1111111111110010","1111111111110011","1111111111110100"}
,{"11111111001","1111111111110101","1111111111110110","1111111111110111","1111111111111000","1111111111111001","1111111111111010","1111111111111011","1111111111111100","1111111111111101","1111111111111110"}
};
//z字行编排
int zseq[8][8] = { {0,1,5,6,14,15,27,28}
,{2,4,7,13,16,26,29,42}
,{3,8,12,17,25,30,41,43}
,{9,11,18,24,31,40,44,53}
,{10,19,23,32,39,45,52,54}
,{20,22,33,38,46,51,55,60}
,{21,34,37,47,50,56,59,61}
,{35,36,48,49,57,58,62,63} };
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
//计算出一个 [1,64] 的列表
int zlist[64];
for (int i = 0; i < 64; i++) zlist[i] = 0;
//DCT[i][j] 8x8像素
for (int u = 0; u < 8; u++) {
for (int v = 0; v < 8; v++) {
zlist[zseq[u][v]] = DCT[i][j].matrix[u][v];
}
}
//根据zlist 计算熵编码
int zeroNum = 0;
vector mid;
for (int y = 0; y < 64; y++) {
if (zlist[y] == 0) {
zeroNum++;
if (zeroNum >= 16) {
midsyn m(zeroNum-1, 0, 0);
mid.push_back(m);
zeroNum = 0;
}
if (y == 63) {
int length = mid.size() - 1;
while (mid[length].c == 0) {
mid[length].a = 0;
length--;
if (length == -1)break;
}
int ggg = mid.size() ;
//cout << length << " " << ggg-2<= 0)
d = toBinary(mid[p].c);
else
d = getVLI(mid[p].c);
//cout << d << endl;
code c(s, d);
entropy[i][j].vc.push_back(c);
}
// cout << endl << endl;
}
}
ofstream out("entropy.txt");
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
{
for (int u = 0; u < entropy[i][j].vc.size(); u++) {
cout << entropy[i][j].vc[u].ssss << " " << entropy[i][j].vc[u].diff << " ";
out << entropy[i][j].vc[u].ssss << " " << entropy[i][j].vc[u].diff <<" ";
}
}
out << "\n";
cout << endl;
out.close();
return 0;
}