?? jpg.h
字號:
/*************************************************************
Filename: JPG.h.
Writer: Dai Zhiheng.
Time: 2005-5-14.
**************************************************************/
#include "DCT.h"
#include "math.h"
int DCTOrd[64] = //Zig-Zag Order
{
0, 1, 8,16, 9, 2, 3,10,
17,24,32,25,18,11, 4, 5,
12,19,26,33,40,48,41,34,
27,20,13, 6, 7,14,21,28,
35,42,49,56,57,50,43,36,
29,22,15,23,30,37,44,51,
58,59,52,45,38,31,39,46,
53,60,61,54,47,55,62,63
};
double Q[64] = //Q
{
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
};
int DC_size[12] = {0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
int DC_code[12] = {0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0e, 0x1e, 0x3e, 0x7e, 0xfe, 0x3fe};
int AC_size[256] =
{ 4,
2, 2, 3, 4, 5, 7, 8, 10, 16, 16, 0, 0, 0, 0, 0, 0,
4, 5, 7, 9, 11, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
5, 8, 10, 12, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
6, 9, 12, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
6, 10, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
7, 11, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
7, 12, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
8, 12, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
9, 15, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0,
11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0
};
int AC_code[256] =
{
10, //EOB
0, 1, 4, 11, 26, 120, 248, 1014, 65410, 65411, 65535, 65535, 65535, 65535, 65535, 65535,
12, 27, 121, 502, 2038, 65412, 65413, 65414, 65415, 65416, 65535, 65535, 65535, 65535, 65535, 65535,
28, 249, 1015, 4084, 65417, 65418, 65419, 65420, 65421, 65422, 65535, 65535, 65535, 65535, 65535, 65535,
58, 503, 4085, 65423, 65424, 65425, 65426, 65427, 65428, 65429, 65535, 65535, 65535, 65535, 65535, 65535,
59, 1016, 65430, 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65535, 65535, 65535, 65535, 65535, 65535,
122, 2039, 65438, 65439, 65440, 65441, 65442, 65443, 65444, 65445, 65535, 65535, 65535, 65535, 65535, 65535,
123, 4086, 65446, 65447, 65448, 65449, 65450, 65451, 65452, 65453, 65535, 65535, 65535, 65535, 65535, 65535,
250, 4087, 65454, 65455, 65456, 65457, 65458, 65459, 65460, 65461, 65535, 65535, 65535, 65535, 65535, 65535,
504, 32704, 65462, 65463, 65464, 65465, 65466, 65467, 65468, 65469, 65535, 65535, 65535, 65535, 65535, 65535,
505, 65470, 65471, 65472, 65473, 65474, 65475, 65476, 65477, 65478, 65535, 65535, 65535, 65535, 65535, 65535,
506, 65479, 65480, 65481, 65482, 65483, 65484, 65485, 65486, 65487, 65535, 65535, 65535, 65535, 65535, 65535,
1017, 65488, 65489, 65490, 65491, 65492, 65493, 65494, 65495, 65496, 65535, 65535, 65535, 65535, 65535, 65535,
1018, 65497, 65498, 65499, 65500, 65501, 65502, 65503, 65504, 65505, 65535, 65535, 65535, 65535, 65535, 65535,
2040, 65506, 65507, 65508, 65509, 65510, 65511, 65512, 65513, 65514, 65535, 65535, 65535, 65535, 65535, 65535,
65515, 65516, 65517, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65535, 65535, 65535, 65535, 65535,
2041, //ZRL
65525, 65526, 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, 65535, 65535, 65535, 65535, 65535
};
unsigned char SOI[2] =
{
0xff,0xd8
};
unsigned char EOI[2] =
{
0xff,0xd9
};
unsigned char DQT[5] =
{
0xff,0xdb,0x00,0x43,0x03
};//還有64Byte的Q
unsigned char DHT_DC[33] =
{
0xff,0xc4,0x00,0x1f,0x00,
0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b
};
unsigned char DHT_AC[183] =
{
0xff,0xc4,0x00,0xb5,0x11,
0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7d,
0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,
0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,
0x29,0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,
0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,
0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
0xF9,0xFA
};
unsigned char SOS[10] =
{
0xff,0xDA,0x00,0x08,0x01,0x00,0x01,0x00,0x3f,0x00
};
unsigned char APPO[18] =
{
0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,
0x02,0x00,0x00,0x01,0x00,0x01,0x00,0x00
};
unsigned char SOFO[13] =
{
0xff,0xc0,0x00,0x0b,0x08,0x01,0x00,0x01,0x00,0x01,0x00,0x22,0x03
};
/**********************************************************************************
函數(shù)功能:把2維BMP格式數(shù)據(jù)轉(zhuǎn)換成JPG文件
Parameter:
*f 圖像數(shù)據(jù)指針
height 圖像長
width 圖像寬
bmf JPG文件流指針
**********************************************************************************/
void jpg(double *f, int height, int width, ofstream bmf)
{
double *X1 = new double[64] ;//載入各塊數(shù)據(jù)
double *F = new double [64] ;//DCT變換結(jié)果
int *X = new int[64] ;//量化和Zig-Zag排序結(jié)果
int *Z = new int[64] ;//游程中0的個數(shù)
int *P = new int[64] ;//游程值
int k=0; //AC保留個數(shù)
int ctc =0 ;//連0記數(shù)器
int DC_temp = 0;//DPCM 編碼(上一塊的DC)
int DC; //DC
int AC; //AC
long jpgcode = 0; //剩余的JPG碼流
long jpg_codeN = 0; //剩余的碼子長度
int r=1; //用來計算位數(shù)
int seg = 0; //位數(shù)
//向JPG 文件寫JPG信息
bmf.seekp(0);
bmf.write(SOI, 2); //SOI
bmf.write(APPO, 18); //APPO
unsigned char Q1[64]; //量化表
for(int z=0; z<64;z++)
{
Q1[z] = (unsigned char)Q[DCTOrd[z]];
}
bmf.write(DQT, 5);
bmf.write(Q1, 64);
SOFO[5] = height>>8; //SOFO
SOFO[6] = height&0xff;
SOFO[7] = width>>8;
SOFO[8] = width&0xff;
bmf.write(SOFO, 13);
bmf.write(DHT_DC, 33); //Huffuman Table
bmf.write(DHT_AC, 183);
bmf.write(SOS, 10); //SOS
//開始編碼
for(int i=0; i<(height/8); i++)//按塊進(jìn)行編碼
for(int j=0; j<(width/8); j++)
{
//記數(shù)清0
k=0;
ctc=0;
//P、Z清零,載入數(shù)據(jù):f->X1,Zig-Zag 排序//量化
for(int m=0; m<8; m++)
for(int n=0; n<8; n++)
{
*(Z + m*8 + n) = 0;
*(P + m*8 + n) = 0;
*(X1 + m*8 + n) = *(f + width*i*8 + width*m + 8*j + n) - 128;
}
//DCT變換:X1->F
D2BMPDCT(X1, F, 8, 8, 3);//DCT變換:f-->F
//量化,四舍五入:F->X
for(m=0; m<64; m++)
{
if(*(F + DCTOrd[m])/Q1[m] - (int)(*(F + DCTOrd[m])/Q1[m]) <0.5)
*(X + m) = (int)(*(F + DCTOrd[m])/Q1[m]);
else
*(X + m) = (int)( *(F + DCTOrd[m])/Q1[m]) + 1;
}
//行程編碼->P、Z,k
for(m=0; m<8; m++)
for(int n=0; n<8; n++)
{
if((m+n)==0)
{
*P=*X;
k++;
continue;
}
if(*(X + m*8 + n)!=0)
{
for(int l=0; l<ctc/16+1; l++)
{
if((ctc%16)!=(ctc-l*16))
{
*(Z + k) = 15;
*(P + k) = 0;
}
else
{
*(Z + k) = (ctc%16);
*(P + k) = *(X + m*8 + n);
}
k++;
}
ctc=0;
}
else
{
ctc++;
}
}
//k個行程中,1個DC分量,k-1個AC分量
//先對DC求差分、查Huffuman表、
r = 1;
seg = 0;
while(1)
{
if(r>abs(*P - DC_temp))break;
else{
r = (r<<1);
seg++;
}
}
if((*P - DC_temp)<0) DC = ((~(DC_temp-*P))&(r-1));
else DC = (*P - DC_temp);
{
jpgcode = (jpgcode<<(DC_size[seg] + seg)) + ((DC_code[seg])<<seg) + DC;
jpg_codeN = jpg_codeN + DC_size[seg] + seg;
}
while(jpg_codeN > 7){
jpg_codeN -= 8;
bmf.put((unsigned char)(jpgcode/(1<<jpg_codeN)));
if((unsigned char)(jpgcode/(1<<jpg_codeN))==255)
bmf.put((unsigned char)0);//0xFF->補(bǔ)0x00
jpgcode = jpgcode - ((jpgcode>>jpg_codeN)<<jpg_codeN);
}
//再對AC進(jìn)行Huffuman編碼
for(m=1; m<k; m++)
{
r=1;
seg = 0;
while(1)
{
if(r>abs(*(P + m)))break;
else{
r=(r<<1);
seg++;
}
}
if(*(P + m)<0) AC = ((~(-*(P + m)))&(r-1));
else AC = *(P + m);
jpgcode = (jpgcode<<(AC_size[*(Z+m)*16 + seg] + seg)) + (AC_code[*(Z+m)*16 + seg]<<seg) + AC;
jpg_codeN = jpg_codeN + AC_size[*(Z+m)*16 + seg] + seg;
while(jpg_codeN > 7){
jpg_codeN -= 8;
bmf.put((unsigned char)(jpgcode/(1<<jpg_codeN)));
if((unsigned char)(jpgcode/(1<<jpg_codeN))==255)
bmf.put((unsigned char)0);//0xFF->補(bǔ)0x00
jpgcode= jpgcode - ((jpgcode>>jpg_codeN)<<jpg_codeN);
}
}
if(k<63)//輸出EOB
{
jpgcode = (jpgcode<<(AC_size[0])) + AC_code[0];
jpg_codeN = jpg_codeN + AC_size[0];
while(jpg_codeN > 7){
jpg_codeN -= 8;
bmf.put((unsigned char)(jpgcode/(1<<jpg_codeN)));
if((unsigned char)(jpgcode/(1<<jpg_codeN))==255)
bmf.put((unsigned char)0);//0xFF->補(bǔ)0x00
jpgcode= jpgcode - ((jpgcode>>jpg_codeN)<<jpg_codeN);
}
}
DC_temp = *P;//備份DC
}
//補(bǔ)全一個Byte.
if(jpg_codeN>0)
{
bmf.put((unsigned char)( (jpgcode<<(8-jpg_codeN)) + (1<<(8-jpg_codeN)) -1 ));
if((unsigned char)( (jpgcode<<(8-jpg_codeN)) + (1<<(8-jpg_codeN)) -1 )==255)
bmf.put((unsigned char)0);//0xFF->補(bǔ)0x00
}
bmf.write(EOI, 2);
bmf.close();
delete []X;
delete []Z;
delete []P;
delete []F;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -