?? jpg.h
字號:
/*************************************************************
Filename: JPG.h.
Writer: Dai Zhiheng.
Time: 2005-5-14.
**************************************************************/
#include "dct.h"
#include "math.h"
#include <fstream>
using namespace std;
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
};
/**********************************************************************************
函數功能:把2維BMP格式數據轉換成JPG文件
Parameter:
*f 圖像數據指針
height 圖像長
width 圖像寬
bmf JPG文件流指針
**********************************************************************************/
void jpg(double *f, int height, int width, ofstream bmf)
{
double *X1 = new double[64] ;//載入各塊數據
double *F = new double [64] ;//DCT變換結果
int *X = new int[64] ;//量化和Zig-Zag排序結果
int *Z = new int[64] ;//游程中0的個數
int *P = new int[64] ;//游程值
int k=0; //AC保留個數
int ctc =0 ;//連0記數器
int DC_temp = 0;//DPCM 編碼(上一塊的DC)
int DC; //DC
int AC; //AC
long jpgcode = 0; //剩余的JPG碼流
long jpg_codeN = 0; //剩余的碼子長度
int r=1; //用來計算位數
int seg = 0; //位數
//向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++)//按塊進行編碼
for(int j=0; j<(width/8); j++)
{
//記數清0
k=0;
ctc=0;
//P、Z清零,載入數據: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
dct2(X1, F, 8, 8);
//量化,四舍五入: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->補0x00
jpgcode = jpgcode - ((jpgcode>>jpg_codeN)<<jpg_codeN);
}
//再對AC進行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->補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->補0x00
jpgcode= jpgcode - ((jpgcode>>jpg_codeN)<<jpg_codeN);
}
}
DC_temp = *P;//備份DC
}
//補全一個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->補0x00
}
bmf.write(EOI, 2);
bmf.close();
delete []X;
delete []Z;
delete []P;
delete []F;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -