jpeg压缩源代码阅读笔记
原理:https://www.cnblogs.com/Arvin-JIN/p/9133745.html
1.将图像分为若干个8*8的块
2.对于每个块中的每个值(YCbCr?)转换为整型,并且减去平均值128,再进行DCT运算
// forward DTC
temp = 0.0; for (u = 0; u < 8; u++) for (v = 0; v < 8; v++) { temp = 0.0; for (x = 0; x < 8; x++) for (y = 0; y < 8; y++) temp += (double)inblock[x][y] * cos((2 * x + 1)*u*pi / 16)*cos((2 * y + 1)*v*pi / 16); adct[u][v] = temp * c[u] * c[v] / 4; }
我的优化:
// forward DTC
double temps[8][8]; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { temps[i][j] = cos((2 * i + 1)*j*pi / 16); } } temp = 0.0; for (u = 0; u < 8; u++) for (v = 0; v < 8; v++) { temp = 0.0; for (x = 0; x < 8; x++) for (y = 0; y < 8; y++) temp += (double)inblock[x][y] * temps[x][u] * temps[y][v]; adct[u][v] = temp * c[u] * c[v] / 4; }
3.量化块,将块中每个值除以给定的量化值表中对应的值
//给定的量化值表,可以对其缩放/扩大进行压缩图像质量的控制
int qtbl[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 (u = 0; u < 8; u++){ for (v = 0; v < 8; v++) { temp1 = adct[u][v]; if (temp1 < 0) { temp1 = -temp1; temp1 += qtbl[u][v] / 2; temp2 = (int)temp1 / qtbl[u][v]; aqant[u][v] = -temp2; } else { temp1 += qtbl[u][v] / 2; temp2 = (int)temp1 / qtbl[u][v]; aqant[u][v] = temp2; } }
}
4.将块改为zigzag顺序
short int zigzag[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 }; /* change the 8x8 block to zigzag sequence form ZIGZAG扫描*/ for (u = 0; u < 8; u++) for (v = 0; v < 8; v++) zz[zigzag[u][v]] = aqant[u][v];
5.DC值减去最后一个块的DC之差
/* replace DC value of each block as the difference between curent DC and the DC of last block */ tempdc = zz[0]; zz[0] = zz[0] - last_dc_value; last_dc_value = tempdc;
6.哈夫曼编码
此单元中append_bits方法为输出方法,actbl、dctbl为储存哈夫曼编码的数据结构
6.1处理DC,计算DC的二进制长度,将对应的哈夫曼编码中的值输出,再将DC值输出(为负数时输出补码)
/* encode DC coefficient */ temp = temp2 = zz[0]; if (temp < 0) { temp = -temp; /* temp is the absulate value of input coefficient */ temp2--; /* for negative coefficient, get complement of abs */ } /* find the number of bits needed for the magnitude of the coeffcient */ nbits = 0; while (temp) { nbits++; temp >>= 1; } /* emit the Huffman_coded symbol for the number of bits */ append_bits(dctbl->ehufco[nbits], dctbl->ehufsi[nbits]); /* emit that number of bits of the value for positive coefficient or the complement of its magnitude for negative coefficient */ if (nbits) append_bits((unsigned int)temp2, nbits);
6.2处理AC,转换成中间熵编码,再查询哈夫曼编码输出,再输出AC本身的值(为负数时输出补码)
for (k = 1; k < 64; k++) { if ((temp = zz[k]) == 0) r++; else { /* if run length is greater than 15, emit special code 0xF0 */
//由于位数限制,只能连续记录最多15个0,记为(15,0),输出对应的哈夫曼编码,再继续循环
while (r > 15) { append_bits(actbl->ehufco[0xF0], actbl->ehufsi[0xF0]); r = r - 16; } temp2 = temp; if (temp < 0) { temp = -temp; temp2--; } /* find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* Nonzero AC value is at least 1 bits long */ while (temp >>= 1) nbits++; /* emit Huffman symbol for run length/number of bits */ i = (r << 4) + nbits; append_bits(actbl->ehufco[i], actbl->ehufsi[i]); /* emit that number of bits of the value for positive coefficient or the complement of its magnitude for negative coefficient */ append_bits((unsigned int)temp2, nbits); r = 0; } }
/* if the last coefficients are zero, emit an end-of-block code */
//块末剩下的0统一记为(0,0),输出其对应的哈夫曼编码
if (r > 0) append_bits(actbl->ehufco[0], actbl->ehufsi[0]);

浙公网安备 33010602011771号