📄 jpegencoder.c
字号:
[in] *nrcodes: 指向输入缓冲区的指针
[in] *std_table: 指向输入缓冲区的指针
[in, out] *HT: 指向输入、输出缓冲区的指针
output:
None
*/
/*
static void writebits(bitstring bs)
{
SBYTE posval; //bit position in the bitstring we read, should be <= 15 and >= 0
WORD value; //AC or DC value
posval = bs.length - 1;
value = bs.value;
#ifdef WRITE_BITS_DEBUG
write_bits_buf[bs.length]++;
#endif
//static WORD Mask[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
while (posval >= 0)
{
#ifdef WRITEBITS_DEBUG
if (value & Mask[posval])
{
bytenew |= Mask[bytepos];
}
#else
if (value & (1 << posval))
{
bytenew |= (1 << bytepos);
}
#endif
posval--;
bytepos--;
if (bytepos < 0)
{
if (bytenew == 0XFF)
{
writebyte(0XFF);
writebyte(0);
}
else
{
writebyte(bytenew);
}
bytepos = 7;
bytenew = 0;
}
}
}
*/
static void subwrite(WORD pos, WORD val)
{
WORD posval = pos;
WORD value = val;
//value = value & ((1 << posval) - 1);
subwritebits_begin:
if(posval < bytepos)
{
bytenew += (value << (bytepos - posval));
bytepos -= posval;
}
else
{
bytenew += (value >> (posval - bytepos));
posval -= bytepos;
if (bytenew == 0XFF)
{
writebyte(0XFF);
writebyte(0);
}
else
{
writebyte(bytenew);
}
bytepos = 8;
bytenew = 0;
if (posval != 0)
//subwrite(posval, value);
goto subwritebits_begin;
}
}
DWORD writebits_cycles = 0;
static void writebits(bitstring bs)
{
#if 1
if((bs.length + bytepos) < 7)
writebits_cycles += 25;
else if(((bs.length + bytepos) > 7) && ((bs.length + bytepos) < 15))
writebits_cycles += 52;
else
writebits_cycles += 79;
#endif
//bs.value = bs.value & ((1 << bs.length) - 1);
subwrite(bs.length, bs.value);
}
/*
function:
compute huffman(DC, AC) table
DC: luminance and chrominance
差值位数 编码位数 huffman编码
HT[x]的x值 HT[x].length HT[x].value
AC: luminance and chrominance
Run Size Code length Code word
HT[x]的x值 HT[x].length HT[x].value
input:
[in] *nrcodes: 指向输入缓冲区的指针
[in] *std_table: 指向输入缓冲区的指针
[in, out] *HT: 指向输入、输出缓冲区的指针
output:
None
*/
static void compute_Huffman_table(BYTE *nrcodes, BYTE *std_table, bitstring *HT)
{
BYTE k, j;
BYTE pos_in_table = 0;
WORD codevalue = 0;
for (k = 1; k <= 16; k++)
{
for (j = 1; j <= nrcodes[k]; j++)
{
HT[std_table[pos_in_table]].value = codevalue;
HT[std_table[pos_in_table]].length = k;
//printf("%x %d %d\n", std_table[pos_in_table], k, codevalue);
pos_in_table++;
codevalue++;
}
//codevalue *= 2;
codevalue <<= 1;
}
}
void init_Huffman_tables(void)
{
compute_Huffman_table(std_dc_luminance_nrcodes, std_dc_luminance_values, dc_luminance_ht);
compute_Huffman_table(std_dc_chrominance_nrcodes, std_dc_chrominance_values, dc_chrominance_ht);
compute_Huffman_table(std_ac_luminance_nrcodes, std_ac_luminance_values, ac_luminance_ht);
compute_Huffman_table(std_ac_chrominance_nrcodes, std_ac_chrominance_values, ac_chrominance_ht);
}
void exitmessage(char *error_message)
{
printf("%s\n", error_message);
//exit(EXIT_FAILURE);
}
/*
function:
Huffman编码器可以使用查表方法进行编码。压缩数据符号时,Huffman编码器对出现频率比较高的符号分配比较
短的代码,而对出现频率比较高的符号分配比较长的代码。这种可变长度的Huffman表可以事先定义。
编码时,每个矩阵数据的DC值与63个AC值,将分别使用不同的Huffman编码器,而亮度和色度也需要不同的Huffman
编码器,所以一共需要四个编码表,才能顺利完成JPEG编码工作。
DC,建立所需位数与差值内容的对照表。
AC, 建立AC系数范围与AC所需位数对照表。
input:
None
output:
None
*/
//static void set_numbers_category_and_bitcode(void)
//{
// SDWORD nr;
// SDWORD nrlower, nrupper;
// BYTE cat;
//allow negative subscripts;
//pCategory = CategoryBuffer + JPEGENCODER_BITCODE_LENGEH;
//allow negative subscripts;
//pBitcode = BitcodeBuffer + JPEGENCODER_BITCODE_LENGEH;
// nrlower = 1;
// nrupper = 2;
// for (cat = 1; cat <= 11; cat++) //7, 8, ok
// {
//Positive numbers
// for (nr = nrlower; nr <= (nrupper - 1); nr++)
// {
//DC,建立所需位数与差值内容的对照表
//pCategory[nr] = cat;
//AC, AC系数范围与AC所需位数对照表
//pBitcode[nr].length = cat; //AC系数所需的位数(SSSS组)
//pBitcode[nr].value = (WORD)nr;//实际保存值
// }
//Negative numbers
// for (nr = -(nrupper - 1); nr <= -nrlower; nr++)
// {
//DC,建立所需位数与差值内容的对照表
//pCategory[nr] = cat;
//AC, AC系数范围与AC所需位数对照表
//pBitcode[nr].length = cat; //AC系数所需的位数(SSSS组)
//pBitcode[nr].value = (WORD)(nrupper - 1 + nr); //实际保存值
// }
// nrlower <<= 1;
// nrupper <<= 1;
// }
//}
//此处把浮点数据转换为定点数据,先把每个数据<< 14或 << 4或 << 18, 然后,在把运算结果>>18
//定点数据最大值为((153887 * 255) >> 18) = 149.
//定点数据最小值为((-109749 * 255) >> 18) = -106.
//所以用2Bytes即可表示需要的数据
//此处把浮点数据转换为定点数据,先把每个数据<< 14或 << 4或 << 18, 然后,在把运算结果>>18
//定点数据最大值为((153887 * 255) >> 18) = 149.
//定点数据最小值为((-109749 * 255) >> 18) = -106.
//所以用2Bytes即可表示需要的数据
#define JPEGENCODER_Y_R 78389 //YR, 16384 * 0.299 * 16 + 0.5 * 16 = 78389.056000
#define JPEGENCODER_CB_R -44226 //CbR, 16384 * -0.16874 * 16 + 0.5 * 16 = -44226.178560
#define JPEGENCODER_CR_R 131072 //CrR, 16384 / 2 * 16 = 131072
#define JPEGENCODER_Y_G 153887 //YG, 16384 * 0.587 * 16 + 0.5 * 16 = 153886.528000
#define JPEGENCODER_CB_G -86830 //CbG, 16384 * -0.33126 * 16 + 0.5 * 16 = -86829.821440
#define JPEGENCODER_CR_G -109749 //CrG, 16384 * -0.41869 * 16 + 0.5 * 16 = -109749.071360
#define JPEGENCODER_Y_B 29892 //YB, 16384 * 0.114 * 16 + 0.5 * 16 = 29892.416000
#define JPEGENCODER_CB_B 131072 //CbB, 16384 / 2 * 16 = 131072
#define JPEGENCODER_CR_B -21307 //CrB, 16384 * -0.08131 * 16 + 0.5 * 16 = -21306.928640
#define JPEGENCODER_Y_CB_CR_SHIFT 18
/*
function:
Precalculated tables for a faster YCbCr->RGB transformation
RGB->YCbCr颜色模式转换格式
Y = 0.2990R + 0.5870G + 0.1140B
Cb = -0.1687R - 0.3313G + 0.5000B + 128
Cr = 0.5000R -0.4187G -0.0813B + 128
input:
None
output:
None
*/
static void precalculate_YCbCr_tables(void)
{
WORD i;
for (i = 0; i <= 255; i++)
{
//R
YRtab[i] = (BYTE)((JPEGENCODER_Y_R * i) >> JPEGENCODER_Y_CB_CR_SHIFT);
CbRtab[i] = (SBYTE)((JPEGENCODER_CB_R * i) >> JPEGENCODER_Y_CB_CR_SHIFT);
CrRtab[i] = (BYTE)((JPEGENCODER_CR_R * i) >> JPEGENCODER_Y_CB_CR_SHIFT);
//G
YGtab[i] = (BYTE)((JPEGENCODER_Y_G * i) >> JPEGENCODER_Y_CB_CR_SHIFT);
CbGtab[i] = (SBYTE)((JPEGENCODER_CB_G * i) >> JPEGENCODER_Y_CB_CR_SHIFT);
CrGtab[i] = (SBYTE)((JPEGENCODER_CR_G * i) >> JPEGENCODER_Y_CB_CR_SHIFT);
//B
YBtab[i] = (BYTE)((JPEGENCODER_Y_B * i) >> JPEGENCODER_Y_CB_CR_SHIFT);
CbBtab[i] = (BYTE)((JPEGENCODER_CB_B * i) >> JPEGENCODER_Y_CB_CR_SHIFT);
CrBtab[i] = (SBYTE)((JPEGENCODER_CR_B * i) >> JPEGENCODER_Y_CB_CR_SHIFT);
}
}
// Using a bit modified form of the FDCT routine from IJG's C source:
// Forward DCT routine idea taken from Independent JPEG Group's C source for
// JPEG encoders/decoders
/*
For float AA&N IDCT method, divisors are equal to quantization coefficients
scaled by scalefactor[row]*scalefactor[col], where scalefactor[0] = 1,
scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
We apply a further scale factor of 8. What's actually stored is 1/divisor
so that the inner loop can use a multiplication rather than a division.
*/
/*
function:
经过FDCT运算,获得fdtbl_Y和fdtbl_Cb的值
input:
None
output:
None
*/
#ifdef QUANT_TABLE_DEBUG
static void prepare_quant_tables(void)
{
//double aanscalefactor[8] = {1.0, 1.387039845, 1.306562965, 1.175875602,
// 1.0, 0.785694958, 0.541196100, 0.275899379};
//scalefactor先放大1024(2^10)倍, Q10
WORD aanscalefactor_1[64] = {1024, 1420, 1338, 1204, 1024, 805, 554, 283,
1420, 1970, 1856, 1670, 1420, 1116, 769, 392,
1338, 1856, 1748, 1573, 1338, 1051, 724, 369,
1204, 1670, 1573, 1416, 1204, 946, 652, 332,
1024, 1420, 1338, 1204, 1024, 805, 554, 283,
805, 1116, 1051, 946, 805, 632, 435, 222,
554, 769, 724, 652, 554, 435, 230, 153,
283, 392, 369, 332, 283, 222, 153, 78 };
BYTE row, col;
BYTE i = 0;
//caculate aanscalefactor_1[64]
//i = 0;
//for (row = 0; row < 8; row++)
//{
// for (col = 0; col < 8; col++)
// {
// aanscalefactor_1[i] = (WORD)(aanscalefactor[row] * aanscalefactor[col] * 1024); //1024
// printf("aanscalefactor[%d] = %f\n", i, aanscalefactor[row] * aanscalefactor[col] * 1024);
// i++;
// }
//}
i = 0;
for (row = 0; row < 8; row++)
{
for (col = 0; col < 8; col++)
{
fdtbl_Y[i] = 32768 / (((DWORD)(DQTinfo.Ytable[zigzag[i]] * aanscalefactor_1[i] * 8)) >> 10);
fdtbl_Cb[i] = 32768 /((DWORD)(DQTinfo.Cbtable[zigzag[i]] * aanscalefactor_1[i] * 8) >> 10);
i++;
}
}
//for (i = 0; i <= 7; i++)
// printf("aanscalefactor[%d] = %f\n", i, aanscalefactor[i]);
//for (i = 0; i <= 63; i++)
//{
// printf("fdtbl_Y[%d] = %d ", i, fdtbl_Y[i]);
// printf("fdtbl_Cb[%d] = %d\n", i, fdtbl_Cb[i]);
//}
}
#else
static void prepare_quant_tables(void)
{
//double aanscalefactor[8] = {1.0, 1.387039845, 1.306562965, 1.175875602,
// 1.0, 0.785694958, 0.541196100, 0.275899379};
//scalefactor先放大16384(2^14)倍, Q14
WORD aanscalefactor[8] = {16384, 22725, 21407, 19266,
16384, 12873, 8867, 4520};
BYTE row, col;
BYTE i = 0;
//运算结果(0.001627 - 0.019134) * 1048576,变成WORD类型,then >> 20
for (row = 0; row < 8; row++)
{
for (col = 0; col < 8; col++)
{
//fdtbl_Y[i] = (float)(1.0 / ((double) DQTinfo.Ytable[zigzag[i]] *
// aanscalefactor[row] * aanscalefactor[col] * 8.0));
//fdtbl_Cb[i] = (float)(1.0 / ((double) DQTinfo.Cbtable[zigzag[i]] *
// aanscalefactor[row] * aanscalefactor[col] * 8.0));
//fdtbl_Y[i] = (DQTinfo.Ytable[zigzag[i]] *
// ((aanscalefactor[row] * aanscalefactor[col]) >> 20) * 8) >> 8;
//fdtbl_Cb[i] = (DQTinfo.Cbtable[zigzag[i]] *
// ((aanscalefactor[row] * aanscalefactor[col]) >> 20) * 8) >> 8;
fdtbl_Y[i] = (DQTinfo.Ytable[zigzag[i]] *
((aanscalefactor[row] * aanscalefactor[col]) >> 20) * 8) >> 8;
fdtbl_Cb[i] = (DQTinfo.Cbtable[zigzag[i]] *
((aanscalefactor[row] * aanscalefactor[col]) >> 20) * 8) >> 8;
i++;
}
}
//for (i = 0; i <= 7; i++)
// printf("aanscalefactor[%d] = %f\n", i, aanscalefactor[i]);
//for (i = 0; i <= 63; i++)
//{
// printf("fdtbl_Y[%d] = %d ", i, fdtbl_Y[i]);
// printf("fdtbl_Cb[%d] = %d\n", i, fdtbl_Cb[i]);
//}
}
#endif
/*
function:
使用正向离散余弦变换(forward discrete cosine transform, FDCT),把空间域表示的图像变换成频率域
表示的图,离散余弦变换把8*8的像素矩阵变成8*8的频率矩阵(色彩改变的速度矩阵)。
使用量化表对DCT系数进行量化,量化表是依据人的视觉系统和压缩图像类型的特点进行优化的量化系数矩阵,
虑掉那些总体上对图像不重要的部分,这一步是JPEG的有损压缩,量化矩阵值越高,从图像中丢失的信息越多,压
缩率越高,图像质量越差。在JPEG压缩时可以选择一个量化因子,这个因子的值决定了量化矩阵中的数值。理想的
量化因子要在压缩比和画质间达到平衡,所以对不同的图像要选择不同的量化因子,通常需要多次实验后方可确定。
input:
[in] *data: 指向量化前的数据缓冲区的指针(先处理row, 再处理column, 两者的处理方法一样)
0 1 2 3 4 5 6 7
8 9 10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
[in] *fdtbl: 量化因子
[in, out] *outdata: 指向量化后的数据缓冲区的指针
output:
None
*/
/*
#define IDCT_COEFF_1 11585 //16384 * 0.707106781 = 11585.237500
#define IDCT_COEFF_2 6270 //16384 * 0.382683433 = 6269.885366
#define IDCT_COEFF_3 8867 //16384 * 0.541196100 = 8866.956902
#define IDCT_COEFF_4 21407 //16384 * 1.306562965 = 21406.727619
#define IDCT_SHIFT 14 //2^14 = 16384, Q14
*/
#ifdef FDCT_AND_QUANTILIZATION_DEBUG
#define IDCT_COEFF_1 724 //1024 * 0.707106781
#define IDCT_COEFF_2 392//392 //1024 * 0.382683433
#define IDCT_COEFF_3 512//512//554 //1024 * 0.541196100
#define IDCT_COEFF_4 1338 //1338 //1024 * 1.306562965
#define IDCT_SHIFT 10 //2^14 = 16384, Q10
static void fdct_and_quantization(SWORD *data, WORD *fdtbl, SWORD *outdata)
{
//float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
SWORD tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
//float tmp10, tmp11, tmp12, tmp13;
SWORD tmp10, tmp11, tmp12, tmp13;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -