信息来源——http://www.onicos.com/staff/iz/formats/gif.html#header http://www.onicos.com/staff/iz/formats/gif.html#header
In GIFimages 实际图像尺寸(宽度、高度)存储在图像块中。据我所知图像块是标头中包含的第一个块。
在实际块开始之前,有一个称为全局颜色表(0..255 x 3 字节)(从现在开始GCT)。如果我能知道保留的字节数GCT我可以从中提取字节 5-9图像块并具有实际图像尺寸。
问题:我怎样才能知道/了解的尺寸是多少GCT?
OR
哪里有GCT end?
OR
哪里有图像块 begin?
OR
哪里有图像块 end?
您可以在这里找到 gif enc/dec 所需的一切3MF 项目 GIF http://www.matthewflickinger.com/lab/whatsinagif/lzw_image_data.asp
-
GCT
该块是可选的,并不总是出现在GIF文件。尺寸由颜色数量和位宽决定GIF标头。我像这样解码/加载它:
struct _hdr
{
// Header
BYTE Signature[3]; /* Header Signature (always "GIF") */
BYTE Version[3]; /* GIF format version("87a" or "89a") */
// Logical Screen Descriptor
WORD xs;
WORD ys;
BYTE Packed; /* Screen and Color Map Information */
BYTE BackgroundColor; /* Background Color Index */
BYTE AspectRatio; /* Pixel Aspect Ratio */
} hdr;
gcolor_bits= (hdr.Packed &7)+1; // global pallete
scolor_bits=((hdr.Packed>>4)&7)+1; // screen
_gcolor_sorted =hdr.Packed&8;
_gcolor_table =hdr.Packed&128;
scolors=1<<scolor_bits;
gcolors=1<<gcolor_bits;
- if
_gcolor_table
那么是真的GCT存在
-
GCT尺寸是
3*gcolors
[字节]按顺序存储R,G,B
-
图像开始
这有点棘手,因为GIF89a文件可能包含许多可选块。您需要进行解码循环检测块的类型并根据其目的解码/跳过它。我这样做:
struct _gfxext
{
BYTE Introducer; /* Extension Introducer (always 21h) */
BYTE Label; /* Graphic Control Label (always F9h) */
BYTE BlockSize; /* Size of remaining fields (always 04h) */
BYTE Packed; /* Method of graphics disposal to use */
WORD DelayTime; /* Hundredths of seconds to wait */
BYTE ColorIndex; /* Transparent Color Index */
BYTE Terminator; /* Block Terminator (always 0) */
} gfx;
struct _txtext
{
BYTE Introducer; /* Extension Introducer (always 21h) */
BYTE Label; /* Extension Label (always 01h) */
BYTE BlockSize; /* Size of Extension Block (always 0Ch) */
WORD TextGridLeft; /* X position of text grid in pixels */
WORD TextGridTop; /* Y position of text grid in pixels */
WORD TextGridWidth; /* Width of the text grid in pixels */
WORD TextGridHeight; /* Height of the text grid in pixels */
BYTE CellWidth; /* Width of a grid cell in pixels */
BYTE CellHeight; /* Height of a grid cell in pixels */
BYTE TextFgColorIndex; /* Text foreground color index value */
BYTE TextBgColorIndex; /* Text background color index value */
// BYTE *PlainTextData; /* The Plain Text data */
// BYTE Terminator; /* Block Terminator (always 0) */
};
struct _remext
{
BYTE Introducer; /* Extension Introducer (always 21h) */
BYTE Label; /* Comment Label (always FEh) */
// BYTE *CommentData; /* Pointer to Comment Data sub-blocks */
// BYTE Terminator; /* Block Terminator (always 0) */
};
struct _appext
{
BYTE Introducer; /* Extension Introducer (always 21h) */
BYTE Label; /* Extension Label (always FFh) */
BYTE BlockSize; /* Size of Extension Block (always 0Bh) */
CHAR Identifier[8]; /* Application Identifier */
BYTE AuthentCode[3]; /* Application Authentication Code */
// BYTE *ApplicationData; /* Point to Application Data sub-blocks */
// BYTE Terminator; /* Block Terminator (always 0) */
};
// handle 89a extensions blocks
_gfxext gfxext; gfxext.Introducer=0;
_txtext txtext; txtext.Introducer=0;
_remext remext; remext.Introducer=0;
_appext appext; appext.Introducer=0;
if((hdr.Version[0]=='8')
&&(hdr.Version[1]=='9')
&&(hdr.Version[2]=='a')) _89a=true; else _89a=false;
if (_89a)
for (;!f.eof;)
{
f.peek((BYTE*)&dw,2);
if (dw==0xF921) { f.read((BYTE*)&gfxext,sizeof(_gfxext)); }
else if (dw==0x0121) { f.read((BYTE*)&txtext,sizeof(_txtext)); for (;!f.eof;) { f.read(&db,1); if (!db) break; f.read(dat,DWORD(db)); } }
else if (dw==0xFE21) { f.read((BYTE*)&remext,sizeof(_remext)); for (;!f.eof;) { f.read(&db,1); if (!db) break; f.read(dat,DWORD(db)); } }
else if (dw==0xFF21) { f.read((BYTE*)&appext,sizeof(_appext)); for (;!f.eof;) { f.read(&db,1); if (!db) break; f.read(dat,DWORD(db)); } }
else if ((dw&0x00FF)==0x0021) return; // corrupted file
else break; // no extension found
}
-
db
是 BYTE 变量
-
dw
是 WORD 变量
-
f
是我的文件缓存类,成员是不言自明的,我希望无论如何:
-
f.read(&data,size)
read size
字节进入data
-
f.peek(&data,size)
执行相同操作,但不更新文件中的位置
-
f.eof
表示已到达文件末尾
在所有图像标头开始之后,必须对每一帧执行此操作。
-
图片结尾
图像块以终止符结束。所有图像块都以BYTE
数数。如果是zero
它是一个终止块。通常图像后面有几个BYTES
不被使用LZW数据,因此在填充整个图像区域后,跳过所有块,直到达到零大小的块,然后停止,即图像结束。如果BYTE
在这之后是0x3B
十六进制,您已到达末尾GIF file
[notes]
不要忘记封装结构体#pragma pack(1)
and #pragma pack()
或手动设置align to 1 BYTE
。当心有符号数据类型的问题(LZW数据是无符号的),因此可以在可以避免问题的地方进行重写,或者仅使用无符号变量(具有足够的位宽)进行解码
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)