程序的思路----显示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;
 }



posted on 2008-05-22 18:26  DavidHu  阅读(1935)  评论(0编辑  收藏  举报

导航