??xml version="1.0" encoding="utf-8" standalone="yes"?> 数据块: 文g_ IHDR块: PLTE块: tRNS块: IDAT块: IEND块: PNG囑փ压羃Q?br> 了解了PNG的文件结构,压羃有的放矢了。压~有6个别,可以Ҏ需要选择?br>Level1Q读取PNG文gQ将除六大块之外的所有区块都qo?br>Level2Q文件头是固定的0x89504e47 0x0d0a1a0aQ文件尾是固定的0x00000000 0x49454e44 0xae426082Q去掉! PNG囑փ解压Q?br> 创徏了自定义的文ӞJ2ME端读取后Q就面解压的问题了。我们可以利用此函数来创建ImageQ?br>static Image PNG囑փ加解密:
HRESULT LoadPSD( LPSTR strFilename ) // dPSD文g
{
DWORD dwWidth, dwHeight; // 宽高
long lSurfWidth = m_Rect.right - m_Rect.left;
long lSurfHeight = m_Rect.bottom - m_Rect.top;
WORD CompressionType; // 压羃cd
HDC hDC;
FILE *fpPSD;
WORD ChannelCount; // 通道?/span>
// 打开PSD文g
if ( ( fpPSD = fopen ( strFilename, "rb" ) ) == NULL ) {
return E_FAIL;
}
// 头四个字节ؓ"8BPS"
char signature[5];
signature[0] = fgetc( fpPSD );
signature[1] = fgetc( fpPSD );
signature[2] = fgetc( fpPSD );
signature[3] = fgetc( fpPSD );
signature[4] = '\0';
if ( strcmp( signature,"8BPS" ) != 0 ) {
return E_FAIL;
}
// 版本必须?
if ( Read16( fpPSD ) != 1 ) {
return E_FAIL;
}
// 跌一些数?(L0)
Read32( fpPSD );
Read16( fpPSD );
// d通道?/font>
ChannelCount = Read16( fpPSD );
// 定臛_有一个通道
if ( ( ChannelCount < 0 ) || ( ChannelCount > MAX_PSD_CHANNELS ) ) {
return E_FAIL;
}
// d宽和?/font>
dwHeight = Read32( fpPSD );
dwWidth = Read32( fpPSD );
if ( dwWidth != ( DWORD )lSurfWidth || dwHeight != ( DWORD )lSurfHeight ) {
return E_FAIL;
}
// 只读?位通道
if ( Read16( fpPSD ) != 8 ) {
return E_FAIL;
}
// 定模式为RGB.
// 可能|
// 0: 位图
// 1: 灰阶
// 2: 索引
// 3: RGB
// 4: CMYK
// 7: Multichannel
// 8: Duotone
// 9: Lab
if ( Read16( fpPSD ) != 3 ) {
return E_FAIL;
}
// 跌数据Q如调色板)
int ModeDataCount = Read32( fpPSD );
if ( ModeDataCount )
fseek( fpPSD, ModeDataCount, SEEK_CUR );
// 跌数据Q如Qpen tool paths, etcQ?/font>
int ResourceDataCount = Read32( fpPSD );
if ( ResourceDataCount )
fseek( fpPSD, ResourceDataCount, SEEK_CUR );
// 条过保留数据
int ReservedDataCount = Read32( fpPSD );
if ( ReservedDataCount )
fseek( fpPSD, ReservedDataCount, SEEK_CUR );
// 0: 非压~?br> // 1: RLE压羃
CompressionType = Read16( fpPSD );
if ( CompressionType > 1 ) {
return E_FAIL;
}
BYTE* PSDPixels = new BYTE[ ( lSurfWidth * lSurfHeight ) * 4 ];
// 解包数据
UnPackPSD( fpPSD, lSurfWidth, lSurfHeight, PSDPixels, ChannelCount, CompressionType );
fclose( fpPSD );
// 复制信息
BITMAPINFO BitmapInfo;
ZeroMemory( &BitmapInfo, sizeof( BitmapInfo ) );
BitmapInfo.bmiHeader.biSize = sizeof( BitmapInfo.bmiHeader );
BitmapInfo.bmiHeader.biWidth = lSurfWidth;
BitmapInfo.bmiHeader.biHeight = -lSurfHeight;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 32;
m_lpDDS7->GetDC( &hDC );
int rc = StretchDIBits( hDC,
0,
0,
lSurfWidth,
lSurfHeight,
0,
0,
lSurfWidth,
lSurfHeight,
PSDPixels,
&BitmapInfo,
DIB_RGB_COLORS,
SRCCOPY );
m_lpDDS7->ReleaseDC( hDC );
if ( rc == GDI_ERROR ) {
H_ARRAY_DELETE( PSDPixels );
#ifdef _DEBUG
g_pHERR->OutDebugMsg( 3, H2DSERR_INVALID_PSD );
#endif
return E_FAIL;
}
// 是否dAlpha混合通道
if( ChannelCount > 3 ) {
m_pbAlphaMask = new BYTE[ lSurfWidth * lSurfHeight ];
for ( int x = 0; x < lSurfWidth; x++ )
for ( int y = 0; y < lSurfHeight; y++ ) {
m_pbAlphaMask[ ( y * lSurfWidth ) + x ] =
PSDPixels[ ( ( ( y * lSurfHeight ) + x ) * 4 ) + 3 ];
}
}
else {
m_pbAlphaMask = NULL;
}
H_ARRAY_DELETE( PSDPixels );
return DD_OK;
}
// PSD文g解包
DWORD dwWidth, // dwWidth、dwHeight为宽高,
DWORD dwHeight,
BYTE* pixels, // pixels包目标指针,
WORD ChannelCnt, // ChannelCnt为通道敎ͼ
WORD Compression ) // Compression位压~类型?
{
int Default[4] = { 0, 0, 0, 255 };
int chn[4] = { 2, 1, 0, 3};
int PixelCount = dwWidth * dwHeight;
if ( Compression ) {
fseek( fp, dwHeight * ChannelCnt * 2, SEEK_CUR );
for ( int c = 0; c < 4; c++ ) {
int pn = 0;
int channel = chn[c];
if ( channel >= ChannelCnt ) {
for ( pn=0; pn < PixelCount ;pn++ ) {
pixels[ ( pn * 4 ) + channel ] = Default[ channel ];
}
}
else // 非压~?br> {
int count = 0;
while( count < PixelCount ) {
int len = fgetc( fp );
if( len == 128 ) { }
len++;
count += len;
while(len) {
pixels[ ( pn * 4 ) + channel ] = fgetc( fp );
pn++;
len--;
}
}
else if ( len > 128 ) // RLE打包
{
len ^= 0x0FF;
len += 2;
unsigned char val = fgetc( fp );
count += len;
while( len ) {
pixels[ ( pn * 4 ) + channel ] = val;
pn++;
len--;
}
}
}
}
}
}
else
{
for ( int c=0; c < 4; c++ ) {
int channel = chn[c];
if ( channel > ChannelCnt ) {
for( int pn = 0; pn < PixelCount; pn++ ) {
pixels[ ( pn * 4 ) + channel ] = Default[ channel ];
}
}
else {
for( int n = 0; n < PixelCount; n++ ) {
pixels[ ( n * 4 ) + channel ] = fgetc( fp );
}
}
}
}
}
]]>
]]>
本文档是为满多对 TGA 囑փ格式的了解需要而创建的。本文摘录自truevision 技术指南的附录 CQ如?
需要更q一步的信息Q请致信以下地址Q?
at&t
electronic photography and imaging center
2002 wellesley ave.
indianapolis, in 42619
本文档不求全面,但力求准。如果你发现了Q何拼写错误或内容错误Q请告诉我,Q?david mcduffe,
75530,2626 Q,我将Ҏq些错误Q谢谢?
不全面的原因?TGA 包含了超q六U图像文件格式,而其中的几种较ؓ常用?我选择了我现在使用的格式ƈ
在本文中加以详解?如果你需要本文中没有包含的格式说明,你可以与你的 truevision 代理商联pR?/pre>
Ҏ有的 TGA 格式的文件而言Q其W三字节Q二q制整数Q用来区别各U不同的 TGA 文g。下面列Z该字
节表明的对应文gcdQ?/pre>
0 - 文g中没有图像数?/pre>
1 - 未压~的Q颜色表囑փ
2 - 未压~的Qrgb 囑փ
3 - 未压~的Q黑白图?/pre>
9 - runlength ~码的颜色表囑փ
10 - runlength ~码?rgb 囑փ
11 - 压羃的,黑白囑փ
32 - 使用 huffman,delta ?runlength ~码的颜色表囑փ
33 - 使用 huffman,delta ?runlength ~码的颜色映图像,4 四叉树cd处理?/pre>
本文仅仅描述对应 1Q?Q? ?10 的文件格式?
--------------------------------------------------------------------------------
|数据cd 1Q?颜色?color-mapped)囑փ
|--------|--------|------------------------------------------------------------
| 偏移 | 长度 | 描述
|--------|--------|------------------------------------------------------------
| 0 | 1 | 囑փ信息字段Q见本子表的后面Q的字符?
| | |
| | | 本字D| 1 字节无符h型,指出了图像格式区别字D长?
| | | 其取D围是 0 ?255 Q当它ؓ 0 时表C没有图像的
| | | 信息字段?
| | |
| | |
|--------|--------|------------------------------------------------------------
| 1 | 1 | 颜色表的cd
| | |
| | | 该字Dؓ表示对应格式 1 的图像而包含一个二q制 1
| | |
|--------|--------|------------------------------------------------------------
| 2 | 1 | 囑փcd?
| | |
| | | 该字D|Mؓ 1 Q?q也是此cd为格?1 的原?
| | |
|--------|--------|------------------------------------------------------------
| 3 | 5 | 颜色表规?
| | |
| 3 | 2 | 颜色表首址
| | | 颜色表首元表的整型Q低?高位Q烦?
| | |
| 5 | 2 | 颜色表的长度
| | | 颜色表的表项LQ整型(低位-高位Q?
| | |
| 7 | 1 | 颜色表表的位(bitQ数
| | | 16 代表 16 ?TGA Q?4 代表 24 ?TGA Q?2 代表 32 ?TGA
| | |
| | |
|--------|--------|------------------------------------------------------------
| 8 | 10 | 囑փ规格
| | |
| 8 | 2 | 囑փ x 坐标起始位置
| | | 囑փ左下?x 坐标的整型(低位-高位Q?
| | |
| | |
| 10 | 2 | 囑փ y 坐标起始位置
| | | 囑փ左下?y 坐标的整型(低位-高位Q?
| | |
| | |
| 12 | 2 | 囑փ宽度
| | | 以像素ؓ单位Q图像宽度的整型Q低?高位Q?
| | |
| 14 | 2 | 囑փ高度
| | | 以像素ؓ单位Q图像高度的整型Q低?高位Q?
| | |
| 16 | 1 | 囑փ每像素存储占用位QbitQ数
| | |
| | |
| 17 | 1 | 囑փ描述W字?
| | | bits 3-0 - 每像素的属性位QbitQ数
| | |
| | | bit 4 - 保留Q必Mؓ 0
| | | bit 5 - 屏幕起始位置标志
| | | 0 = 原点在左下角
| | | 1 = 原点在左上角
| | | truevision 囑փ必须?0
| | | bits 7-6 - 交叉数据存储标志
| | | 00 = 无交?
| | | 01 = 两\?偶交?
| | | 10 = 四\交叉
| | | 11 = 保留
| | | q一应该设?0Q不要问我ؓ什?
| | |
|--------|--------|------------------------------------------------------------
| 18 | 可变 | 囑փ信息字段
| | | 包含一个自由格式的Q长度是囑փ记录块偏U?0 处的字节中的
| | | 倹{它常常被忽略(卛_U?0 处gؓ 0 Q,注意其最大可?
| | | 含有 255 个字W。如果需要存储更多信息,可以攑֜囑փ数据
| | | 之后
| | |
| | |
|--------|--------|------------------------------------------------------------
| 可变 | 可变 | 颜色表数?
| | |
| | | 起始位置由前一个字D늚大小军_Q其长度由单Ҏ据大?
| | | 和数据项数目军_Q在前面相应的说明字D中l出Q?
| | | 每项?2 字节Q? 字节?4 字节Q字节中没有使用的位QbitQ?
| | | 被认为是属性位?
| | |
| | | 4 字节表项中,字节 1 表示 BLUEQ字?2 表示 GREENQ?
| | | 字节 3 表示 REDQ字?4 表示属?
| | | 3 字节表项中各字节依次对应 BLUEQGREENQRED
| | |
| | | 2 字节表项中,两个字节分解成如下Ş式:
| | | arrrrrgg gggbbbbb
| | | 但是Q由于低位在前,高位在后的存储顺序,从文件中d表项
| | | Ӟ先d gggbbbbb 而后d arrrrrgg Qa 表示属性位?
| | |
|--------|--------|------------------------------------------------------------
| 可变 | 可变 | 囑փ数据字段
| | |
| | | 该字D늻Z Q高度)xQ宽度)个颜色表烦引,每个索引
| | | 以整C字节的Ş式存储(典型的例子如 1 ?2 个字节)
| | | 所有的数据都没有符P对于 2-字节表项而言Q低位字节是
| | | 先存储的?
| | |
-------------------------------------------------------------------------------
--------------------------------------------------------------------------------
|数据cd 2Q?无颜色表 rgb 囑փ
|--------|--------|------------------------------------------------------------
| 偏移 | 长度 | 描述
|--------|--------|----------------------------------------------------------
| 0 | 1 | 囑փ信息字段Q?见本子表的后?Q的字符?
| | |
| | | 本字D| 1 字节无符h型,指出了图像格式区别字D长?
| | | 其取D围是 0 ?255 Q当它ؓ 0 时表C没有图像的
| | | 信息字段?
| | |
|--------|--------|------------------------------------------------------------
| 1 | 1 | 颜色表类?
| | |
| | | 该字D늚内容或者ؓ 0 或者ؓ 1Q? 表示没有颜色表,1 表示
| | | 颜色表存在。由于本格式是无颜色表的Q因此此w常被忽略?
| | | 提示Q如果置?1Qtarga l画E序Q将把边框颜色设|ؓ映射
| | | 中的W一U颜?
| | |
|--------|--------|------------------------------------------------------------
| 2 | 1 | 囑փcd?
| | |
| | | 该字D|Mؓ 2 Q?q也是此cd为格?2 的原?
| | |
|--------|--------|------------------------------------------------------------
| 3 | 5 | 颜色表规?
| | |
| | | 如果颜色表类型字Dؓ 0 则被忽略Q否则描q如?
| | |
| 3 | 2 | 颜色表首址
| | | 颜色表首元入口的整型Q低?高位Q烦?
| | |
| 5 | 2 | 颜色表的长度
| | | 颜色表的表项LQ整型(低位-高位Q?
| | |
| 7 | 1 | 颜色表表的位(bitQ数
| | | 16 代表 16 ?TGA Q?4 代表 24 ?TGA Q?2 代表 32 ?TGA
| | |
| | |
|--------|--------|------------------------------------------------------------
| 8 | 10 | 囑փ规格
| | |
| 8 | 2 | 囑փ x 坐标起始位置
| | | 囑փ左下?x 坐标的整型(低位-高位Q?
| | |
| | |
| 10 | 2 | 囑փ y 坐标起始位置
| | | 囑փ左下?y 坐标的整型(低位-高位Q?
| | |
| | |
| 12 | 2 | 囑փ宽度
| | | 以像素ؓ单位Q图像宽度的整型Q低?高位Q?
| | |
| 14 | 2 | 囑փ高度
| | | 以像素ؓ单位Q图像高度的整型Q低?高位Q?
| | |
| 16 | 1 | 囑փ每像素存储占用位QbitQ数
| | | 它的gؓ16Q?4 ?32 {等军_了该囑փ?TGA 16QTGA24
| | | TGA 32 {等
| | |
| 17 | 1 | 囑փ描述W字?
| | | bits 3-0 - 每像素对应的属性位的位敎ͼ对于 TGA 16Q?
| | | 该gؓ 0 ?1Q对?TGA 24Q该gؓ 0Q?
| | | 对于 TGA 32Q该gؓ 8
| | |
| | | bit 4 - 保留Q必Mؓ 0
| | | bit 5 - 屏幕起始位置标志
| | | 0 = 原点在左下角
| | | 1 = 原点在左上角
| | | 对于 truevision 囑փ必须?0
| | | bits 7-6 - 交叉数据存储标志
| | | 00 = 无交?
| | | 01 = 两\?偶交?
| | | 10 = 四\交叉
| | | 11 = 保留
| | |
|--------|--------|------------------------------------------------------------
| 18 | 可变 | 囑փ信息字段
| | | 包含一个自由格式的Q长度是囑փ记录块偏U?0 处的字节中的
| | | 倹{它常常被忽略(卛_U?0 处gؓ 0 Q,注意其最大可?
| | | 含有 255 个字W。如果需要存储更多信息,可以攑֜囑փ数据
| | | 之后
| | |
|--------|--------|------------------------------------------------------------
| 可变 | 可变 | 颜色表数?
| | |
| | | 如果颜色表类型ؓ 0Q则该域不存在,否则过该域直接d
| | | 囑փ颜色表规g描述了每的字节敎ͼ?2Q?Q? 之一
| | |
| | |
| | |
| | |
|--------|--------|------------------------------------------------------------
| 可变 | 可变 | 囑փ数据?
| | |
| | | q里存储了(宽度QxQ高度)个像素,每个像素中的 rgb 色?
| | | 该色值包含整C字节
| | |
| | |
| | | 3 字节表项中各字节依次对应 BLUEQGREENQRED
| | |
| | | 2 字节表项中,两个字节分解成如下Ş式:
| | | arrrrrgg gggbbbbb
| | | 但是Q由于低位在前,高位在后的存储顺序,从文件中d表项
| | | Ӟ先d gggbbbbb 而后d arrrrrgg Qa 表示属性位
| | |
| | | 4 字节表项包含了分别代?blue,green,red 及属性的四个
| | | 字节Q(׃g上的原因Q有的时?TGA 24 cd的图像也?
| | | TGA 32 cd的图像那样存?
| | |
| | |
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
|数据cd 9: runlength ~码Q带颜色表的囑փ
|--------|--------|------------------------------------------------------------
| 偏移 | 长度 | 描述
|--------|--------|------------------------------------------------------------
| 0 | 1 | 囑փ信息字段Q见本子表的后面Q的字符?
| | |
| | | 本字D| 1 字节无符h型,指出了图像格式区别字D长?
| | | 其取D围是 0 ?255 Q当它ؓ 0 时表C没有图像的
| | | 信息字段?
| | |
|--------|--------|------------------------------------------------------------
| 1 | 1 | 颜色表的cd
| | |
| | | 该字Dؓ表示对应带颜色表的图像而Mؓ 1
| | |
|--------|--------|------------------------------------------------------------
| 2 | 1 | 囑փcd?
| | |
| | | 本类型该字段Zq制 9
| | |
|--------|--------|------------------------------------------------------------
| 3 | 5 | 颜色表规?
| | |
| | | 如果颜色表类型字Dؓ 0 则被忽略Q否则描q如?
| | |
| | |
| 3 | 2 | 颜色表首址
| | | 颜色表首元入口的整型Q低?高位Q烦?
| | |
| 5 | 2 | 颜色表的长度
| | | 颜色表的表项LQ整型(低位-高位Q?
| | |
| 7 | 1 | 颜色表表的位(bitQ数
| | | 16 代表 16 ?TGA Q?4 代表 24 ?TGA Q?2 代表 32 ?TGA
| | |
|--------|--------|------------------------------------------------------------
| 8 | 10 | 囑փ规格
| | |
| 8 | 2 | 囑փ x 坐标起始位置
| | | 囑փ左下?x 坐标的整型(低位-高位Q?
| | |
| | |
| 10 | 2 | 囑փ y 坐标起始位置
| | | 囑փ左下?y 坐标的整型(低位-高位Q?
| | |
| | |
| 12 | 2 | 囑փ宽度
| | | 以像素ؓ单位Q图像宽度的整型Q低?高位Q?
| | |
| 14 | 2 | 囑փ高度
| | | 以像素ؓ单位Q图像高度的整型Q低?高位Q?
| | |
| 16 | 1 | 囑փ每像素存储占用位QbitQ数
| | |
| | |
| 17 | 1 | 囑փ描述W字?
| | | bits 3-0 - 每像素的属性位QbitQ数
| | |
| | | bit 4 - 保留Q必Mؓ 0
| | | bit 5 - 屏幕起始位置标志
| | | 0 = 原点在左下角
| | | 1 = 原点在左上角
| | | truevision 囑փ必须?0
| | | bits 7-6 - 交叉数据存储标志
| | | 00 = 无交?
| | | 01 = 两\?偶交?
| | | 10 = 四\交叉
| | | 11 = 保留
| | |
|--------|--------|------------------------------------------------------------
| 18 | 可变 | 囑փ信息字段
| | | 包含一个自由格式的Q长度是囑փ记录块偏U?0 处的字节中的
| | | 倹{它常常被忽略(卛_U?0 处gؓ 0 Q,注意其最大可?
| | | 含有 255 个字W。如果需要存储更多信息,可以攑֜囑փ数据
| | | 之后
| | |
|--------|--------|------------------------------------------------------------
| 可变 | 可变 | 颜色表数?
| | |
| | | 起始位置由前一个字D늚大小军_Q其长度由单Ҏ据大?
| | | 和数据项数目军_Q在前面相应的说明字D中l出Q?
| | | 每项?2 字节Q? 字节?4 字节Q字节中没有使用的位QbitQ?
| | | 被认为是属性位?
| | |
| | | 4 字节表项中,字节 1 表示 BLUEQ字?2 表示 GREENQ?
| | | 字节 3 表示 REDQ字?4 表示属?
| | | 3 字节表项中各字节依次对应 BLUEQGREENQRED
| | |
| | | 2 字节表项中,两个字节分解成如下Ş式:
| | | arrrrrgg gggbbbbb
| | | 但是Q由于低位在前,高位在后的存储顺序,从文件中d表项
| | | Ӟ先d gggbbbbb 而后d arrrrrgg Qa 表示属性位?
| | |
|--------|--------|------------------------------------------------------------
| 可变 | 可变 | 囑փ数据?
| | |
| | | 本区域给ZQ宽度)xQ高度)个颜色表索引q些索引存放
| | | 在数据包中;有两中类型的数据包:run-length 数据包,
| | | 以及未加工的数据包,每种cd的数据包含有 1-字节的头信息Q?
| | | Q其中指Z数据包类型和数目Q,其后是可变长度的数据?
| | | 头信息中最高位?1 表示 run-length cd的数据包Q当
| | | 它ؓ 0 Ӟ表示未加工的数据?
| | |
| | | 对于 run-length 数据包,头信息含义如?
| | | __________________________________________________
| | | | 1 bit | 7 位的重复记数减一
| | | | id | ׃ 7 位表C的最大gؓ 127Q故最? |
| | | | | 的运行大ؓ 128Q(译注Q原文ؓ |
| | | | | the largest run sizeQ? |
| | | |-------|----------------------------------------|
| | | | 1 | c c c c c c c |
| | | --------------------------------------------------
| | |
| | | 对于未加工数据包Q头信息的含义如?
| | | __________________________________________________
| | | | 1 bit | 7 位的像素个数减一 |
| | | | id | ׃ 7 位表C的最大gؓ 127Q故? |
| | | | | cd的一个数据包中像素个C能大? |
| | | | | 128 |
| | | |-------|----------------------------------------|
| | | | 0 | n n n n n n n |
| | | --------------------------------------------------
| | |
| | | 对于 run-length 数据包而言Q头信息之后是一个简单的
| | | 颜色索引Q且假定该烦引被重复头信息中?7 位表C的ơ数
| | | run-length 数据包也怼跨越扫描U?
| | | Q扫描线起始于某行结束于下一行)
| | |
| | | 对于未加工的数据包,头信息之后是颜色索引Q数值由头信?
| | | l出Q该cd的数据包也可能跨扫描线
| | |
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
|数据cd 10Qrun length ~码Qrgb 囑փ
|--------|--------|------------------------------------------------------------
| 偏移 | 长度 | 描述
|--------|--------|------------------------------------------------------------
| 0 | 1 | 囑փ信息字段Q见本子表的后面Q的字符?
| | |
| | | 本字D| 1 字节无符h型,指出了图像格式区别字D长?
| | | 其取D围是 0 ?255 Q当它ؓ 0 时表C没有图像的
| | | 信息字段?
| | |
|--------|--------|------------------------------------------------------------
| 1 | 1 | 该字D늚内容或者ؓ 0 或者ؓ 1Q? 表示没有颜色表,1 表示
| | | 颜色表存在。由于本格式是无颜色表的Q因此此w常被忽略?
| | | 提示Q如果置?1Qtarga l画E序Q将把边框颜色设|ؓ映射
| | | 中的W一U颜?
| | |
|--------|--------|------------------------------------------------------------
| 2 | 1 | 囑փcd代码
| | |
| | | 本类型该字段Zq制 10
| | |
|--------|--------|------------------------------------------------------------
| 3 | 5 | 颜色表规?
| | |
| | | 如果颜色表类型字Dؓ 0 则被忽略Q否则描q如?
| | |
| | |
| 3 | 2 | 颜色表首址
| | | 颜色表首元入口的整型Q低?高位Q烦?
| | |
| 5 | 2 | 颜色表的长度
| | | 颜色表的表项LQ整型(低位-高位Q?
| | |
| 7 | 1 | 颜色表表的位(bitQ数
| | | 16 代表 16 ?TGA Q?4 代表 24 ?TGA Q?2 代表 32 ?TGA
| | |
|--------|--------|------------------------------------------------------------
| 8 | 10 | 囑փ规格
| | |
| 8 | 2 | 囑փ x 坐标起始位置
| | | 囑փ左下?x 坐标的整型(低位-高位Q?
| | |
| | |
| 10 | 2 | 囑փ y 坐标起始位置
| | | 囑փ左下?y 坐标的整型(低位-高位Q?
| | |
| | |
| 12 | 2 | 囑փ宽度
| | | 以像素ؓ单位Q图像宽度的整型Q低?高位Q?
| | |
| 14 | 2 | 囑փ高度
| | | 以像素ؓ单位Q图像高度的整型Q低?高位Q?
| | |
| 16 | 1 | 囑փ每像素存储占用位QbitQ数
| | |
| | |
| 17 | 1 | 囑փ描述W字?
| | | bits 3-0 - 每像素的属性位QbitQ数
| | |
| | | bit 4 - 保留Q必Mؓ 0
| | | bit 5 - 屏幕起始位置标志
| | | 0 = 原点在左下角
| | | 1 = 原点在左上角
| | | truevision 囑փ必须?0
| | | bits 7-6 - 交叉数据存储标志
| | | 00 = 无交?
| | | 01 = 两\?偶交?
| | | 10 = 四\交叉
| | | 11 = 保留
| | |
|--------|--------|------------------------------------------------------------
| 18 | 可变 | 囑փ信息字段
| | | 包含一个自由格式的Q长度是囑փ记录块偏U?0 处的字节中的
| | | 倹{它常常被忽略(卛_U?0 处gؓ 0 Q,注意其最大可?
| | | 含有 255 个字W。如果需要存储更多信息,可以攑֜囑փ数据
| | | 之后
| | |
|--------|--------|------------------------------------------------------------
| 可变 | 可变 | 颜色表数?
| | |
| | | 如果颜色表类型ؓ 0Q则该域不存在,否则过该域直接d
| | | 囑փ颜色表规g描述了每的字节敎ͼ?2Q?Q? 之一
| | |
|--------|--------|------------------------------------------------------------
| 可变 | 可变 | 囑փ数据?
| | |
| | | 本区域给ZQ宽度)xQ高度)个颜色表索引q些索引存放
| | | 在数据包中;有两中类型的数据包:run-length 数据包,
| | | 以及未加工的数据包,每种cd的数据包含有 1-字节的头信息Q?
| | | Q其中指Z数据包类型和数目Q,其后是可变长度的数据?
| | | 头信息中最高位?1 表示 run-length cd的数据包Q当
| | | 它ؓ 0 Ӟ表示未加工的数据?
| | |
| | | 对于 run-length 数据包,头信息含义如?
| | | __________________________________________________
| | | | 1 bit | 7 位的重复记数减一
| | | | id | ׃ 7 位表C的最大gؓ 127Q故最? |
| | | | | 的运行大ؓ 128Q(译注Q原文ؓ |
| | | | | the largest run sizeQ? |
| | | |-------|----------------------------------------|
| | | | 1 | c c c c c c c |
| | | --------------------------------------------------
| | |
| | | 对于未加工数据包Q头信息的含义如?
| | | __________________________________________________
| | | | 1 bit | 7 位的像素个数减一 |
| | | | id | ׃ 7 位表C的最大gؓ 127Q故? |
| | | | | cd的一个数据包中像素个C能大? |
| | | | | 128 |
| | | |-------|----------------------------------------|
| | | | 0 | n n n n n n n |
| | | --------------------------------------------------
| | |
| | |
| | | 对于 run length 数据包,头信息之后是一个简单颜色|
| | | 且假定该值重复的ơ数为头信息中记录的?
| | | run-length 数据包也怼跨越扫描U?
| | | Q扫描线起始于某行结束于下一行)
| | |
| | | 对于未加工数据包Q头信息之后是颜色|数目由头信息指出Q?
| | |
| | |
| | | 颜色表项自n?2-字节Q?-字节?4-字节几种大小Q分?
| | | 对应 TGA 16,TGA 24 ?TGA 32QŞ式如下:
| | |
| | |
| | | 3 字节表项中各字节依次对应 BLUEQGREENQRED
| | |
| | | 2 字节表项中,两个字节分解成如下Ş式:
| | | arrrrrgg gggbbbbb
| | | 但是Q由于低位在前,高位在后的存储顺序,从文件中d表项
| | | Ӟ先d gggbbbbb 而后d arrrrrgg Qa 表示属性位
| | |
| | | 4 字节表项包含了分别代?blue,green,red 及属性的四个
| | | 字节Q(׃g上的原因Q有的时?TGA 24 cd的图像也?
| | | TGA 32 cd的图像那样存?
| | |
--------------------------------------------------------------------------------
]]>
]]>
在J2MEq_上PNG囄格式几乎成ؓ了标准,无数台手持设备上q行的J2MEE序几乎都选用PNG来显C图像,包括大量的手机游戏以及手机应用,所以对PNG文g格式的了解,可以更有效的减少Jar SizeQ保护自有知识权?br> CoCoMo曄对PNG文gq行q一D|间的研究Q包括图像压~、解压以及加解密{,现将研究心得记录如下Q?
PNG文g格式Q?br> PNG文g格式分ؓPNG-24和PNG-8Q其最大的区别是PNG-24是用24位来保存一个像素|是真彩色Q而PNG-8是用8位烦引值来在调色盘中烦引一个颜Ԍ因ؓ一个烦引值的最大上限ؓ2?ơ方?28Q故调色盘中颜色数最多ؓ128U,所以该文g格式又被叫做PNG-8 128仿色?br> PNG-24因ؓ其图片容量过大,而且在Nokia和Moto{某些机型上创徏囄p|和显CZ正确{异常时有发生,有时q会严重拖慢昄速度Q故q不常用QCoCoMo认ؓq些异常和^台底层的囑փ解压不无关系。不q该格式最大的优点是可以保存Alpha通道Q同事也曾有q利用该囄格式实现Alpha混合的先例,x随着技术的发展Q手机硬件^台的提升QAlpha混合一定会被广泛的应用Q到那时该格式的最大优势才会真正发挥?br> PNG-8文g是目前广泛应用的PNG囑փ格式Q其主要有六大块l成Q?br>1.文g?br>2.IHDR?br>3.PLTE?br>4.tRNS?br>5.IDAT?br>6.文g?br>q六大块按顺序排列,也就是说IDAT块永q是在PLTE块之后,期间也会有许多其他的区块用来描述信息Q例如图像的最后修Ҏ间是多少Q图像的创徏者是谁等Q不q这些区块的信息Ҏ们来说都是可有可无的描述信息Q故压羃时一般先向这些区块开刀?/p>
除了文g_其中四大数据块和文gN是由l一的数据块文gl构描述的:
Chunk Length: 4byte
Chunk Type: 4byte
Chunk Data: Chunk Length的长?br> Chunk CRC: 4byte
例如IHDR块的数据长度?3Q既
Chunk Length = 13
Chunk Type = "IHDR"
用来标示PNG文gQؓ固定?4个字节:0x89504e47 0x0d0a1a0a
用来描述囑փ的基本信息,其格式ؓQ?br> 囑փ宽: 4byte
囑փ高: 4byte
囑փ色深Q?4byte
颜色cdQ?1byte
压羃ҎQ?1byte
滤LҎQ?1byte
扫描ҎQ?1byte
曄有h问过我,撒叫滤LҎ和扫描方法,汗,说实话我也不知道Q不q我们是在做手机游戏Q不是在搞图形学不是嘛?/p>
q个是传说中放|调色盘数据的地方啦Q其格式为:
循环
REDQ?nbsp; 1byte
GREENQ?byte
BLUEQ?nbsp; 1byte
END
循环长度嘛,不就是Chunk Length / 3的长度嘛Q而且Chunk Length一定ؓ3的倍数?/p>
q个块时有时无,主要是看你是否用了透明艌Ӏ该区块的格式ؓQ?br> 循环
if(对应调色盘颜色非透明)
0xFFQ?nbsp; 1byte
else
0x00Q?nbsp; 1byte
END
循环长度色盘的颜色数Q相当于调色盘颜色表的一个对应表Q标识该颜色是否透明Q?xFF不透明Q?x00透明。故如果用UltraEdit查看PNG文g的二q制~码Q如果看C大片FFQ一般就是tRNS区块啦,因ؓ一个PNG文g一般只有一个透明艌Ӏ?/p>
q个是存放囑փ数据的地方啦Q这里要注意的是一个PNG文g可能有多个IDAT区块Q而其他三大区块只可能有一个?br>IDAT区块是经q压~的Q所以数据不可读Q压~算法一般ؓLZ77滑动H口法Q如果硬要看里面的数据的话,用zlib库也是可以的QCoCoMo当年pqWindows Mobile上的帝国时代巨变态的用zlib库压~和解压该区块来q一步减PNG文g大小Q真是寸K寔R啊?/p>
该区块虽然也按照数据块的l构Q但Chunk Data是没有的Q所以是固定?6个字节:0x00000000 0x49454e44 0xae426082
Level3Q每个区块的Chunk Type我们是否需要呢Q很明显Q我们自己写的压~格式自己应该清楚是按照什么样的顺序,LQ?br>Level4Q每个区块的Chunk Length我们是否需要呢Q?br> IHDR块:定长13个字节,明显不需要,L?br> PLTE块:最?28个颜Ԍ为撒要用4byte来记录区块长度而不是用1byte来记录颜色数呢?
tRNS块:既然有颜色数QtRNS又是调色盘颜色表的对应表Q既数量与颜色数相同Qؓ撒还需要呢Q?br> IDAT块:我想q个是唯一需?byte来记录长度的区块?br>Level5Q每个区块的Chunk CRC是否需要呢Q?br> 因ؓ计算CRC需要一些时_但对于字节较的区块一般可以忽略不计,所以对于这个问题还是由E序员自己决定吧。对于CRC的计可以参看CoCoMo的另一Blog“PNG文g的CRC码计?#8221;
Level6Q每个区块我们是否要原封不动的保存期数据呢?
IHDR块:除了宽、高、色深是需要的Q后面那4byte的信息是固定?x03000000
PLTE块:为撒要用3byte来表CRGB而不?byte?65格式Q压~方法可以参看CoCoMo的另一Blog“关于PNG囑փ压羃的一Ҏ?#8221;
tRNS块:我想tRNS块是冗余最多的区块了吧Q大D大D늚0xFF明显没有必要Q一般的PNG文g只有一个透明Ԍ为撒要用对应表的Ҏ而不是一个烦引来记录到底哪个是透明色呢Q由于颜色数最?28Q所以只需1byte可以代替tRNS那么?xFF啦?br> IDAT块:么想法,如果你够变态,把zlib加进来吧Q?/p>
createImage(byte[] imageData, int imageOffset, int imageLength)
前提是传入的imageData与PNG未被压羃前的一致。因为PNG文g格式是固定的Q所以读取自定义的压~文件后Q开始将那些默认的数据再dq去Q实现解压的目的。下面就开始解压之旅吧!
首先要创Z个ByteArrayOutputStream outQ?br>1.写入文g_
out.writeInt(0x89504e47);
out.writeInt(0x0d0a1a0a);
2.写入IHDR?br>out.writeInt(13);
out.writeInt(0x49484452); //0x49484452为Chunk Type "IHDR"
out.writeInt(width);
out.writeInt(height);
out.writeByte(depth);
out.writeInt(0x03000000); //压羃时舍掉的4byteQ默?x03000000
out.writeInt(crc);
其他区块Ҏ一_故略q。。?br>3.写入文g?br>out.writeInt(0x00000000);
out.writeInt(0x49454e44);
out.writeInt(0xae426082);
4.转换成数l,创徏Image
byte[] pngBuffer = out.toByteArray();
Image image = Image.createImage(pngBuffer, 0, pngBuffer.length);
哈哈Q大功告成。这里注意如果中途数据写入有错误Q经怼出现创徏Imagep|的异常,而且非常不好调试Q不q只要自定的压羃格式定下来后Q对应的创徏Image的函数只要写一ơ,以后基本不会出问题哈?/p>
很多人都担心自己辛苦创作的漂亮的术囄很easyp别h拿到了,I其原因是由于PNG文g格式是固定的Q稍微了解的人用UltraEdit很容易就能找到IHDRQPLTE{标识了。CoCoMoq常看GameLoft的图像文Ӟ哈哈。一般是2byte的LengthQ然后紧接着囄数据Q都攑֜一个文仉Q直接拷?q制然后_脓C个新文g里就是一q图。后来的加密技术会把PNG分块Q例如前100个字节一块,紧接着1K一块,最后剩余字节一块,然后把块序打ؕQ用2byte来记录总长度,1byte记录序Q但是这q没有从Ҏ上消除IHDRQIENDq些昄的定位标识,好像在对破解者说Q嘿Q看Q我在q里Q?br> 现在了解了之前的压羃和解压技术,q个问题也就q刃而解了,因ؓChunk LengthQChunk Type和Chunk CRCq些东西都消׃Q甚臌数据块本w的数据都修改了Q我可以按照ImageWidth、ImageHeight、ImageDepth的顺序写数据Q也可以倒过来写。我惛_牛的PNG分析器也是无能ؓ力的吧,唯一可以定位的就只有IDAT区块了,不过q得到该区块的数据Q也应该是一张黑白图?br> 不过在加解密的领域真是道高一,高一丈,CoCoMo很希望和各位共同探讨Q共同提高!
]]>
一、下面我们来看看位图文gQ?/span>*.BMPQ的格式?/span>
位图文g主要分ؓ如下3个部分:
块名U?/font> |
对应Windowsl构体定?/span> |
大小Q?/span>ByteQ?/span> |
文g信息?/font> |
BITMAPFILEHEADER |
14 |
位图信息?/font> |
BITMAPINFOHEADER |
40 |
RGB颜色阵列 |
BYTE* |
由图像长宽尺寸决?/font> |
1?span> 文g信息?/span>BITMAPFILEHEADER
l构体定义如下:
typedef struct tagBITMAPFILEHEADER { /* bmfh */
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
其中Q?/font>
bfType |
说明文g的类型,该值必需?/span>0x4D42Q也是字符'BM'?/span> |
bfSize |
说明该位图文件的大小Q用字节为单?/span> |
bfReserved1 |
保留Q必设|ؓ0 |
bfReserved2 |
保留Q必设|ؓ0 |
bfOffBits |
说明从文件头开始到实际的图象数据之间的字节的偏U量。这个参数是非常有用的,因ؓ位图信息头和调色板的长度会根据不同情况而变化,所以你可以用这个偏UdD速的从文件中dC数据?/span> |
2?/font>位图信息?/span>BITMAPINFOHEADER
l构体定义如下:
typedef struct tagBITMAPINFOHEADER { /* bmih */
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
其中Q?/span>
biSize |
说明BITMAPINFOHEADERl构所需要的字数?/span> |
biWidth |
说明图象的宽度,以象素ؓ单位?/font> |
biHeight |
说明图象的高度,以象素ؓ单位。注Q这个值除了用于描q图像的高度之外Q它q有另一个用处,是指明该图像是倒向的位图,q是正向的位图。如果该值是一个正敎ͼ说明囑փ是倒向的,如果该值是一个负敎ͼ则说明图像是正向的。大多数?/span>BMP文g都是倒向的位图,也就是时Q高度值是一个正数?/span> |
biPlanes |
为目标设备说明位面数Q其值将L被设?/span>1?/span> |
biBitCount |
说明比特?/span>/象素Q其gؓ1?/span>4?/span>8?/span>16?/span>24、或32。但是由于我们^时用到的囑փl大部分?/span>24位和32位的Q所以我们讨两类囑փ?/span> |
biCompression |
说明图象数据压羃的类型,同样我们只讨论没有压~的cdQ?/span>BI_RGB?/span> |
biSizeImage |
说明图象的大,以字节ؓ单位。当?/span>BI_RGB格式Ӟ可设|ؓ0?/span> |
biXPelsPerMeter |
说明水^分L率,用象?/span>/cC?/span> |
biYPelsPerMeter |
说明垂直分L率,用象?/span>/cC?/span> |
biClrUsed |
说明位图实际使用的彩色表中的颜色索引敎ͼ设ؓ0的话Q则说明使用所有调色板)?/span> |
biClrImportant |
说明对图象显C有重要影响的颜色烦引的数目Q如果是0Q表C都重要?/span> |
3?/span>RGB颜色阵列
有关RGB三色I间我想大家都很熟悉Q这里我惌的是?/span>Windows下,RGB颜色阵列存储的格式其?/span>BGR。也是_对于24位的RGB位图像素数据格式是:
蓝色B?/span> |
l色G?/span> |
U色R?/span> |
对于32位的RGB位图像素数据格式是:
蓝色B?/span> |
l色G?/span> |
U色R?/span> |
透明通道A?/span> |
透明通道也称Alpha通道Q该值是该像素点的透明属性,取值在0Q全透明Q到255Q不透明Q之间。对?/span>24位的囑փ来说Q因为没?/span>Alpha通道Q故整个囑փ都不透明?/span>
二、搞清了文g格式Q下一步我们要实现加蝲?/font>
加蝲文g的目的是要得到图片属性,以及RGB数据Q然后可以将其绘制在DC?/span>(GDI)Q或是生成纹理对?/span>(3D:OpenGL/Direct3D)。这两种用途在数据处理上有点区别,我们主要按前一U用法讲Q在?/span>3D有不同的地方Q我们再提出来?/span>
1、加载文件头
//Load the file header
BITMAPFILEHEADER header;
memset(&header, 0, sizeof(header));
inf.read((char*)&header, sizeof(header));
if(header.bfType != 0x4D42)
return false;
q个很简单,没有什么好说的?/span>
2、加载位图信息头
//Load the image information header
BITMAPINFOHEADER infoheader;
memset(&infoheader, 0, sizeof(infoheader));
inf.read((char*)&infoheader, sizeof(infoheader));
m_iImageWidth = infoheader.biWidth;
m_iImageHeight = infoheader.biHeight;
m_iBitsPerPixel = infoheader.biBitCount;
q里我们得到?/span>3各重要的囑Ş属性:宽,高,以及每个像素颜色所占用的位数?/span>
3?/font>行对?/span>
׃Windows在进行行扫描的时候最的单位?/span>4个字节,所以当
囄?/span> X 每个像素的字节数 Q?/span>= 4的整数?/span>
时要在每行的后面补上~少的字节,?/span>0填充Q一般来说当囑փ宽度?/span>2的幂时不需要对齐)。位图文仉的数据在写入的时候已l进行了行对齐,也就是说加蝲的时候不需要再做行寚w。但是这样一来图片数据的长度׃是:?/span> X ?/span> X 每个像素的字节数 了,我们需要通过下面的方法计正的数据长度Q?/span>
//Calculate the image data size
int iLineByteCnt = (((m_iImageWidth*m_iBitsPerPixel) + 31) >> 5) << 2;
m_iImageDataSize = iLineByteCnt * m_iImageHeight;
4?/font>加蝲囄数据
对于24位和32位的位图文gQ位图数据的偏移量ؓsizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)Q也是说现在我们可以直接读取图像数据了?/span>
if(m_pImageData) delete []m_pImageData;
m_pImageData = new unsigned char[m_iImageDataSize];
inf.read((char*)m_pImageData, m_iImageDataSize);
如果你够细心,׃发现内存m_pImageData里的数据的确?/span>BGR格式Q可以用个纯蓝色或者是U红色的囄试一下?/span>
5?/font>l制
好了Q数据和属性我们都有了Q现在就可以拿来随便用了Q就和吃馒头一Pq白糖_白p,qU糖_红p。下面是我的GDIl制代码Q仅作参考?/span>
void CImage::DrawImage(HDC hdc, int iLeft, int iTop, int iWidth, int iHeight)
{
if(!hdc || m_pImageData == NULL)
return;
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
bmi.bmiHeader.biWidth = m_iImageWidth;
bmi.bmiHeader.biHeight = m_iImageHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = m_iBitsPerPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = m_iImageDataSize;
StretchDIBits(hdc, iLeft, iTop, iWidth, iHeight,
0, 0, m_iImageWidth, m_iImageHeight,
m_pImageData, &bmi, DIB_RGB_COLORS, SRCCOPY);
}
6?/span>3D(OpenGL)的不同之?/span>
如果你是想用刚才我们得到的数据生成纹理对象,那么你还要请Z面的问题?/font>
首先Q用来生成纹理的数据不需要对齐,也就是说不能在每行的后面加上寚w的字节。当然在OpenGL里要求纹理图片的寸?/span>2的幂Q所以这个问题实际上不存在;
其次Q我们得到的囑Ş数据格式?/span>BGR(BGRA)Q所以在生成U理的时候,需指定格式?/span>GL_BGR_EXT(GL_BGRA_EXT)Q否则需要做BGR->RGB(BGRA->RGBA)的{?/span>
位图文g的组?/p> |
l构名称 |
W号 |
位图文g?bitmap-file header) | BITMAPFILEHEADER | bmfh |
位图信息?bitmap-information header) | BITMAPINFOHEADER | bmih |
彩色?color table) | RGBQUAD | aColors[] |
图象数据阵列字节 | BYTE | aBitmapBits[] |
位图文gl构可综合在?-01中?/p>
?1 位图文gl构内容摘要
偏移?/p> |
域的名称 |
大小 |
内容 |
|||||||||
图象文g ?/p> |
0000h | 文g标识 | 2 bytes | 两字节的内容用来识别位图的类型:
‘BM’ Q?Windows 3.1x, 95, NT, … ‘BA’ QOS/2 Bitmap Array ‘CI’ QOS/2 Color Icon ‘CP’ QOS/2 Color Pointer ‘IC’ Q?OS/2 Icon ‘PT’ QOS/2 Pointer 注:因ؓOS/2pȝq没有被普及开Q所以在~程Ӟ你只需判断W一个标?#8220;BM”p?/p> |
||||||||
0002h | File Size | 1 dword | 用字节表C的整个文g的大?/td> | |||||||||
0006h | Reserved | 1 dword | 保留Q必设|ؓ0 | |||||||||
000Ah | Bitmap Data Offset | 1 dword | 从文件开始到位图数据开始之间的数据(bitmap data)之间的偏U量 | |||||||||
000Eh | Bitmap Header Size | 1 dword | 位图信息?Bitmap Info Header)的长度,用来描述位图的颜艌Ӏ压~方法等。下面的长度表示Q?
28h - Windows 3.1x, 95, NT, … 0Ch - OS/2 1.x F0h - OS/2 2.x 注:在Windows95?8?000{?font color=#0000ff>操作pȝ中,位图信息头的长度q不一定是28hQ因为微软已l制定出了新的BMP文g格式Q其中的信息头结构变化比较大Q长度加ѝ所以最好不要直接用常?8hQ而是应该从具体的文g中读取这个倹{这h能确保程序的兼容性?/p> |
|||||||||
0012h | Width | 1 dword | 位图的宽度,以象素ؓ单位 | |||||||||
0016h | Height | 1 dword | 位图的高度,以象素ؓ单位 | |||||||||
001Ah | Planes | 1 word | 位图的位面数Q注Q该值将L1Q?/td> | |||||||||
图象 信息 ?/p>
|
001Ch | Bits Per Pixel | 1 word | 每个象素的位?
1 - 单色位图Q实际上可有两种颜色Q缺省情况下是黑色和白色。你可以自己定义q两U颜Ԍ 4 - 16 色位?/p> 8 - 256 色位?/p> 16 - 16bit 高彩色位?/p> 24 - 24bit 真彩色位?/p> 32 - 32bit 增强型真彩色位图 |
||||||||
001Eh | Compression | 1 dword | 压羃说明Q?
0 - 不压~?(使用BI_RGB表示) 1 - RLE 8-使用8位RLE压羃方式(用BI_RLE8表示) 2 - RLE 4-使用4位RLE压羃方式(用BI_RLE4表示) 3 - Bitfields-位域存放方式(用BI_BITFIELDS表示) |
|||||||||
0022h | Bitmap Data Size | 1 dword | 用字节数表示的位图数据的大小。该数必L4的倍数 | |||||||||
0026h | HResolution | 1 dword | 用象?cC的水^分L?/td> | |||||||||
002Ah | VResolution | 1 dword | 用象?cC的垂直分L?/td> | |||||||||
002Eh | Colors | 1 dword | 位图使用的颜色数。如8-比特/象素表示?00h或?256. | |||||||||
0032h | Important Colors | 1 dword | 指定重要的颜色数。当该域的值等于颜色数Ӟ或者等?ӞQ表C所有颜色都一样重?/td> | |||||||||
调色板数?/td> | ҎBMP版本的不同而不?/td> | Palette | N * 4 byte | 调色板规范。对于调色板中的每个表项Q这4个字节用下述Ҏ来描qRGB的|
|
||||||||
图象数据 | ҎBMP版本及调色板寸的不同而不?/td> | Bitmap Data | xxx bytes | 该域的大取决于压羃Ҏ及图像的寸和图像的位深度,它包含所有的位图数据字节Q这些数据可能是彩色调色板的索引P也可能是实际的RGB|q将Ҏ囑փ信息头中的位深度值来军_?/td> |
1. 位图文g?/p> 位图文g头包含有关于文gcd、文件大、存放位|等信息Q在Windows 3.0以上版本的位图文件中用BITMAPFILEHEADERl构来定义: typedef struct tagBITMAPFILEHEADER { /* bmfh */ UINT bfType; } BITMAPFILEHEADER;
其中Q?
2. 位图信息?/p> 位图信息用BITMAPINFOl构来定义,它由位图信息?bitmap-information header)和彩色表(color table)l成Q前者用BITMAPINFOHEADERl构定义Q后者用RGBQUADl构定义。BITMAPINFOl构h如下形式Q?/p> typedef struct tagBITMAPINFO { /* bmi */ BITMAPINFOHEADER bmiHeader; } BITMAPINFO;
其中Q?
BITMAPINFOHEADERl构包含有位图文件的大小、压~类型和颜色格式Q其l构定义为: typedef struct tagBITMAPINFOHEADER { /* bmih */ DWORD biSize; } BITMAPINFOHEADER;
其中Q?
现就BITMAPINFOHEADERl构作如下说明: (1) 彩色表的定位 应用E序可用存储在biSize成员中的信息来查扑֜BITMAPINFOl构中的彩色表,如下所C: pColor = ((LPSTR) pBitmapInfo + (WORD) (pBitmapInfo->bmiHeader.biSize)) (2) biBitCount biBitCount=1 表示位图最多有两种颜色Q缺省情况下是黑色和白色Q你也可以自己定义这两种颜色。图像信息头装调色板中将有两个调色板,UCؓ索引0和烦?。图象数据阵列中的每一位表CZ个象素。如果一个位?Q显C时׃用烦?的RGB|如果位是1Q则使用索引1的RGB倹{?/p> biBitCount=4 表示位图最多有16U颜艌Ӏ每个象素用4位表C,q用q?位作为彩色表的表Ҏ查找该象素的颜色。例如,如果位图中的W一个字节ؓ0x1FQ它表示有两个象素,W一象素的颜色就在彩色表的第2表项中查找,而第二个象素的颜色就在彩色表的第16表项中查找。此Ӟ调色板中~省情况下会?6个RGBV对应于索引0到烦?5?/p> biBitCount=8 表示位图最多有256U颜艌Ӏ每个象素用8位表C,q用q?位作为彩色表的表Ҏ查找该象素的颜色。例如,如果位图中的W一个字节ؓ0x1FQ这个象素的颜色在彩色表的W?2表项中查找。此Ӟ~省情况下,调色板中会有256个RGB,对应于烦?到烦?55?/p> biBitCount=16 表示位图最多有216U颜艌Ӏ每个色素用16位(2个字节)表示。这U格式叫作高彩色Q或叫增强型16位色Q或64K艌Ӏ它的情冉|较复杂,当biCompression成员的值是BI_RGBӞ它没有调色板?6位中Q最低的5位表C色分量,中间?位表C绿色分量,高的5位表C红色分量,一共占用了15位,最高的一位保留,设ؓ0。这U格式也被称?55 16位位图。如果biCompression成员的值是BI_BITFIELDSQ那么情况就复杂了,首先是原来调色板的位|被三个DWORD变量占据Q称为红、绿、蓝掩码。分别用于描q红、绿、蓝分量?6位中所占的位置。在Windows 95Q或98Q中Q系l可接受两种格式的位域:555?65Q在555格式下,U、绿、蓝的掩码分别是Q?x7C00?x03E0?x001FQ而在565格式下,它们则分别ؓQ?xF800?x07E0?x001F。你在读取一个像素之后,可以分别用掩?#8220;?#8221;上像素|从而提取出惌的颜色分量(当然q要再经q适当的左右移操作Q。在NTpȝ中,则没有格式限Ӟ只不q要求掩码之间不能有重叠。(注:q种格式的图像用v来是比较ȝ的,不过因ؓ它的昄效果接近于真彩,而图像数据又比真彩图像小的多Q所以,它更多的被用于游戏YӞ?/p> biBitCount=24 表示位图最多有224U颜艌Ӏ这U位图没有调色板QbmiColors成员寸?Q,在位数组中,?个字节代表一个象素,分别对应于颜色R、G、B?/p> biBitCount=32 表示位图最多有232U颜艌Ӏ这U位囄l构?6位位囄构非常类|当biCompression成员的值是BI_RGBӞ它也没有调色板,32位中?4位用于存放RGB|序是:最高位—保留,U?位、绿8位、蓝8位。这U格式也被成?88 32位图。如?biCompression成员的值是BI_BITFIELDSӞ原来调色板的位置被三个DWORD变量占据Q成为红、绿、蓝掩码Q分别用于描q红、绿、蓝分量?2位中所占的位置。在Windows 95(or 98)中,pȝ只接?88格式Q也是说三个掩码的值将只能是:0xFF0000?xFF00?xFF。而在NTpȝ中,你只要注意掩码之间不生重叠就行。(注:q种囑փ格式比较规整Q因为它是DWORD寚w的,所以在内存中进行图像处理时可进行汇~的代码优化(单)Q?/p> (3) ClrUsed BITMAPINFOHEADERl构中的成员ClrUsed指定实际使用的颜色数目。如果ClrUsed讄?Q位图用的颜色数目q于biBitCount成员中的数目。请注意Q如果ClrUsed的g是可用颜色的最大值或不是0Q则在编E时应该注意调色板尺寸的计算Q比如在4位位图中Q调色板的缺省尺寸应该是16Qsizeof(RGBQUAD)Q但是,如果ClrUsed的g?6或者不?Q那么调色板的尺寸就应该是ClrUsedQsizeof(RGBQUAD)?/p> (4) 图象数据压羃 ?BI_RLE8Q每个象素ؓ8比特的RLE压羃~码Q可使用~码方式和绝Ҏ式中的Q何一U进行压~,q两U方式可在同一q图中的M地方使用?/p> ~码方式Q由2个字节组成,W一个字节指定用相同颜色的象素数目Q第二个字节指定使用的颜色烦引。此外,q个字节对中的第一个字节可讄?Q联合用第二个字节的DC:
l对方式Q第一个字节设|ؓ0Q而第二个字节讄?x03?xFF之间的一个倹{在q种方式中,W二个字节表C在这个字节后面的字节敎ͼ每个字节包含单个象素的颜色烦引。压~数据格式需要字边界(word boundary)寚w。下面的例子是用16q制表示?-位压~图象数据: 03 04 05 06 00 03 45 56 67 00 02 78 00 02 05 01 02 78 00 00 09 1E 00 01
?BI_RLE4Q每个象素ؓ4比特的RLE压羃~码Q同样也可用编码方式和l对方式中的M一U进行压~,q两U方式也可在同一q图中的M地方使用。这两种方式是: ~码方式Q由2个字节组成,W一个字节指定象素数目,W二个字节包含两U颜色烦引,一个在?位,另一个在?位。第一个象素用高4位的颜色索引Q第二个使用?位的颜色索引Q第3个用高4位的颜色索引Q依此类推?/p> l对方式Q这个字节对中的W一个字节设|ؓ0Q第二个字节包含有颜色烦引数Q其后箋字节包含有颜色烦引,颜色索引存放在该字节的高、低4位中Q一个颜色烦引对应一个象素。此外,BI_RLE4也同栯合用第二个字节中的DC:
下面的例子是?6q制数表C的4-位压~图象数据: 03 04 05 06 00 06 45 56 67 00 04 78 00 02 05 01 04 78 00 00 09 1E 00 01 q些压羃数据可解释ؓ Q?/p>
3. 彩色?/p> 彩色表包含的元素与位图所h的颜色数相同Q象素的颜色用RGBQUADl构来定义。对?4-位真彩色图象׃使用彩色表(同样也包?6位、和32位位图)Q因Z图中的RGB值就代表了每个象素难?Q噬 械难丈 ׃ 闹匾 耘判?饪梢ѝ 允厩 l蛭 荒芟允咀愎欢嘌丈 南允旧璞赶允静噬 枯 GBQUADl构描述由R、G、B相对强度l成的颜Ԍ定义如下Q?/p> typedef struct tagRGBQUAD { /* rgbq */ BYTE rgbBlue; } RGBQUAD;
其中Q?
4. 位图数据 紧跟在彩色表之后的是图象数据字节阵列。图象的每一扫描行由表示图象象素的连l的字节l成Q每一行的字节数取决于图象的颜色数目和用象素表C的图象宽度。扫描行是由底向上存储的Q这是_阵列中的W一个字节表CZ囑ַ下角的象素,而最后一个字节表CZ囑֏上角的象素。(只针对与倒向DIBQ如果是正向DIBQ则扫描行是由顶向下存储的)Q倒向DIB的原点在囑փ的左下角Q而正向DIB的原点在囑փ的左上角。同Ӟ每一扫描行的字节数必需?的整倍数Q也是DWORD寚w的。如果你想确保图像的扫描行DWORD寚wQ可使用下面的代码: |