程序的思路----显示GIF,BMP,JPG,的类CPictureEx
这是我自己整理的,希望能给大家带去帮助。
Written by Oleg Bykov
Copyright (c) 2001
程序的思路:
1。Load(LPCTSTR szFileName) 是第一部,先把图片的内容全部读到memory中。 接着调用下一个Load(HGLOBAL hGlobal, DWORD dwSize)
2。Load(HGLOBAL hGlobal, DWORD dwSize)开始,先取它的头,根据 m_pGIFHeader来判断是不是GIF(87a和89a),如果不是GIF,用最普通的方法显示出图片来。如果是,那么要计算全局颜色列表。接着用循环语句
while (SkipNextGraphicBlock())
nFrameCount++;
判断这个GIF里面有几帧。如果是一帧,那么表明是87a,就用最普通的方法把它显示出来,如果是多帧,表明是89a,那么就可以用下面的方法显示:
ResetDataPointer(); 这个方法是重掷整个GIF的指针,m_nCurrOffset = sizeof(TGIFHeader)+sizeof(TGIFLSDescriptor)+m_nGlobalCTSize; 让它指向全局颜色列表的下一个位置。然后用GetNextGraphicBlock这个方法,每当得到一块图片数据区的时候就把它封装成一帧,然后再把每一帧转成IPicture的对象,加到m_arrFrames[],到显示的时候用。(IPicture是VC中自带的接口,用来处理bitmaps, icons, and metafiles)。接着调用PrepareDC(m_PictureSize.cx,m_PictureSize.cy);
3。最后是Draw()显示。如果是动态GIF的话,就用线程,按照当时在GetNextGraphicBlock()方法中在每一块图象数据块对应的 BLOCK_CONTROLEXT中取到的m_wDelayTime(时间),把m_arrFrames[]里面的帧一个一个显示出来。
这就是整个的过程。我现在是要找到注释块。我用的方法是GetCommentExt(),是在判断(如果它有多张数据图片区)后调用的。具体的位置是在Load(HGLOBAL hGlobal, DWORD dwSize)中的if (nFrameCount == 1)的else 中调用的。
自己定义的固定块的表示符
enum GIFBlockTypes
{
BLOCK_UNKNOWN,
BLOCK_APPEXT,
BLOCK_COMMEXT,
BLOCK_CONTROLEXT,
BLOCK_PLAINTEXT,
BLOCK_IMAGE,
BLOCK_TRAILER
};
下面的是每一块的结构体
struct TGIFHeader // GIF header
{
char m_cSignature[3]; // Signature - Identifies the GIF Data Stream
// This field contains the fixed value 'GIF'
char m_cVersion[3]; // Version number. May be one of the following:
// "87a" or "89a"
};
struct TGIFLSDescriptor // Logical Screen Descriptor
{
WORD m_wWidth; // 2 bytes. Logical screen width
WORD m_wHeight; // 2 bytes. Logical screen height
unsigned char m_cPacked; // packed field
unsigned char m_cBkIndex; // 1 byte. Background color index
unsigned char m_cPixelAspect; // 1 byte. Pixel aspect ratio
inline int GetPackedValue(enum LSDPackedValues Value);
};
struct TGIFAppExtension // application extension block
{
unsigned char m_cExtIntroducer; // extension introducer (0x21)
unsigned char m_cExtLabel; // app. extension label (0xFF)
unsigned char m_cBlockSize; // fixed value of 11
char m_cAppIdentifier[8]; // application identifier
char m_cAppAuth[3]; // application authentication code
};
struct TGIFControlExt // graphic control extension block
{
unsigned char m_cExtIntroducer; // extension introducer (0x21)
unsigned char m_cControlLabel; // control extension label (0xF9)
unsigned char m_cBlockSize; // fixed value of 4
unsigned char m_cPacked; // packed field
WORD m_wDelayTime; // delay time
unsigned char m_cTColorIndex; // transparent color index
unsigned char m_cBlockTerm; // block terminator (0x00)
public:
inline int GetPackedValue(enum ControlExtValues Value);
};
struct TGIFCommentExt // comment extension block
{
unsigned char m_cExtIntroducer; // extension introducer (0x21)
unsigned char m_cCommentLabel; // comment extension label (0xFE)
};
struct TGIFPlainTextExt // plain text extension block
{
unsigned char m_cExtIntroducer; // extension introducer (0x21)
unsigned char m_cPlainTextLabel; // text extension label (0x01)
unsigned char m_cBlockSize; // fixed value of 12
WORD m_wLeftPos; // text grid left position
WORD m_wTopPos; // text grid top position
WORD m_wGridWidth; // text grid width
WORD m_wGridHeight; // text grid height
unsigned char m_cCellWidth; // character cell width
unsigned char m_cCellHeight; // character cell height
unsigned char m_cFgColor; // text foreground color index
unsigned char m_cBkColor; // text background color index
};
struct TGIFImageDescriptor // image descriptor block
{
unsigned char m_cImageSeparator; // image separator byte (0x2C)
WORD m_wLeftPos; // image left position
WORD m_wTopPos; // image top position
WORD m_wWidth; // image width
WORD m_wHeight; // image height
unsigned char m_cPacked; // packed field
inline int GetPackedValue(enum IDPackedValues Value);
};
我用的查询语句是:
BOOL CPictureEx::GetCommentExt()
{
enum GIFBlockTypes nBlock;
nBlock = GetNextBlock();
while( (nBlock != BLOCK_COMMEXT) &&
(nBlock != BLOCK_TRAILER) )
{
if(!SkipNextBlock())
return NULL;
nBlock = GetNextBlock();
}
if(nBlock == BLOCK_COMMEXT)
{
//如果找到了,就用指针m_pCommentExt指向这块,准备加载数据。gifcommentext_size 是用来判断的。
m_pCommentExt =
reinterpret_cast<unsigned char *> (&m_pRawData[m_nCurrOffset]);
gifcommentext_size = GetNextBlockLen() - 2;
//AfxMessageBox()没有意义,是测试用的。
AfxMessageBox("文件太大,无法嵌入到GIF图片中!");
}
if(nBlock == BLOCK_TRAILER)
{
return NULL;
}
return TRUE;
}
Written by Oleg Bykov
Copyright (c) 2001
程序的思路:
1。Load(LPCTSTR szFileName) 是第一部,先把图片的内容全部读到memory中。 接着调用下一个Load(HGLOBAL hGlobal, DWORD dwSize)
2。Load(HGLOBAL hGlobal, DWORD dwSize)开始,先取它的头,根据 m_pGIFHeader来判断是不是GIF(87a和89a),如果不是GIF,用最普通的方法显示出图片来。如果是,那么要计算全局颜色列表。接着用循环语句
while (SkipNextGraphicBlock())
nFrameCount++;
判断这个GIF里面有几帧。如果是一帧,那么表明是87a,就用最普通的方法把它显示出来,如果是多帧,表明是89a,那么就可以用下面的方法显示:
ResetDataPointer(); 这个方法是重掷整个GIF的指针,m_nCurrOffset = sizeof(TGIFHeader)+sizeof(TGIFLSDescriptor)+m_nGlobalCTSize; 让它指向全局颜色列表的下一个位置。然后用GetNextGraphicBlock这个方法,每当得到一块图片数据区的时候就把它封装成一帧,然后再把每一帧转成IPicture的对象,加到m_arrFrames[],到显示的时候用。(IPicture是VC中自带的接口,用来处理bitmaps, icons, and metafiles)。接着调用PrepareDC(m_PictureSize.cx,m_PictureSize.cy);
3。最后是Draw()显示。如果是动态GIF的话,就用线程,按照当时在GetNextGraphicBlock()方法中在每一块图象数据块对应的 BLOCK_CONTROLEXT中取到的m_wDelayTime(时间),把m_arrFrames[]里面的帧一个一个显示出来。
这就是整个的过程。我现在是要找到注释块。我用的方法是GetCommentExt(),是在判断(如果它有多张数据图片区)后调用的。具体的位置是在Load(HGLOBAL hGlobal, DWORD dwSize)中的if (nFrameCount == 1)的else 中调用的。
自己定义的固定块的表示符
enum GIFBlockTypes
{
BLOCK_UNKNOWN,
BLOCK_APPEXT,
BLOCK_COMMEXT,
BLOCK_CONTROLEXT,
BLOCK_PLAINTEXT,
BLOCK_IMAGE,
BLOCK_TRAILER
};
下面的是每一块的结构体
struct TGIFHeader // GIF header
{
char m_cSignature[3]; // Signature - Identifies the GIF Data Stream
// This field contains the fixed value 'GIF'
char m_cVersion[3]; // Version number. May be one of the following:
// "87a" or "89a"
};
struct TGIFLSDescriptor // Logical Screen Descriptor
{
WORD m_wWidth; // 2 bytes. Logical screen width
WORD m_wHeight; // 2 bytes. Logical screen height
unsigned char m_cPacked; // packed field
unsigned char m_cBkIndex; // 1 byte. Background color index
unsigned char m_cPixelAspect; // 1 byte. Pixel aspect ratio
inline int GetPackedValue(enum LSDPackedValues Value);
};
struct TGIFAppExtension // application extension block
{
unsigned char m_cExtIntroducer; // extension introducer (0x21)
unsigned char m_cExtLabel; // app. extension label (0xFF)
unsigned char m_cBlockSize; // fixed value of 11
char m_cAppIdentifier[8]; // application identifier
char m_cAppAuth[3]; // application authentication code
};
struct TGIFControlExt // graphic control extension block
{
unsigned char m_cExtIntroducer; // extension introducer (0x21)
unsigned char m_cControlLabel; // control extension label (0xF9)
unsigned char m_cBlockSize; // fixed value of 4
unsigned char m_cPacked; // packed field
WORD m_wDelayTime; // delay time
unsigned char m_cTColorIndex; // transparent color index
unsigned char m_cBlockTerm; // block terminator (0x00)
public:
inline int GetPackedValue(enum ControlExtValues Value);
};
struct TGIFCommentExt // comment extension block
{
unsigned char m_cExtIntroducer; // extension introducer (0x21)
unsigned char m_cCommentLabel; // comment extension label (0xFE)
};
struct TGIFPlainTextExt // plain text extension block
{
unsigned char m_cExtIntroducer; // extension introducer (0x21)
unsigned char m_cPlainTextLabel; // text extension label (0x01)
unsigned char m_cBlockSize; // fixed value of 12
WORD m_wLeftPos; // text grid left position
WORD m_wTopPos; // text grid top position
WORD m_wGridWidth; // text grid width
WORD m_wGridHeight; // text grid height
unsigned char m_cCellWidth; // character cell width
unsigned char m_cCellHeight; // character cell height
unsigned char m_cFgColor; // text foreground color index
unsigned char m_cBkColor; // text background color index
};
struct TGIFImageDescriptor // image descriptor block
{
unsigned char m_cImageSeparator; // image separator byte (0x2C)
WORD m_wLeftPos; // image left position
WORD m_wTopPos; // image top position
WORD m_wWidth; // image width
WORD m_wHeight; // image height
unsigned char m_cPacked; // packed field
inline int GetPackedValue(enum IDPackedValues Value);
};
我用的查询语句是:
BOOL CPictureEx::GetCommentExt()
{
enum GIFBlockTypes nBlock;
nBlock = GetNextBlock();
while( (nBlock != BLOCK_COMMEXT) &&
(nBlock != BLOCK_TRAILER) )
{
if(!SkipNextBlock())
return NULL;
nBlock = GetNextBlock();
}
if(nBlock == BLOCK_COMMEXT)
{
//如果找到了,就用指针m_pCommentExt指向这块,准备加载数据。gifcommentext_size 是用来判断的。
m_pCommentExt =
reinterpret_cast<unsigned char *> (&m_pRawData[m_nCurrOffset]);
gifcommentext_size = GetNextBlockLen() - 2;
//AfxMessageBox()没有意义,是测试用的。
AfxMessageBox("文件太大,无法嵌入到GIF图片中!");
}
if(nBlock == BLOCK_TRAILER)
{
return NULL;
}
return TRUE;
}