📄 jpegbianma.txt
字号:
//
// 参数说明:
// value:AC/DC信号的振幅
//********************************************************** **********
SYM2 BuildSym2(SHORT value)
{
SYM2 Symbol;
Symbol.codeLen = ComputeVLI(value); //获取编码长度
Symbol.amplitude = 0;
if (value >= 0)
{
Symbol.amplitude = value;
}
else
{
Symbol.amplitude = SHORT(pow(2,Symbol.codeLen)-1) + value; //计算反码
}
return Symbol;
}
//返回符号的长度
BYTE ComputeVLI(SHORT val)
{
BYTE binStrLen = 0;
val = abs(val);
//获取二进制码长度
if(val == 1)
{
binStrLen = 1;
}
else if(val >= 2 && val <= 3)
{
binStrLen = 2;
}
else if(val >= 4 && val <= 7)
{
binStrLen = 3;
}
else if(val >= 8 && val <= 15)
{
binStrLen = 4;
}
else if(val >= 16 && val <= 31)
{
binStrLen = 5;
}
else if(val >= 32 && val <= 63)
{
binStrLen = 6;
}
else if(val >= 64 && val <= 127)
{
binStrLen = 7;
}
else if(val >= 128 && val <= 255)
{
binStrLen = 8;
}
else if(val >= 256 && val <= 511)
{
binStrLen = 9;
}
else if(val >= 512 && val <= 1023)
{
binStrLen = 10;
}
else if(val >= 1024 && val <= 2047)
{
binStrLen = 11;
}
return binStrLen;
}
//********************************************************** **********
// 方法名称:BuildVLITable
//
// 方法说明:生成VLI表
//
// 参数说明:
//********************************************************** **********
void BuildVLITable(void)
{
int i = 0;
for (i = 0; i < DC_MAX_QUANTED; ++i)
{
pVLITAB = ComputeVLI(i);
}
for (i = DC_MIN_QUANTED; i < 0; ++i)
{
pVLITAB = ComputeVLI(i);
}
}
};
#endif // __JENC__
Jpeg.h
typedef struct tagBMBUFINFO
{
UINT imgWidth;
UINT imgHeight;
UINT buffWidth;
UINT buffHeight;
WORD BitCount;
BYTE padSize;
}BMBUFINFO;
// DCT转换尺寸
static const BYTE DCTSIZE = 8;
// DCT转换块长度
static const BYTE DCTBLOCKSIZE = 64;
//Huffman码结构
typedef struct tagHUFFCODE
{
WORD code; // huffman 码字
BYTE length; // 编码长度
WORD val; // 码字对应的值
}HUFFCODE;
//AC信号中间符号结构
typedef struct tagACSYM
{
BYTE zeroLen; //0行程
BYTE codeLen; //幅度编码长度
SHORT amplitude;//振幅
}ACSYM;
//DC/AC 中间符号2描述结构
typedef struct tagSYM2
{
SHORT amplitude;//振幅
BYTE codeLen; //振幅长度(二进制形式的振幅数据的位数)
}SYM2;
// 存放VLI表
BYTE VLI_TAB[4096];
BYTE* pVLITAB; //VLI_TAB的别名,使下标在-2048-2048
// 存放2个量化表
BYTE YQT[DCTBLOCKSIZE];
BYTE UVQT[DCTBLOCKSIZE];
// 存放2个FDCT变换要求格式的量化表
FLOAT YQT_DCT[DCTBLOCKSIZE];
FLOAT UVQT_DCT[DCTBLOCKSIZE];
//存放4个Huffman表
HUFFCODE STD_DC_Y_HT[12];
HUFFCODE STD_DC_UV_HT[12];
HUFFCODE STD_AC_Y_HT[256];
HUFFCODE STD_AC_UV_HT[256];
static BYTE bytenew=0; // The byte that will be written in the JPG file
static CHAR bytepos=7; //bit position in the byte we write (bytenew)
//should be<=7 and >=0
static USHORT mask[16] ={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,327 68};
static const DOUBLE aanScaleFactor[8] = {1.0, 1.387039845, 1.306562965, 1.175875602,
1.0, 0.785694958, 0.541196100, 0.275899379};
//量化后DC范围在-2^11 - 2^11 - 1之间,量化后AC范围在-2^10 - 2^10 - 1之间
static const INT AC_MAX_QUANTED = 1023; //量化后AC的最大值
static const INT AC_MIN_QUANTED = -1024; //量化后AC的最小值
static const INT DC_MAX_QUANTED = 2047; //量化后DC的最大值
static const INT DC_MIN_QUANTED = -2048; //量化后DC的最小值
//标准亮度信号量化模板
const static BYTE std_Y_QT[64] =
{
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
};
//标准色差信号量化模板
const static BYTE std_UV_QT[64] =
{
17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99,
47, 66, 99 ,99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
//正向 8x8 Z变换表
const static BYTE FZBT[64] =
{
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
};
//色彩空间系数常量,依次是411,111,211采样的系数,211采样的2种方式的系数相同
static const FLOAT COLORSPACECOEF[4][3] = {{1,0.25,0.25},{1,1,1},{1,0.5,0.5},{1,0.5,0.5}};
//MCU中各型号分量出现的比率
static const BYTE MCUIndex[4][3] = {{4,1,1},{1,1,1},{2,1,1},{2,1,1}};
// 标准Huffman表 (cf. JPEG standard section K.3)
static BYTE STD_DC_Y_NRCODES[17]={0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
static BYTE STD_DC_Y_VALUES[12]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
static BYTE STD_DC_UV_NRCODES[17]={0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
static BYTE STD_DC_UV_VALUES[12]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
static BYTE STD_AC_Y_NRCODES[17]={0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0X7D };
static BYTE STD_AC_Y_VALUES[162]= {
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 };
static BYTE STD_AC_UV_NRCODES[17]={0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0X77};
static BYTE STD_AC_UV_VALUES[162]={
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 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, 0x82, 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,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
Jpegformat.h
//文件开始,开始标记为0xFFD8
const static WORD SOITAG = 0xD8FF;
//文件结束,结束标记为0xFFD9
const static WORD EOITAG = 0xD9FF;
//JFIF APP0段结构
#pragma pack(push,1)
typedef struct tagJPEGAPP0
{
WORD segmentTag; //APP0段标记,必须为FFE0
WORD length; //段长度,一般为16,如果没有缩略图
CHAR id[5]; //文件标记 "JFIF" + "\0"
WORD ver; //文件版本,一般为0101或0102
BYTE densityUnit; //密度单位,0=无单位 1=点数/英寸 2=点数/厘米
WORD densityX; //X轴方向密度,通常写1
WORD densityY; //Y轴方向密度,通常写1
BYTE thp; //缩略图水平像素数,写0
BYTE tvp; //缩略图垂直像素数,写0
}JPEGAPP0;// = {0xE0FF,16,'J','F','I','F',0,0x0101,0,1,1,0,0};
#pragma pack(pop)
//JFIF APPN段结构
#pragma pack(push,1)
typedef struct tagJPEGAPPN
{
WORD segmentTag; //APPn段标记,从FFE0 - FFEF n=0-F
WORD length; //段长度
}JPEGAPPN;
#pragma pack(pop)
//JFIF DQT段结构(8 bits 量化表)
#pragma pack(push,1)
typedef struct tagJPEGDQT_8BITS
{
WORD segmentTag; //DQT段标记,必须为0xFFDB
WORD length; //段长度,这里是0x4300
BYTE tableInfo; //量化表信息
BYTE table[64]; //量化表(8 bits)
}JPEGDQT_8BITS;
#pragma pack(pop)
//JFIF DQT段结构(8 bits 量化表)
#pragma pack(push,1)
typedef struct tagJPEGDQT_16BITS
{
WORD segmentTag; //DQT段标记,必须为0xFFDB
WORD length; //段长度,这里是0x8300
BYTE tableInfo; //量化表信息
WORD table[64]; //量化表(16 bits)
}JPEGDQT_16BITS;
#pragma pack(pop)
//JFIF SOF0段结构(真彩),其余还有SOF1-SOFF
#pragma pack(push,1)
typedef struct tagJPEGSOF0_24BITS
{
WORD segmentTag; //SOF段标记,必须为0xFFC0
WORD length; //段长度,真彩图为17,灰度图为11
BYTE precision; //精度,每个信号分量所用的位数,基本系统为0x08
WORD height; //图像高度
WORD width; //图像宽度
BYTE sigNum; //信号数量,真彩JPEG应该为3,灰度为1
BYTE YID; //信号编号,亮度Y
BYTE HVY; //采样方式,0-3位是垂直采样,4-7位是水平采样
BYTE QTY; //对应量化表号
BYTE UID; //信号编号,色差U
BYTE HVU; //采样方式,0-3位是垂直采样,4-7位是水平采样
BYTE QTU; //对应量化表号
BYTE VID; //信号编号,色差V
BYTE HVV; //采样方式,0-3位是垂直采样,4-7位是水平采样
BYTE QTV; //对应量化表号
}JPEGSOF0_24BITS;// = {0xC0FF,0x0011,8,0,0,3,1,0x11,0,2,0x11,1,3,0x11,1};
#pragma pack(pop)
//JFIF SOF0段结构(灰度),其余还有SOF1-SOFF
#pragma pack(push,1)
typedef struct tagJPEGSOF0_8BITS
{
WORD segmentTag; //SOF段标记,必须为0xFFC0
WORD length; //段长度,真彩图为17,灰度图为11
BYTE precision; //精度,每个信号分量所用的位数,基本系统为0x08
WORD height; //图像高度
WORD width; //图像宽度
BYTE sigNum; //信号数量,真彩JPEG应该为3,灰度为1
BYTE YID; //信号编号,亮度Y
BYTE HVY; //采样方式,0-3位是垂直采样,4-7位是水平采样
BYTE QTY; //对应量化表号
}JPEGSOF0_8BITS;// = {0xC0FF,0x000B,8,0,0,1,1,0x11,0};
#pragma pack(pop)
//JFIF DHT段结构
#pragma pack(push,1)
typedef struct tagJPEGDHT
{
WORD segmentTag; //DHT段标记,必须为0xFFC4
WORD length; //段长度
BYTE tableInfo; //表信息,基本系统中 bit0-3 为Huffman表的数量,bit4 为0指DC的Huffman表 为1指AC的Huffman表,bit5-7保留,必须为0
BYTE huffCode[16];//1-16位的Huffman码字的数量,分别存放在数组[1-16]中
//BYTE* huffVal; //依次存放各码字对应的值
}JPEGDHT;
#pragma pack(pop)
// JFIF SOS段结构(真彩)
#pragma pack(push,1)
typedef struct tagJPEGSOS_24BITS
{
WORD segmentTag; //SOS段标记,必须为0xFFDA
WORD length; //段长度,这里是12
BYTE sigNum; //信号分量数,真彩图为0x03,灰度图为0x01
BYTE YID; //亮度Y信号ID,这里是1
BYTE HTY; //Huffman表号,bit0-3为DC信号的表,bit4-7为AC信号的表
BYTE UID; //亮度Y信号ID,这里是2
BYTE HTU;
BYTE VID; //亮度Y信号ID,这里是3
BYTE HTV;
BYTE Ss; //基本系统中为0
BYTE Se; //基本系统中为63
BYTE Bf; //基本系统中为0
}JPEGSOS_24BITS;// = {0xDAFF,0x000C,3,1,0,2,0x11,3,0x11,0,0x3F,0};
#pragma pack(pop)
// JFIF SOS段结构(灰度)
#pragma pack(push,1)
typedef struct tagJPEGSOS_8BITS
{
WORD segmentTag; //SOS段标记,必须为0xFFDA
WORD length; //段长度,这里是8
BYTE sigNum; //信号分量数,真彩图为0x03,灰度图为0x01
BYTE YID; //亮度Y信号ID,这里是1
BYTE HTY; //Huffman表号,bit0-3为DC信号的表,bit4-7为AC信号的表
BYTE Ss; //基本系统中为0
BYTE Se; //基本系统中为63
BYTE Bf; //基本系统中为0
}JPEGSOS_8BITS;// = {0xDAFF,0x0008,1,1,0,0,0x3F,0};
#pragma pack(pop)
// JFIF COM段结构
#pragma pack(push,1)
typedef struct tagJPEGCOM
{
WORD segmentTag; //COM段标记,必须为0xFFFE
WORD length; //注释长度
}JPEGCOM;
#pragma pack(pop)
Main.cpp
#include <iostream>
#include "jenc.h"
using namespace std;
int main(int argc, char* argv[])
{
if (argc <= 1)
{
cout << "please input bmp filename." << endl;
return 0;
}
string fileName = string(argv[1]);
string outFile = fileName.substr(0,fileName.find_last_of('.'));
outFile = outFile + ".jpg";
JEnc enc;
enc.Invoke(fileName, outFile,100);
cout << outFile << endl;
getchar();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -