📄 jpeg_compress.c
字号:
#include "jcodestruct.h"
#include "jpegstuct.h"
#include "jcfunction.h"
#include "bitstream.h"
#include "tr8x8dct.h"
extern void fdct_int32(short *const block);
//********************************************************************
// 方法名称:ProcessDU
//
// 方法说明:数据处理的最小单位,真正实现了FDCT,QUANTIZATION,HUFFMAN
//
// 参数说明:
// lpBuf:8x8信号输入缓冲
// quantTab:量化表
// dcHuffTab:DC huffman表
// acHuffTab:AC huffman表
// DC:前一数据块的DC值
//********************************************************************
#ifdef 0
void ProcessDU(short* lpBuf,unsigned char* quantTab,HUFFCODE* dcHuffTab,HUFFCODE* acHuffTab,short* DC)
{
unsigned char i = 0;
unsigned int j = 0;
short diffVal = 0; //DC差异值
// unsigned char acLen = 0; //熵编码后AC中间符号的数量
#pragma align 4
short sigBuf[DCTBLOCKSIZE]; //量化后信号缓冲
// ACSYM acSym[DCTBLOCKSIZE]; //AC中间符号缓冲
SYM2 sym2;
HUFFCODE * huff;
// fdct_int32(lpBuf);
_r8x8dct(lpBuf, coeff, temp);
quantize(sigBuf, lpBuf, quantTab);
/*
for (i = 0; i < DCTBLOCKSIZE; i++) //量化操作
{
// sigBuf[FZBT[i]] = (short)( (lpBuf[i] * quantTab[i] + 16384.5) - 16384 );
short temp;
unsigned short qval;
temp = lpBuf[i];
//qval = quantTab[FZBT[i]];
qval = quantTab[i];
// qval <<= 3;
//#ifdef FAST_DIVIDE
//#define DIVIDE_BY(a,b) a /= b
//#else
//#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
//#endif
if (temp < 0) {
temp = -temp;
temp += qval>>1; // for rounding
// DIVIDE_BY(temp, qval);
if(temp > qval)
temp /= qval;
else
temp = 0;
temp = -temp;
} else {
temp += qval>>1; // for rounding
// DIVIDE_BY(temp, qval);
if(temp > qval)
temp /= qval;
else
temp = 0;
}
sigBuf[FZBT[i]] = temp;
}
*/
/* FDCT(lpBuf); //离散余弦变换
for (i = 0; i < DCTBLOCKSIZE; i++) //量化操作
{
sigBuf[FZBT[i]] = (short)( (lpBuf[i] * quantTab[i] + 16384.5) - 16384 );
}
*/
//-----------------------------------------------------
//对DC信号编码,写入文件,DPCM编码
DCComp(sigBuf, DC, dcHuffTab);
/*
diffVal = sigBuf[0] - *DC;
*DC = sigBuf[0];
//搜索Huffman表,写入相应的码字
if (diffVal == 0)
{
huff = &dcHuffTab[0];
WriteBitsStream(huff->code, huff->length); //{0,2,0},写进零长度
}
else
{
huff = &dcHuffTab[pVLITAB[diffVal]];
sym2 = BuildSym2(diffVal);
WriteBitsStream(huff->code, huff->length); //写进长度
WriteBitsStream(sym2.amplitude, sym2.codeLen); //写进幅度
}
*/
RLEComp(sigBuf, acHuffTab);
//-------------------------------------------------------
//对AC信号编码并写入文件
/*
for (i = 63; (i > 0) && (sigBuf[i] == 0); i--) //判断ac信号是否为0
{
//注意,空循环
}
*/
// i = get_nonzero_ac_index(sigBuf);
// if (i == 0) //如果ac信号全为0
// {
// huff = &acHuffTab[0x00];
// WriteBitsStream(huff->code, huff->length); //写入块结束标记
// }
// else
// {
// RLEComp(sigBuf, acHuffTab, i); //对AC进行长度编码
/* for (j = 0; j < acLen; j++) //依次对AC中间符号Huffman编码
{
if (acSym[j].codeLen == 0) //是否有连续16个0
{
huff = &acHuffTab[0xF0];
WriteBitsStream(huff->code, huff->length); //写入块结束标记
}
else
{
huff = &acHuffTab[acSym[j].zeroLen * 16 + acSym[j].codeLen];
WriteBitsStream(huff->code, huff->length); //写入块结束标记
sym2 = BuildSym2(acSym[j].amplitude);
WriteBitsStream(sym2.amplitude, sym2.codeLen); //写进幅度
}
}
*/
// if (i != 63) //如果最后位以0结束就写入EOB
// {
// huff = &acHuffTab[0x00];
// WriteBitsStream(huff->code, huff->length); //写入块结束标记
// }
// }
}
#endif //0
/*
copy8to16(short* d, unsigned char* s, int stride)
{
int i, j;
for(i = 0; i < 8; i++)
{
for(j = 0; j < 8; j++)
{
d[i*8+j] = (short)(s[i*stride+j]-128);
}
}
}
*/
void ProcessData(unsigned char* y,unsigned char* u,unsigned char* v, int w, int h)
{
int i, j, mcux = w>>4, mcuy = h>>4;
#pragma align 4
short d[DCTBLOCKSIZE];
short yDC = 0; //Y信号的当前块的DC
short uDC = 0; //U信号的当前块的DC
short vDC = 0; //V信号的当前块的DC
unsigned char* source;
for(i = 0; i < mcuy; i++)
{
for(j = 0; j < mcux; j++)
{
source = y + w*i*16 + j*16;
pre_fetch(source, w);
copy8to16(d, source, w);
ProcessDU(d, YQT,STD_DC_Y_HT,STD_AC_Y_HT,&yDC);
source += 8;
pre_fetch(source, w);
copy8to16(d, source, w);
ProcessDU(d, YQT,STD_DC_Y_HT,STD_AC_Y_HT,&yDC);
source += -8 + w*8;
pre_fetch(source, w);
copy8to16(d, y + w*(i*16+8) + j*16, w);
ProcessDU(d, YQT,STD_DC_Y_HT,STD_AC_Y_HT,&yDC);
source += 8;
pre_fetch(source, w);
copy8to16(d, y + w*(i*16+8) + j*16 + 8, w);
ProcessDU(d, YQT,STD_DC_Y_HT,STD_AC_Y_HT,&yDC);
source = u + (w>>1)*i*8 + j*8;
pre_fetch(source, w>>1);
copy8to16(d, source, (w>>1));
ProcessDU(d, UVQT,STD_DC_UV_HT,STD_AC_UV_HT,&uDC);
source += v - u;
pre_fetch(source, w>>1);
copy8to16(d, source, (w>>1));
ProcessDU(d, UVQT,STD_DC_UV_HT,STD_AC_UV_HT,&vDC);
}
}
}
int jpeg_compress(unsigned char* image, unsigned char* code_stream, int w, int h, int Q)
{
unsigned char *y, *u, *v;
bitstream_init(code_stream);
y = image;
u = y + w*h;
v = u + w*h/4;
SetQuantTable(std_Y_QT,YQT, Q); // 设置Y量化表
SetQuantTable(std_UV_QT,UVQT, Q); // 设置UV量化表
pVLITAB=VLI_TAB + 2047; // 设置VLI_TAB的别名
BuildVLITable(); // 计算VLI表
// 写入文件标记结构
WriteSOI();
WriteAPP0();
WriteDQT();
WriteSOF(w, h);
WriteDHT();
WriteSOS();
// 计算Y/UV信号的交直分量的huffman表,这里使用标准的huffman表,并不是计算得出,缺点是文件略长,但是速度快
BuildSTDHuffTab(STD_DC_Y_NRCODES,STD_DC_Y_VALUES,STD_DC_Y_HT);
BuildSTDHuffTab(STD_AC_Y_NRCODES,STD_AC_Y_VALUES,STD_AC_Y_HT);
BuildSTDHuffTab(STD_DC_UV_NRCODES,STD_DC_UV_VALUES,STD_DC_UV_HT);
BuildSTDHuffTab(STD_AC_UV_NRCODES,STD_AC_UV_VALUES,STD_AC_UV_HT);
ProcessData(y, u, v, w, h); // 处理单元数据
bitstream_pad2byte();
WriteEOI();
return bitstream_getlen();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -