Прив
Народ, начал писать декодер 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)