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]);

 

posted @ 2019-12-12 12:09  Gyzarus  阅读(304)  评论(0)    收藏  举报