|
|
#ifndef UNIX
#pragma pack( push, PNG )
#pragma pack( 1 )
#endif
typedef struct _PNGCHUNKHEADER { ULONG nDataLength; DWORD dwChunkType; } PNGCHUNKHEADER;
typedef struct _PNGIHDRDATA { ULONG nWidth; ULONG nHeight; BYTE nBitDepth; BYTE bColorType; BYTE bCompressionMethod; BYTE bFilterMethod; BYTE bInterlaceMethod; } PNGIHDRDATA;
#ifndef UNIX
#pragma pack( pop, PNG )
#endif
typedef struct _PNG_INTERLACE_INFO { ULONG nDeltaX; ULONG nDeltaY; ULONG nPixelWidth; ULONG nPixelHeight; ULONG iFirstX; ULONG iFirstY; BYTE anPixelsInPartialBlock[8]; BYTE anScanLinesInPartialBlock[8]; } PNG_INTERLACE_INFO;
typedef struct _FLOATRGB { float fRed; float fGreen; float fBlue; } FLOATRGB;
typedef void (*PNGCOPYSCANLINEPROC)( void* pDest, const void* pSrc, ULONG nPixels, ULONG nDeltaXDest, const FLOATRGB* pfrgbBackground, BYTE* pXlate ); typedef void (*PNGDUPLICATESCANLINEPROC)( void* pScanLine, ULONG nDeltaX, ULONG nFullPixels, ULONG nFullPixelWidth, ULONG nPartialPixelWidth );
typedef struct _PNG_FORMAT_INFO { ULONG nPossibleFormats; const GUID* pPossibleFormats; const PNGCOPYSCANLINEPROC* ppfnCopyScanLineProcs; const PNGDUPLICATESCANLINEPROC* ppfnDuplicateScanLineProcs; } PNG_FORMAT_INFO;
#define PNGCHUNK( a, b, c, d ) \
(MAKELONG( MAKEWORD( (a), (b) ), MAKEWORD( (c), (d) ) ))
const DWORD PNG_CHUNK_IHDR = PNGCHUNK( 'I', 'H', 'D', 'R' ); const DWORD PNG_CHUNK_IEND = PNGCHUNK( 'I', 'E', 'N', 'D' ); const DWORD PNG_CHUNK_IDAT = PNGCHUNK( 'I', 'D', 'A', 'T' ); const DWORD PNG_CHUNK_PLTE = PNGCHUNK( 'P', 'L', 'T', 'E' ); const DWORD PNG_CHUNK_BKGD = PNGCHUNK( 'b', 'K', 'G', 'D' ); const DWORD PNG_CHUNK_TRNS = PNGCHUNK( 't', 'R', 'N', 'S' ); const DWORD PNG_CHUNK_GAMA = PNGCHUNK( 'g', 'A', 'M', 'A' );
const DWORD PNG_CHUNK_ANCILLARY = 0x00000020;
const BYTE PNG_COMPRESSION_DEFLATE32K = 0; const BYTE PNG_FILTER_ADAPTIVE = 0; const BYTE PNG_INTERLACE_NONE = 0; const BYTE PNG_INTERLACE_ADAM7 = 1;
const ULONG PNG_BUFFER_SIZE = 4096;
const DWORD CHUNK_IHDR = 0x01; const DWORD CHUNK_PLTE = 0x02; const DWORD CHUNK_POSTPLTE = 0x04; const DWORD CHUNK_IDAT = 0x08; const DWORD CHUNK_LASTIDAT = 0x10; const DWORD CHUNK_IEND = 0x20; const DWORD CHUNK_BKGD = 0x40; const DWORD CHUNK_TRNS = 0x80; const DWORD CHUNK_GAMA = 0x100;
const BYTE PNG_COLORTYPE_PALETTE_MASK = 0x01; const BYTE PNG_COLORTYPE_COLOR_MASK = 0x02; const BYTE PNG_COLORTYPE_ALPHA_MASK = 0x04; const BYTE PNG_COLORTYPE_INDEXED = PNG_COLORTYPE_PALETTE_MASK| PNG_COLORTYPE_COLOR_MASK; const BYTE PNG_COLORTYPE_RGB = PNG_COLORTYPE_COLOR_MASK; const BYTE PNG_COLORTYPE_GRAY = 0x00; const BYTE PNG_COLORTYPE_RGBA = PNG_COLORTYPE_COLOR_MASK| PNG_COLORTYPE_ALPHA_MASK; const BYTE PNG_COLORTYPE_GRAYA = PNG_COLORTYPE_ALPHA_MASK;
class CPNGFilter : public IImageDecodeFilter, public CComObjectRoot, public CComCoClass< CPNGFilter, &CLSID_CoPNGFilter > { public: CPNGFilter(); ~CPNGFilter();
BEGIN_COM_MAP( CPNGFilter ) COM_INTERFACE_ENTRY( IImageDecodeFilter ) END_COM_MAP()
DECLARE_NOT_AGGREGATABLE( CPNGFilter ) // Remove the comment from the line above if you don't want your object to
// support aggregation. The default is to support it
DECLARE_REGISTRY( CPNGFilter, _T( "PNGFilter.CoPNGFilter.1" ), _T( "PNGFilter.CoPNGFilter" ), IDS_COPNGFILTER_DESC, THREADFLAGS_BOTH )
// DECLARE_NO_REGISTRY()
// IImageDecodeFilter
public: STDMETHOD( Initialize )( IImageDecodeEventSink* pEventSink ); STDMETHOD( Process )( IStream* pStream ); STDMETHOD( Terminate )( HRESULT hrStatus );
protected: HRESULT BeginImage(); HRESULT ChooseDestinationFormat( GUID* pBFID ); HRESULT DetermineSourceFormat(); HRESULT EatData(); HRESULT FireGetSurfaceEvent(); HRESULT FireOnProgressEvent(); HRESULT NextState(); HRESULT OutputBytes( const BYTE* pData, ULONG nBytes ); HRESULT ChooseBKGD(); HRESULT ProcessBKGD(); HRESULT ProcessIDAT(); HRESULT ProcessIEND(); HRESULT ProcessIHDR(); HRESULT ProcessPLTE(); HRESULT ProcessTRNS(); HRESULT ProcessGAMA(); HRESULT ReadChunkHeader(); HRESULT ReadChunkData(); HRESULT ReadChunkCRC(); HRESULT ReadFileHeader(); HRESULT ReadIDATData(); HRESULT NextPass(); HRESULT NextScanLine(); BOOL BeginPass( ULONG iPass ); HRESULT WriteScanLine();
HRESULT LockBits(RECT *prcBounds, DWORD dwLockFlags, void **ppBits, long *pPitch); HRESULT UnlockBits(RECT *prcBounds, void *pBits);
void NoneFilterScanLine(); void SubFilterScanLine(); void UpFilterScanLine(); void AverageFilterScanLine(); void PaethFilterScanLine();
protected: static const PNG_INTERLACE_INFO s_aInterlaceInfoNone[1]; static const PNG_INTERLACE_INFO s_aInterlaceInfoAdam7[7]; static const PNG_FORMAT_INFO s_aFormatInfo[15];
protected: typedef enum _EInternalState { ISTATE_READFILEHEADER, ISTATE_READCHUNKHEADER, ISTATE_READCHUNKDATA, ISTATE_READIDATDATA, ISTATE_READCHUNKCRC, ISTATE_PROCESSIHDR, ISTATE_PROCESSIEND, ISTATE_PROCESSPLTE, ISTATE_PROCESSBKGD, ISTATE_PROCESSTRNS, ISTATE_PROCESSGAMA, ISTATE_CHOOSEBKGD, ISTATE_EATDATA, ISTATE_DONE } EInternalState; typedef enum _ESrcFormat { SRC_GRAY_1, SRC_GRAY_2, SRC_GRAY_4, SRC_GRAY_8, SRC_GRAY_16, SRC_RGB_24, SRC_RGB_48, SRC_INDEXED_RGB_1, SRC_INDEXED_RGB_2, SRC_INDEXED_RGB_4, SRC_INDEXED_RGB_8, SRC_GRAYA_16, SRC_GRAYA_32, SRC_RGBA_32, SRC_RGBA_64 } ESrcFormat;
EInternalState m_eInternalState; // State of decode state machine
DWORD m_dwEvents; // Events the event sink wants to receive
PNGCOPYSCANLINEPROC m_pfnCopyScanLine; PNGDUPLICATESCANLINEPROC m_pfnDuplicateScanLine; const PNG_INTERLACE_INFO* m_pInterlaceInfo; ULONG m_nFormats; // Number of formats the event sink supports
GUID* m_pFormats; // Formats supported by the event sink
BOOL m_bPalette; // Does image use a palette?
BOOL m_bColor; // Does image use color?
BOOL m_bAlpha; // Does image have an alpha channel
BOOL m_bSurfaceUsesAlpha; BOOL m_bConvertAlpha; BOOL m_bSkipData; ESrcFormat m_eSrcFormat; // Source pixel format
DWORD m_dwCRC; // CRC accumulator
DWORD m_dwChunkCRC; // Stored CRC of current chunk
ULONG m_nColors; // Number of colors in palette
ULONG m_iBackgroundIndex; // Index of background color
RGBQUAD m_rgbBackground; // Background color
FLOATRGB m_frgbBackground; // Floating-point background color
DWORD m_dwTransKey; // Transparent color key (RGB or indexed
ULONG m_nTransparentColors; // # transparent indices
IStream* m_pStream; // Source stream
CComPtr< IImageDecodeEventSink > m_pEventSink; // Event sink
PNGCHUNKHEADER m_pngChunkHeader; // Header of current chunk
PNGIHDRDATA m_pngIHDR; // IHDR chunk
DWORD m_dwChunksEncountered; // CHUNK_* flags for what chunks have been
// encountered in the image stream so far
CComPtr< IDirectDrawSurface > m_pDDrawSurface; BOOL m_bFinishedIDAT; // Have we finished the IDAT section?
ULONG m_nBytesLeftInCurrentTask; // Bytes remaining before we switch to a
// new state
ULONG m_nDataBytesRead; // Bytes of chunk data read
ULONG m_iAppend; // Where to append data in buffer
BYTE* m_pbScanLine; // Current decoded scan line (including filter byte)
BYTE* m_pbPrevScanLine; // Previous decoded scan line
ULONG m_iPass; // Current pass
ULONG m_nPasses; // Number of passes
ULONG m_nBytesInScanLine; // Number of bytes in one scan line
ULONG m_nPixelsInScanLine; // Number of pixels in one scan line
ULONG m_nBitsPerPixel; // Bits per pixel in source image
BOOL m_bExpandPixels; // Expand interlaced pixels?
ULONG m_iScanLine; // Current scan line
ULONG m_nScanLinesInPass; // Number of scan lines in current pass
ULONG m_iScanLineInPass; // Current scan line in pass
ULONG m_iFirstStaleScanLine; // First scan line whose progress has not been
// reported
ULONG m_nBPP; // Bytes per pixel
ULONG m_nDeltaX; // Horizontal distance between pixels
ULONG m_nDeltaY; // Vertical distance between pixels
ULONG m_nPixelWidth; // Width of a pixel
ULONG m_nPixelHeight; // Height of a pixel
ULONG m_iFirstX; // Horizontal position of first pixel in scan line
ULONG m_iFirstY; // Vertical position of first scan line in pass
ULONG m_nFullPixelsInScanLine; ULONG m_nPartialPixelWidth; z_stream m_zlibStream; // ZLib data
BYTE m_abData[PNG_BUFFER_SIZE]; // Data buffer
BYTE m_abTrans[256]; // table to collapse multiple transparent indices
BYTE m_abGamma[256]; // gamma correction table
RGBQUAD m_argbColors[256];
};
|