кодек GIF
От: LongWalker Россия  
Дата: 03.06.03 14:17
Оценка:
Прив

Народ, начал писать декодер GIF и заткнулся на распаковке LZW. Исходники прицеплены. Кто-нить может подсказать чо-нить дельное? С чего начать ( см. Decode() ).
///////////////////////////////////////////////////////////////////////////////
//
// Класс поддержки декодирования GIF в BMP и загрузки BMP из ресурсов
// Описание типов
//
// Copyright (C) 2003, Bank's soft systems
// Copyright (C) 1992, 1999 - 2003, Alexander Butenko | butenko@bssys.com
// All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#if !defined(_45B05C1F_FBA8_4f6a_8356_ADAFD7AD416F)
#define _45B05C1F_FBA8_4f6a_8356_ADAFD7AD416F

#include "stdafx.h"
#include <malloc.h>
#include <math.h>
#include <atlsimpcoll.h>

namespace GifImageTypes
{
    typedef            DWORD                    ARGB;

    struct ColorPalette
    {
        UINT Flags;             // Palette flags
        UINT Count;             // Number of color entries
        ARGB Entries[1];        // Palette color entries
    };

    struct GifHeader
    {
        BYTE    ID[3];            // GIF
        BYTE    Ver[3];            // 87a | 89a
    };

    // size 7 (has no ID)
    struct GifLogScreenDescriptor
    {
        USHORT    width;            // Width of the log screen
        USHORT    height;            // Heigth of the log screen
        // bit field
        BYTE    GCT: 1;            // Flag of global color table (GCT)
        BYTE    BPP: 3;            // Bits per pixel (color resolution)
        BYTE    sort: 1;        // Flag of sorting
        BYTE    GCT_size: 3;    // Size of GCT
        // end of bitfld
        BYTE    bk_color_idx;    // Index of background color
        BYTE    pixel_ratio;    // Pixel sides ratio
    };

    struct GifImageDescriptor        // size 9 (ID == 0x2c)
    {
        USHORT    left;
        USHORT    top;
        USHORT    width;
        USHORT    height;
        // bit field
        BYTE    LCT: 1;            // Flag of local color table (LCT)
        BYTE    interlaced: 1;    // Interlaced flag
        BYTE    sort: 1;        // Flag of sorting
        BYTE    reserved: 2;    // Reserved
        BYTE    LCT_size: 3;    // Size of LCT
        // end of bitfld
    };

    // Requires 89a version
    struct GifAdditionalImageControlBlock    // size 6 (ID == 0x21, token == 0xf9)
    {
        BYTE    block_size;            // Block size
        // bit field
        BYTE    reserved: 3;        // Reserved
        BYTE    alloc_type: 3;        // Allocation type
        BYTE    manual_input: 1;    // Manual input flag
        BYTE    transparency: 1;    // Transparent color flag
        // end of bitfld
        USHORT    time_delay;            // Time delay
        BYTE    transparent_color_idx;    // Index of transparent color
        BYTE    block_terminator;
    };

    struct GifApplicationExtension    //size 12 (ID == 0x21, token == 0xff)
    {
        BYTE    block_size;            // Block size
        BYTE    app_id[8];            // Application ID
        BYTE    code[3];            // Application code ID
    };

    struct GifImage
    {
        GifHeader                        gif_header;                        // GifHeader
        GifLogScreenDescriptor            log_screen_descriptor;            // GifLogScreenDescriptor
        GifImageDescriptor                image_descriptor;                // GifImageDescriptor
        GifAdditionalImageControlBlock    additional_image_ctrl_block;    // GifAdditionalImageControlBlock
        GifApplicationExtension            application_extension;            // GifApplicationExtension
        BOOL                            bExtensionPresent;                // Indicates that AppExtension is present
        BYTE                            LZW_code_min;                    // MinCode of LZW
        CHAR*                            comment[256];                    // Image comments
        ColorPalette                    Palette[256];                    // LCT
        CSimpleArray< BYTE >            LZW;

        // Constructortion/Destruction
        GifImage()
        {
            memset( &gif_header, 0, sizeof( GifHeader ) );
            memset( &log_screen_descriptor, 0, sizeof( GifLogScreenDescriptor ) );
            memset( &image_descriptor, 0, sizeof( GifImageDescriptor ) );
            memset( &additional_image_ctrl_block, 0, sizeof( GifAdditionalImageControlBlock ) );
            memset( &application_extension, 0, sizeof( GifApplicationExtension ) );

            bExtensionPresent = FALSE;
            LZW_code_min = 0;
            memset( comment, 0, 256 );
            memset( &Palette, 0, sizeof( ColorPalette ) * 256 );
        }
        virtual ~GifImage() { }                    // Void destructor
    };
}// namespace GifImageTypes
#endif //#if !defined(_45B05C1F_FBA8_4f6a_8356_ADAFD7AD416F)

///////////////////////////////////////////////////////////////////////////////
//
// Класс поддержки декодирования GIF в BMP и загрузки BMP из ресурсов
// Реализация
//
// Copyright (C) 2003, Bank's soft systems
// Copyright (C) 1992, 1999 - 2003, Alexander Butenko | butenko@bssys.com
// All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#if !defined(_46EEB2D7_9AA1_490c_9FE0_7FB309E069BB)
#define _46EEB2D7_9AA1_490c_9FE0_7FB309E069BB

#ifndef _ATL_NO_DEFAULT_LIBS
    #if WINVER >= 0x0500
    #pragma comment(lib, "msimg32.lib")
    #endif  // WINVER >= 0x0500
#endif  // !_ATL_NO_DEFAULT_LIBS

#include "stdafx.h"
#include <comdef.h>
#include <malloc.h>
#include <stdio.h>
#include <math.h>
#include <atlsimpcoll.h>
#include "GifImagesTypes.h"

namespace NativeImage
{
    // Base image class
    class CImage
    {
    public:
    // Construction/Destruction
        CImage() { Init(); }

        CImage( BSTR bsFileName )
        {
            ATLASSERT( bsFileName != NULL );
            //if( !Create( image.lsd.width, image.lsd.height, 8 ) )
            //    return;

            Init();
            BYTE c, k;    // Currently readed byte and tmp byte
            BOOL bResult = FALSE;

            bResult = OpenImageFile( bsFileName );
            if( bResult == FALSE )
                return;

            // Load log screen descriptor
            fread( &image.log_screen_descriptor, 7, 1, f );

            // Load GCT
            if( image.log_screen_descriptor.GCT )
            {
                UINT nGCTSize = UINT( pow( 2, image.log_screen_descriptor.GCT_size ) );
                bResult = LoadGCT( nGCTSize );
                if( bResult == FALSE )
                    return;
            }

            // Load data
            BYTE buff[255];
            memset( &buff, 0, 255 );

            while( 1 )
            {
                if( !fread( &c, 1, 1, f ) )
                    return;    // Read error

                // Special block
                if( c == 0x21 )
                {
                    // Read extension code
                    fread( &c, 1, 1, f );

                    // Comment extension
                    if( c == 0xfe )
                    {
                        fread( &c, 1, 1, f );
                        fread( &image.comment, c, 1, f );
                        fread( &c, 1, 1, f );
                        if( c )
                            return;    // Error in comment
                        continue;
                    }//if( c == 0xfe )    // Comment extension

                    // Application extension
                    if( c == 0xff )
                    {
                        fread( &image.application_extension, 12, 1, f );
                        fread( &c, 1, 1, f );
                        k = c;
                        for( int i = 0; i < k + 1; i++ )
                            fread( &c, 1, 1, f );
                        image.bExtensionPresent = TRUE;
                        continue;
                    }//if( c == 0xff )    // Application extension

                    // Text extension
                    if( c == 0x01 )
                    {
                        m_bLoaded = FALSE;
                        return;
                    }//if( c == 0x01 )    // Text extension

                    // Graphics control extension
                    if( c == 0xf9 )
                    {
                        fread( &image.additional_image_ctrl_block, 6, 1, f );
                        continue;
                    }//if( c == 0xf9 )    // Graphics control extension
                }//if( c == 0x21 )    // Special block

                // Image data
                if( c == 0x2c )
                {
                    fread( &image.image_descriptor, 9, 1, f );
                    if( image.image_descriptor.LCT )    // Load LCT
                    {
                        UINT nLCTSize = UINT( pow( 2, image.image_descriptor.LCT_size ) );
                        bResult = LoadLCT( nLCTSize );
                        if( bResult == FALSE )
                            return;
                    }

                    // Load LZW data
                    fread( &image.LZW_code_min, 1, 1, f );
                    UINT j = 0;
                    do
                    {
                        if( !fread( &c, 1, 1, f ) )
                            return;

                        if( c != 0x00 )
                        {
                            fread( &buff, c, 1, f );
                            for(int i = 0; i < c; i++ )
                            {
                                image.LZW.Add( buff[i] );
                            }
                            j += c;
                            memset( &buff, 0, 255 );    // unwarranted cleanup
                        }//if( c != 0x00 )
                    } while ( c != 0x00 );

                    Decode();
                    continue;
                }//if( c == 0x2c )// Image data

                // EOF
                if( c == 0x3b )
                {
                    // Image loaded
                    m_bLoaded = TRUE;
                    return;
                }//if( c == 0x3b ) // EOF
            }//while( 1 )// Load data

            CloseImageFile();
            // Since that, GCT located at image.Palette,
            //    GCT at this->m_Palette
            //    and compressed data at image.LZW
            // Decompression proceed with Decode()...
        }

        virtual ~CImage()
        {
            Destroy();
            CloseImageFile();
        }

    protected:
    // Helpers
        HDC                            m_hDC;
        HBITMAP                        m_hBitmap;
        HBITMAP                        m_hOldBitmap;
        COLORREF                    m_rgbTransparentColor;
        int                            m_nHeight;
        int                            m_nWidth;
        int                            m_BPP;
        int                            m_nPlanes;
        void*                        m_pBits;
        GifImageTypes::GifImage        image;
        GifImageTypes::ColorPalette    m_Palette[257]; // GCT
        BOOL                        m_bLoaded;
        FILE*                        f;

    protected:
        // Opens an image file
        BOOL OpenImageFile( BSTR bsFileName )
        {
            CString sFilePath = CW2CT( bsFileName );
            int iPos = sFilePath.Find( _T("://") );
            if( iPos > 0 )
                sFilePath = sFilePath.Right( sFilePath.GetLength() - iPos - 3 );

            m_bLoaded = FALSE;
            f = fopen( sFilePath, "rb" );
            if( f == NULL )
                return( FALSE );
            // Read signature
            fread( &image.gif_header.ID, 3, 1, f );
            fread( &image.gif_header.Ver, 3, 1, f );
            if( image.gif_header.ID[0] != 'G' && image.gif_header.ID[1] != 'I' && image.gif_header.ID[2] != 'F' )
                return FALSE;
            return( TRUE );
        }

        // Closes an image file
        inline void CloseImageFile()
        {
            if( !IsNull() )
            {
                fclose( f ); 
                f = NULL;
            }
        }

        // Load global color table
        BOOL LoadGCT(UINT nSize )
        {
            ATLASSERT( IsNull() == FALSE );

            UCHAR r, g, b;
            for( UINT i = 0; i < nSize; i++ )
            {
                fread( &r, 1, 1, f );
                fread( &g, 1, 1, f );
                fread( &b, 1, 1, f );

                m_Palette[i].Entries[0] = b;
                m_Palette[i].Entries[0] = m_Palette[i].Entries[0] << 8;
                m_Palette[i].Entries[0] += g;
                m_Palette[i].Entries[0] = m_Palette[i].Entries[0] << 8;
                m_Palette[i].Entries[0] += r;
                m_Palette[i].Count = i;
                m_Palette[i].Flags = 0;
            }
            return TRUE;
        }

        // Load local color table
        BOOL LoadLCT(UINT nSize )
        {
            ATLASSERT( IsNull() == FALSE );

            UCHAR r, g, b;
            for( UINT i = 0; i < nSize; i++ )
            {
                fread( &r, 1, 1, f );
                fread( &g, 1, 1, f );
                fread( &b, 1, 1, f );

                image.Palette[i].Entries[0] = b;
                image.Palette[i].Entries[0] = image.Palette[i].Entries[0] << 8;
                image.Palette[i].Entries[0] += g;
                image.Palette[i].Entries[0] = image.Palette[i].Entries[0] << 8;
                image.Palette[i].Entries[0] += r;
                image.Palette[i].Count = i;
                image.Palette[i].Flags = 0;
            }
            return TRUE;
        }

        // Decodes GIF compressed data
        BOOL Decode()
        {
            USHORT c = 0;    // Current LZW code
            USHORT n = 0;    // Next LZW code

            return( TRUE );
        }

        // Initializes an object
        virtual void Init()
        {
            m_hBitmap        = NULL;
            m_hOldBitmap    = NULL;
            m_hDC            = NULL;
            m_rgbTransparentColor = RGB( 255, 0, 255 );
            m_nHeight        = 0;
            m_nWidth        = 0;
            m_BPP            = 8;
            m_nPlanes        = 1;
            m_pBits            = NULL;
            m_bLoaded        = FALSE;
            f                = NULL;
        }

        // Returns a palette
        BOOL LoadPalette( GifImageTypes::ColorPalette* pPalette, UINT nPaletteSize )
        {
            ATLASSERT( pPalette != NULL );
            ATLASSERT( nPaletteSize > 0 );
            ATLASSERT( IsNull() == FALSE );

            fseek( f, 14, SEEK_SET );
            for( UINT i = 0; i < nPaletteSize; i++ )
            {
                DWORD c;
                fread( &c, 3, 1, f );
                pPalette->Entries[i] = c;
            }
            pPalette->Count = i;
            pPalette->Flags = 0;
            return TRUE;
        }

        // Sets a color table for an existing bitmap
        void SetColorTable( UINT iFirstColor, UINT nColors, const RGBQUAD* prgbColors )
        {
            ATLASSERT( m_hBitmap != NULL );

            GetDC();
            ::SetDIBColorTable( m_hDC, iFirstColor, nColors, prgbColors );
            ReleaseDC();
        }

    public:
    // Implementation
        // Returns that image is loaded
        inline BOOL IsLoaded() { return( m_bLoaded == TRUE ? TRUE : FALSE ); }

        // Returns that an image file opens and present
        inline BOOL IsNull() { return( ((f == NULL) && (m_bLoaded == TRUE)) ? TRUE : FALSE ); }

        // Gets an image information
        virtual void GetImageInfo()
        {
            ATLASSERT( m_hBitmap != NULL );

            BITMAP bitmap;
            int iResult = ::GetObject( m_hBitmap, sizeof( BITMAP ), LPSTR( &bitmap ) );

            ATLASSERT( iResult != 0 );

            m_nHeight = bitmap.bmHeight;
            m_nWidth = bitmap.bmWidth;
            m_BPP = bitmap.bmBitsPixel;
            m_nPlanes = bitmap.bmPlanes;
        }

        // Attaches a bitmap
        virtual void Attach( HBITMAP hBitmap )
        {
            ATLASSERT( hBitmap != NULL );
            ATLASSERT( m_hBitmap == NULL );

            m_hBitmap = hBitmap;
        }

        // Detaches a bitmap
        virtual HBITMAP Detach()
        {
            HBITMAP hBitmap;

            ATLASSERT( m_hBitmap != NULL );
            ATLASSERT( m_hDC == NULL );

            hBitmap = m_hBitmap;
            Init();
            return( hBitmap );
        }

        // Destroys an internal HBITMAP object
        virtual void Destroy()
        {
            HBITMAP hBitmap;
            if( m_hBitmap != NULL )
            {
                hBitmap = Detach();
                ::DeleteObject( hBitmap );
            }
        }
        
        // Returns an internal DC
        virtual HDC GetDC()
        {
            ATLASSERT( m_hBitmap != NULL );
            if( m_hDC == NULL )
            {
                m_hDC = ::CreateCompatibleDC( NULL );
                m_hOldBitmap = HBITMAP( ::SelectObject( m_hDC, m_hBitmap ) );
            }
            return( m_hDC );
        }

        // Releases an internal DC
        virtual void ReleaseDC()
        {
            ATLASSERT( m_hDC != NULL );

            HBITMAP hBitmap = HBITMAP( ::SelectObject( m_hDC, m_hOldBitmap ) );

            ATLASSERT( hBitmap == m_hBitmap );

            ::DeleteDC( m_hDC );
            m_hDC = NULL;
        }

        // Returns that supports OS the transparentcy or dont
        virtual BOOL IsTransparencySupported()
        {
            OSVERSIONINFO osvi;
            osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
            ::GetVersionEx( &osvi );

            // Transparency supported for Win98 and Win2000 and later only
            if( (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion >= 10) || (osvi.dwMajorVersion >= 5) )
                return( TRUE );
            return( FALSE );
        }

        // Creates a BMP image
        virtual BOOL Create(int nWidth, int nHeight, int nBPP)
        {
            ATLASSERT( nBPP <= 8 );

            LPBITMAPINFO pbmi;
            HBITMAP hBitmap;
            pbmi = LPBITMAPINFO( _alloca( sizeof( BITMAPINFO ) + 256 * sizeof( RGBQUAD ) ) );
            memset( &pbmi->bmiHeader, 0, sizeof( pbmi->bmiHeader ) );
            pbmi->bmiHeader.biSize = sizeof( pbmi->bmiHeader );
            pbmi->bmiHeader.biWidth = nWidth;
            pbmi->bmiHeader.biHeight = nHeight;
            pbmi->bmiHeader.biPlanes = 1;
            pbmi->bmiHeader.biBitCount = USHORT( nBPP );
            pbmi->bmiHeader.biCompression = BI_RGB;
            memset( pbmi->bmiColors, 0, 256 * sizeof( RGBQUAD ) );

            hBitmap = ::CreateDIBSection( NULL, pbmi, DIB_RGB_COLORS, &m_pBits, NULL, 0 );
            if( hBitmap == NULL )
                return( FALSE );
            Attach( hBitmap );
            return( TRUE );
        }

        // Loads a BMP from resource
        virtual BOOL LoadFromResource( LPCTSTR pszResourceName )
        {
            ATLASSERT( pszResourceName != NULL && pszResourceName != _T("") );

            Destroy();
            HBITMAP hBitmap = HBITMAP(
                ::LoadImage( _Module.GetModuleInstance(), pszResourceName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION )
            );
            Attach( hBitmap );
            GetImageInfo();
            return( hBitmap != NULL ? TRUE : FALSE );
        }

        // Loads an Image from file
        virtual BOOL LoadFromFile( BSTR bsFilePath )
        {
            CImage gif( bsFilePath );
            if( gif.IsNull() == FALSE )
            {
                //CreateFromHandle( gif.GetHandle() );
            }
            return FALSE;
        }

        // Draws an Image
        virtual BOOL Draw( HDC hDestDC, int x, int y, UINT nIndex, COLORREF rgbTransparentColor = RGB(255, 0, 255) )
        {
            GetDC();

            ATLASSERT( hDestDC != NULL );
            ATLASSERT( m_hDC != NULL );
            ATLASSERT( nIndex >= 0 );
            ATLASSERT( m_nHeight > 0 );
            ATLASSERT( m_nWidth > 0 );

            UINT nMaxIndex = m_nWidth / m_nHeight;

            ATLASSERT( nMaxIndex >= 0 );
            ATLASSERT( nIndex <= nMaxIndex );

            BOOL bResult = FALSE;
            if( IsTransparencySupported() )
                bResult = ::TransparentBlt( hDestDC, x, y, m_nHeight, m_nHeight, m_hDC, m_nHeight * nIndex, 0, m_nHeight, m_nHeight, rgbTransparentColor );
            else
                bResult = ::BitBlt( hDestDC, x, y, m_nHeight, m_nHeight, m_hDC, m_nHeight * nIndex, 0, SRCCOPY );
            ReleaseDC();
            return( bResult );
        }    
    };// class CImage
}// namespace NativeImage

#endif    //#if !defined(_46EEB2D7_9AA1_490c_9FE0_7FB309E069BB)
GHOST (LongWalker)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.