[Date Prev][Date Next][Thread Prev][Thread Next][Thread Index]
[XaraXtreme-commits] Commit Complete
Commit by : luke
Repository : xara
Revision : 1348
Date : Wed Jun 21 13:47:27 BST 2006
Changed paths:
M /Trunk/XaraLX/Kernel/filters.cpp
M /Trunk/XaraLX/wxOil/Makefile.am
M /Trunk/XaraLX/wxOil/giffiltr.cpp
A /Trunk/XaraLX/wxOil/gifutil.cpp
A /Trunk/XaraLX/wxOil/gifutil.h
M /Trunk/XaraLX/wxOil/outptgif.cpp
M /Trunk/XaraLX/wxOil/outptgif.h
Enable import of GIF files (in correct colors)
Diff:
Index: Trunk/XaraLX/Kernel/filters.cpp
===================================================================
--- Trunk/XaraLX/Kernel/filters.cpp (revision 1347)
+++ Trunk/XaraLX/Kernel/filters.cpp (revision 1348)
@@ -790,9 +790,10 @@
ADD_FILTER(JPEGImportFilter)
ADD_FILTER(PNGFilter)
-PORTNOTETRACE("filter","Removed TIFFFilter and TI_GIFFilter");
+
+ ADD_FILTER(TI_GIFFilter)
+PORTNOTETRACE("filter","Removed TIFFFilter");
#ifndef EXCLUDE_FROM_XARALX
- ADD_FILTER(TI_GIFFilter)
ADD_FILTER(TIFFFilter)
#endif
Index: Trunk/XaraLX/wxOil/outptgif.h
===================================================================
--- Trunk/XaraLX/wxOil/outptgif.h (revision 1347)
+++ Trunk/XaraLX/wxOil/outptgif.h (revision 1348)
@@ -105,30 +105,12 @@
#include "dibconv.h" // needs DIBConvert
#include "dibutil.h" // needs FNPTR_SCANLINE
#include "outptdib.h"
-//#include "gifutil.h" // GIF header definitions
+#include "gifutil.h" // GIF header definitions
-// From gifutil.h
-enum GIFDisposalMethod
-{
- GDM_NONE = 0, // No disposal specified. The decoder is not required to take any action.
- GDM_LEAVE = 1, // Do not dispose. The graphic is to be left in place.
- GDM_BACKTOBACK = 2, // Restore to background color. The area used by the graphic must be restored to the background color.
- GDM_PREVIOUS = 3 // Restore to previous. The decoder is required to restore the area overwritten by the graphic with what was there prior to rendering the graphic.
-};
-
#define GIFBITS 12
#define MAX_LWZ_BITS 12
#define HSIZE 5003 // 80% occupancy
-typedef INT32 code_int;
-typedef INT32 count_int;
-
-const INT32 maxbits = GIFBITS; // user settable max # bits/code
-const code_int maxmaxcode = (code_int)1 << GIFBITS; // should NEVER generate this code
-
-const code_int hsize = HSIZE; // for dynamic table sizing
-
-
#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
#define HashTabOf(i) htab[i]
Index: Trunk/XaraLX/wxOil/gifutil.h
===================================================================
--- Trunk/XaraLX/wxOil/gifutil.h (revision 0)
+++ Trunk/XaraLX/wxOil/gifutil.h (revision 1348)
@@ -0,0 +1,299 @@
+// $Header: /Camelot/winoil/gifutil.h 12 20/05/97 16:18 Neville $
+
+// Header for GIFUtil which suprisingly enough contains lots of
+// useful routines for:-
+// reading in a GIF file as a bitmap
+//
+
+// Code based on the GD image library code which has the following
+// copyright notice:-
+/* +-------------------------------------------------------------------+ */
+/* | Copyright 1990, 1991, 1993, David Koblas. (koblas@xxxxxxxxxx) | */
+/* | Permission to use, copy, modify, and distribute this software | */
+/* | and its documentation for any purpose and without fee is hereby | */
+/* | granted, provided that the above copyright notice appear in all | */
+/* | copies and that both that copyright notice and this permission | */
+/* | notice appear in supporting documentation. This software is | */
+/* | provided "as is" without express or implied warranty. | */
+/* +-------------------------------------------------------------------+ */
+// Code in this file at present is mainly from GIDDecod.c
+
+#ifndef INC_GIFUTIL
+#define INC_GIFUTIL
+
+#include "ccfile.h" // needs FilePos
+#include "dibconv.h" // needs DIBConvert
+#include "dibutil.h" // needs FNPTR_SCANLINE
+//#include "outptdib.h"
+
+typedef struct tagGIFINFOHEADER
+{
+ char giName[6]; // GIF87a or 9a
+ WORD giWidth;
+ WORD giHeight;
+ BYTE giFlags; // Colourmap flag, bpp, resolution
+ BYTE giBackground; // background colour
+ BYTE giAspect; // aspect
+} GIFINFOHEADER, FAR *LPGIFINFOHEADER;
+
+typedef struct tagGIFIMAGEBLOCK
+{
+ WORD gibLeft;
+ WORD gibTop;
+ WORD gibWidth;
+ WORD gibDepth;
+ BYTE gibFlags; // Colourmap flag, bpp, resolution
+} GIFIMAGEBLOCK, FAR *LPGIFIMAGEBLOCK;
+
+// Flags definitions
+#define INTERLACE 0x40
+#define LOCALCOLOURMAP 0x80
+#define GLOBALCOLOURMAP 0x80
+
+// Extension block type definitions
+#define EXTENSIONBLOCK 0x21
+#define TRANSPARENTBLOCK 0xf9
+
+typedef struct tagGIFTRANSBLOCK
+{
+ BYTE gtbBlockStart; // 0x21
+ BYTE gtbIdentifier; // 0xf9
+ BYTE gtbBlockSize; // 4 (always)
+ BYTE gtbFlags; // 1 (transparent flag 0x01, wait for key 0x02)
+ WORD gtbDelay; // 0 (delay to display for if 0x02 set)
+ BYTE gtbTransparency;// transparency
+ BYTE gtbTerminator; // 0
+} GIFTRANSBLOCK, FAR *LPGIFTRANSBLOCK;
+
+#define COMMENTBLOCK 0xfe
+
+typedef struct tagGIFCOMMENTBLOCK
+{
+ BYTE gcbBlockStart; // 0x21
+ BYTE gcbIdentifier; // 0xfe
+ BYTE gcbTextSize; // size of text, followed by text
+} GIFCOMMENTBLOCK, FAR *LPGIFCOMMENTBLOCK;
+
+#define APPLICATIONBLOCK 0xff
+
+typedef struct tagGIFAPPLICATIONBLOCK
+{
+ BYTE gabBlockStart; // 0x21
+ BYTE gabIdentifier; // 0xff
+ BYTE gabBlockSize; // size of block
+ CHAR gabString[8]; // application block
+ BYTE gabAuthentication; // check sum
+} GIFAPPLICATIONBLOCK, FAR *LPGIFAPPLICATIONBLOCK;
+
+#define PLAINTEXTBLOCK 0x01
+
+typedef struct tagGIFRGBTRIPLE
+{
+ BYTE grgbtRed;
+ BYTE grgbtGreen;
+ BYTE grgbtBlue;
+} GIFRGBTRIPLE, FAR *LPGIFRGBTRIPLE;
+
+
+const unsigned long masks[] = {
+ 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF,
+ 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF,
+ 0x7FFF, 0xFFFF
+ };
+
+//#define MAXCOLORMAPSIZE 256
+#define GIFBITS 12
+#define MAX_LWZ_BITS 12
+#define HSIZE 5003 // 80% occupancy
+
+typedef int code_int;
+typedef long int count_int;
+
+const int maxbits = GIFBITS; // user settable max # bits/code
+const code_int maxmaxcode = (code_int)1 << GIFBITS; // should NEVER generate this code
+
+const code_int hsize = HSIZE; // for dynamic table sizing
+
+enum GIFDisposalMethod
+{
+ GDM_NONE = 0, // No disposal specified. The decoder is not required to take any action.
+ GDM_LEAVE = 1, // Do not dispose. The graphic is to be left in place.
+ GDM_BACKTOBACK = 2, // Restore to background color. The area used by the graphic must be restored to the background color.
+ GDM_PREVIOUS = 3 // Restore to previous. The decoder is required to restore the area overwritten by the graphic with what was there prior to rendering the graphic.
+};
+
+
+
+class BaseCamelotFilter;
+
+/********************************************************************************************
+
+> class Palette : public CC_CLASS_MEMDUMP
+
+ Author: Colin
+ Created: 24/4/95
+ Purpose: Something that should have been done long ago...
+ SeeAlso: Everywhere
+
+********************************************************************************************/
+class PaletteIterator
+{
+public:
+ PaletteIterator(): m_pPalette(NULL) {}
+
+ void SetRed(const UINT32 nRed)
+ { m_pPalette->rgbRed = nRed; }
+
+ void SetGreen(const UINT32 nGreen)
+ { m_pPalette->rgbGreen = nGreen; }
+
+ void SetBlue(const UINT32 nBlue)
+ { m_pPalette->rgbBlue = nBlue; }
+
+ void SetTransparent(const UINT32 nTransparent)
+ { m_pPalette->rgbReserved = nTransparent; }
+
+ BOOL operator< (const PaletteIterator& rhsIterator)
+ { return m_pPalette < rhsIterator.m_pPalette; }
+
+ PaletteIterator& operator++()
+ {
+ ++m_pPalette;
+ return *this;
+ }
+
+protected:
+ LPRGBQUAD m_pPalette;
+};
+
+
+/********************************************************************************************
+
+> class Palette : public CC_CLASS_MEMDUMP
+
+ Author: Colin
+ Created: 24/4/95
+ Purpose: Something that should have been done long ago...
+ SeeAlso: Everywhere
+
+********************************************************************************************/
+class Palette : public CC_CLASS_MEMDUMP
+{
+ // Declare the class for memory tracking
+ CC_DECLARE_MEMDUMP(Palette);
+public:
+ Palette() : m_pColours(NULL), m_nSize(0) {}
+ ~Palette();
+
+// Palette& operator= (const Palette& otherPalette) {return Palette(otherPalette);}
+
+ BOOL SetSize(const UINT32 nSize);
+
+
+ BOOL IsConstructedOK() const
+ { return m_bInitOK; }
+
+
+ const PaletteIterator& Start() const
+ { return m_StartIterator; }
+
+ const PaletteIterator& End() const
+ { return m_EndIterator; }
+
+protected:
+ Palette(const Palette& otherPalette);
+
+protected:
+ LPRGBQUAD m_pColours;
+ UINT32 m_nSize;
+
+ PaletteIterator m_StartIterator;
+ PaletteIterator m_EndIterator;
+
+private:
+ BOOL m_bInitOK;
+};
+
+
+/********************************************************************************************
+
+> class OutputGIF : public OutputDIB
+
+ Author: Neville Humphrys
+ Created: 24/4/95
+ Purpose: Contains functions to read in a GIF file as a DIB.
+ SeeAlso: OutputGIF;
+
+********************************************************************************************/
+
+class GIFUtil //: public CC_CLASS_MEMDUMP
+{
+public:
+
+ //GIFUtil();
+ //~GIFUtil();
+
+ static BOOL ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits,
+ int *TransColour, String_64 *ProgressString = NULL,
+ BaseCamelotFilter *pFilter = NULL );
+ static BOOL ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits,
+ int *TransColour, int& nBitmapToRead, String_64 *ProgressString = NULL,
+ BaseCamelotFilter *pFilter = NULL, UINT32* Delay=NULL,
+ GIFDisposalMethod *Restore=NULL,
+ UINT32 * pLeftOffset = NULL, UINT32* pTopOffset = NULL,
+ BOOL * pLocalPalette = NULL);
+// static BOOL WriteToFile ( CCLexFile *, LPBITMAPINFO Info, LPBYTE Bits,
+// String_64 *ProgressString = NULL);
+
+ // Access to the values read in as part of the GIF header
+ static UINT32 GetGlobalWidth() { return m_GlobalWidth; }
+ static UINT32 GetGlobalHeight() { return m_GlobalHeight; }
+
+protected:
+ BOOL ProcessHeader();
+ static BOOL ProcessExtension(CCLexFile *fd);
+ static BOOL ProcessImageBlock(CCLexFile* File, LPBITMAPINFO *Info, LPBYTE *Bits,
+ UINT32 * pLeftOffset = NULL, UINT32 * pTopOffset = NULL,
+ BOOL * pLocalPalette = NULL);
+
+ static BOOL ReadColourMap(CCLexFile *fd, int number, LPRGBQUAD lpPalette);
+ static int GetDataBlock( CCLexFile *fd, unsigned char *buf );
+ static int GetCode( CCLexFile *fd, int code_size, int flag );
+ static int LWZReadByte( CCLexFile *fd, int flag, int input_code_size );
+ static BOOL ReadImage( CCLexFile *fd, LPBYTE pBitsData, int width, int height, int bpp,
+ BOOL interlace, BaseCamelotFilter *pFilter = NULL );
+
+private:
+ // Some useful variables
+ //int Width; // Width of the image
+ //int Height; // Height of the image
+ static WORD m_GlobalWidth; // The overall width from the GIF header
+ static WORD m_GlobalHeight; // The overall height from the GIF header
+
+ static BOOL Interlace; // Use interlace or not
+ static int Transparent; // colour or -1 = no transparency
+ static UINT32 m_Delay; // The Animation delay value for each bitmap.
+ static GIFDisposalMethod m_Restore; // The Animation Restore value for exch bitmap.
+
+ static int m_nCurrentBitmap; // the number of the bitmap currently (or was just) in the buffer
+
+ //WORD BitsPerPixel; // Colour depth required
+
+ //UINT32 WidthOfLine; // word/byte rounded line width rather than the pixel width
+
+ // Importint specific variables
+ static BOOL ZeroDataBlock; // flag to say whether we have a zero length block or not
+
+ Palette m_GlobalPalette; // the global palette of the GIF
+
+ // replace this with the above...eventually
+ static LPRGBQUAD lpGlobalPalette; // pointer to temporary palette store
+ static int GlobalPaletteSize; // size of the global palette found
+
+ static BOOL m_bImageRead; // Has an image been found this pass?
+ // the start position of the next image in the file
+ static FilePos m_NextImageStartPosition;
+};
+
+#endif // INC_GIFUTIL
Index: Trunk/XaraLX/wxOil/gifutil.cpp
===================================================================
--- Trunk/XaraLX/wxOil/gifutil.cpp (revision 0)
+++ Trunk/XaraLX/wxOil/gifutil.cpp (revision 1348)
@@ -0,0 +1,1272 @@
+// $Header: /Camelot/winoil/gifutil.cpp 19 25/03/99 16:16 Markn $
+
+// Contains useful routines for compressing a bitmap out to a GIF format file and
+// routines to load that file back in.
+
+/*
+*/
+
+#include "camtypes.h"
+#include "ensure.h"
+#include "fixmem.h"
+#include "errors.h"
+#include "progress.h" // For hourglass stuff
+//#include "resource.h" // IDS_OUTOFMEMORY
+//#include "accures.h" // IDW_CANCELLEDBMPIMPORT
+#include "gifutil.h"
+//#include "outptgif.h"
+//#include "andy.h"
+//#include "dibconv.h"
+//#include "string.h" // memcpy
+#include "camfiltr.h" // BaseCamelotFilter
+
+#define new CAM_DEBUG_NEW
+
+
+CC_IMPLEMENT_MEMDUMP(Palette, CC_CLASS_MEMDUMP)
+Palette::~Palette()
+{
+ if (m_pColours)
+ delete [] m_pColours;
+ m_pColours = NULL; // ensure state correct
+ m_nSize = 0;
+}
+
+
+
+Palette::Palette(const Palette& otherPalette)
+{
+ if (&otherPalette == this) return;
+
+ if (otherPalette.m_nSize > m_nSize)
+ delete [] m_pColours;
+ m_pColours = new RGBQUAD[otherPalette.m_nSize];
+ if (m_pColours == NULL)
+ {
+ m_bInitOK = FALSE;
+ return;
+ }
+ m_nSize = otherPalette.m_nSize;
+ memcpy(m_pColours, otherPalette.m_pColours, m_nSize);
+ m_bInitOK = TRUE;
+}
+
+#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
+
+// define the statics that we require
+BOOL GIFUtil::Interlace = FALSE; // Use interlace or not
+int GIFUtil::Transparent = -1; // colour or -1 = no transparency
+UINT32 GIFUtil::m_Delay = 0; // Data member, to recieve a bitmaps Animation delay value
+BOOL GIFUtil::ZeroDataBlock = FALSE; // flag to say whether we have a zero length block or not
+int GIFUtil::m_nCurrentBitmap = 0;
+GIFDisposalMethod GIFUtil::m_Restore = GDM_LEAVE; // Data member, to recieve a bitmaps' Animation Restore value.
+
+LPRGBQUAD GIFUtil::lpGlobalPalette = NULL; // pointer to temporary palette store
+int GIFUtil::GlobalPaletteSize = 0; // size of the global palette found
+FilePos GIFUtil::m_NextImageStartPosition = 0; // Position in file of next image
+BOOL GIFUtil::m_bImageRead = FALSE; // Did we get something?
+
+WORD GIFUtil::m_GlobalWidth = 0; // The overall width from the GIF header
+WORD GIFUtil::m_GlobalHeight = 0; // The overall height from the GIF header
+
+/********************************************************************************************
+
+> GIFUtil::GIFUtil()
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Purpose: Default constructor for the class.
+ SeeAlso:
+
+********************************************************************************************/
+
+//GIFUtil::GIFUtil()
+//{
+//}
+
+/********************************************************************************************
+> GIFUtil::GIFUtil()
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Purpose: Default destructor for the class.
+ SeeAlso:
+
+********************************************************************************************/
+
+//GIFUtil::~GIFUtil()
+//{
+//}
+
+/********************************************************************************************
+
+> static BOOL GIFUtil::ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits,
+ int *TransColour, int& nBitmapToRead,
+ String_64 *ProgressString, BaseCamelotFilter *pFilter = NULL )
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Inputs: File A opened CCLexFile that can be read from. It should be positioned at the
+ start. Caller is responsible for closing it. The file needs to be in
+ Binary mode.
+ nBitmapToRead The number of the bitmap in the GIF that you wish to read.
+ If 1 then the GIF will be read from the beginning obtaining the
+ header information.
+ For any number other than 1 it should be noted that bitmaps can only
+ be read in an incremental sequence and that the first one must have
+ been read prior to any call with a non-1 value.
+ ProgressString allows the user to specify whether they require a progress hourglass or
+ not. If NULL then none is shown, otherwise an progress bar is shown
+ using the text supplied. Defaults to NULL i.e. no progress bar.
+ pFilter is an alternative way of handling the progress bar, assume the
+ progress bar has been start and just call the IncProgressBarCount in
+ BaseCamelotFilter to do the progress bar update.
+ Defaults to NULL i.e. no progress bar.
+ Outputs: Info points to a new LPBITMAPINFO struct and Bits points to the bytes.
+ These can be freed up with FreeDIB.
+ TransColour is either -1 == none or equal to the transparency colour found
+ nBitmapToRead Returns the number of the next bitmap that can be read from the GIF
+ or -1 if no further bitmaps exist.
+ Returns: TRUE if worked, FALSE if failed (error will be set accordingly but not reported)
+ Purpose: Reads a .gif file into memory decompressing it as it goes.
+ ***Errors on 16-bit builds***
+ A progress hourglass can be shown if required.
+ Errors: Calls SetError on FALSE returns.
+ Scope: Static, Public
+ SeeAlso: DIBUtil::ReadFromFile; AccusoftFilters::ReadFromFile;
+
+********************************************************************************************/
+BOOL GIFUtil::ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits,
+ int *TransColour, String_64 *ProgressString,
+ BaseCamelotFilter *pFilter )
+{
+ int nBitmap = 1;
+
+ return (ReadFromFile( File, Info, Bits, TransColour, nBitmap, ProgressString, pFilter));
+}
+
+/**********************************************************************************************
+
+static BOOL GIFUtil::ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits,
+ int *TransColour, int& nBitmapToRead, String_64 *ProgressString = NULL,
+ BaseCamelotFilter *pFilter = NULL, UINT32* Delay=NULL,
+ GIFDisposalMethod *Restore=NULL,
+ UINT32 * pLeftOffset = NULL, UINT32 * pTopOffset = NULL,
+ BOOL * pLocalPalette = NULL)
+Author: -
+Created: -
+Inputs/Outputs Refer to the above Function Header for a full explanation.
+
+*************************************************************************************************/
+
+BOOL GIFUtil::ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits,
+ int *TransColour, int& nBitmapToRead, String_64 *ProgressString,
+ BaseCamelotFilter *pFilter, UINT32* Delay, GIFDisposalMethod *Restore,
+ UINT32 * pLeftOffset, UINT32 * pTopOffset,
+ BOOL * pLocalPalette)
+{
+ if ((nBitmapToRead > 1 && nBitmapToRead == m_nCurrentBitmap) || nBitmapToRead < 1)
+ {
+ ERROR3("GIFUtil::ReadFromFile() - can't read that bitmap");
+ return FALSE;
+ }
+
+ *Info = NULL; // in case of early exit
+ *Bits = NULL;
+ Transparent = -1;
+ *TransColour = -1; // in case of early exit set to none
+ int Background = 0; // background colour number !!! not used !!!
+ Interlace = FALSE; // set interlace to false by default
+
+ // Must set the exception throwing flag to True and force reporting of errors to False.
+ // This means that the caller must report an error if the function returns False.
+ // Any calls to CCLexFile::GotError will now throw a file exception and should fall into
+ // the catch handler at the end of the function.
+ BOOL OldThrowingState = File->SetThrowExceptions( TRUE );
+ BOOL OldReportingState = File->SetReportErrors( FALSE );
+
+ // If the caller has specified a string then assume they require a progress bar
+ // Start it up.
+ if (ProgressString != NULL)
+ BeginSlowJob(100, FALSE, ProgressString);
+
+ try
+ {
+ // If we want the first bitmap we'll assume we're at the start of the file & read the header
+ if (nBitmapToRead == 1)
+ {
+ // place to store the global palette, if present, for later use
+ lpGlobalPalette = NULL; // pointer to temporary palette store
+ GlobalPaletteSize = 0; // size of the global palette found
+
+ GIFINFOHEADER Header;
+ // This is really sizeof(GIFINFOHEADER) but this returns 14 instead of 13
+ // as it rounds to the nearest word boundary
+ const size_t HeaderSize = sizeof(char)* 6 + sizeof(WORD) * 2 + sizeof(BYTE) * 3;
+
+ File->read( &Header, HeaderSize );
+ if (File->bad())
+ File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
+
+ // Just double check that the signature is correct, if not then fail immediately
+ if (
+ (strncmp(Header.giName, "GIF89a", 6) != 0) &&
+ (strncmp(Header.giName, "GIF87a", 6) != 0)
+ )
+ File->GotError( _R(IDE_BADFORMAT) );
+
+ // Note the overall size of the GIF from the header, may be the animation size
+ m_GlobalWidth = Header.giWidth;
+ m_GlobalHeight = Header.giHeight;
+ // flags word consists of:-
+ // - bit 7 colour table flag = set if global colour table follows
+ // - bits 6-4 colour resolution = bpps - 1
+ // - bit 3 sort flag = set global colour table sorted
+ // - bits 3-0 size of global colour table = size is 2^(value+1)
+ int ColorResolution = (((Header.giFlags >> 4) & 0x07) + 1);
+ GlobalPaletteSize = 2 << (Header.giFlags & 0x07);
+ Background = Header.giBackground;
+ int AspectRatio = Header.giAspect;
+
+TRACEUSER("Neville",_T("Gif Global Width = %d Height = %d
"), m_GlobalWidth, m_GlobalHeight);
+TRACEUSER("Neville",_T("Gif ColorResolution = %d
"), ColorResolution);
+
+ // Check if we have a global colour map present or not, if so then read it in.
+ if (BitSet(Header.giFlags, GLOBALCOLOURMAP))
+ {
+TRACEUSER("Neville",_T("Gif read global colour table size = %d
"), GlobalPaletteSize);
+ // Read in the global colour map into a palette structure for possible later use
+ const size_t TotalPal = sizeof(RGBQUAD) * GlobalPaletteSize;
+ lpGlobalPalette = (LPRGBQUAD)CCMalloc( TotalPal );
+ if (lpGlobalPalette==NULL)
+ return FALSE;
+
+ ReadColourMap(File, GlobalPaletteSize, lpGlobalPalette);
+ }
+ m_nCurrentBitmap = 0;
+ m_NextImageStartPosition = 0;
+ }
+
+ // We now need to go through and process the data in this file which
+ // should now consist off GIF blocks until we hit the end of file or
+ // we have processed the lot.
+ BOOL FileProcessed = FALSE;
+
+ m_bImageRead = FALSE;
+ unsigned char c;
+ // Set up bad values so that the DIB alloc claim will fail if there
+ // has been no GIFIMAGEBLOCK found
+// int Width = 0; // Width of bitmap
+// int Height = 0; // Height of bitmap
+// int BitsPerPixel = 0; //ColorResolution; // Colour depth required
+
+ if (m_NextImageStartPosition != 0)
+ {
+ File->seekIn(m_NextImageStartPosition, ios::beg);
+ m_NextImageStartPosition = 0;
+ }
+
+ while (!File->eof() && !File->bad() && !FileProcessed)
+ {
+ // Get the next character in the stream and see what it indicates
+ // comes next in the file
+ // Use Get as this will read the EOF character (255) and exit via the
+ // File->eof() test rather than Read which will throw an exception.
+ //File->read( &c, 1 );
+ File->get( (char&)c );
+
+ switch (c)
+ {
+ case ';':
+ {
+ // GIF terminator
+ // Cannot assume that the terminator immediately follows the image data
+ // Might have some extensions following the image data.
+ FileProcessed = TRUE;
+ nBitmapToRead = -1;
+ break;
+ }
+
+ case '!': //EXTENSIONBLOCK:
+ {
+ // Extension
+ ProcessExtension(File);
+ break;
+ }
+
+ case ',':
+ {
+ // start of image character
+ if (m_bImageRead) // another bitmap - save it for the next call to ReadFromFile()
+ {
+ if (m_NextImageStartPosition == 0)
+ {
+ // No transparency info for the next one so start here
+ m_NextImageStartPosition = File->tellIn() - 1;
+ }
+ ++nBitmapToRead;
+ FileProcessed = TRUE;
+ break;
+ }
+
+ UINT32 LeftOffset = 0;
+ UINT32 TopOffset = 0;
+ BOOL LocalPalette = FALSE;
+
+ // Should be followed by a GIFIMAGE BLOCK
+ ProcessImageBlock(File, Info, Bits, &LeftOffset, &TopOffset, &LocalPalette);
+ ++m_nCurrentBitmap;
+
+ if (nBitmapToRead == m_nCurrentBitmap)
+ {
+ m_bImageRead = TRUE;
+ }
+
+ // return the values back to the caller if it desired them
+ if (pLeftOffset)
+ *pLeftOffset = LeftOffset;
+ if (pTopOffset)
+ *pTopOffset = TopOffset;
+ if (pLocalPalette)
+ *pLocalPalette = LocalPalette;
+ break;
+ }
+
+ default:
+ // We have found something other than what we are expecting
+ // so fail with an error
+ //File->GotError( IDE_BADFORMAT );
+ // Cannot do this as some files have random bits
+ // e.g. galileo.gif has a random zero before the ;
+ // colsec.gif has a rampant > at the end instead of ;
+ if (m_bImageRead)
+ {
+ // We've already got something so ignore anything else in case it goes
+ // completely wrong.
+ FileProcessed = TRUE;
+ nBitmapToRead = -1;
+ }
+ TRACE( _T("Unrecognized Character %x at %d
"), (int)c, File->tellIn());
+
+ break;
+ }
+ }
+
+ // If we reach here and the bitmap allocations are still null then no valid image
+ // was found and so we should error now.
+ // Might have just been a GIF file with extension tags in and no images!
+ if (*Info == NULL || *Bits == NULL)
+ File->GotError( _R(IDE_BADFORMAT) );
+
+ // We read the desired bitmap but the EOF came along before we could try anything else
+ // Signal this is the last bitmap
+ if (m_bImageRead && File->eof())
+ {
+ TRACE( _T("GIF: Premature end of file") );
+ nBitmapToRead = -1;
+ }
+
+ // Return the transparency/delay/restore found to the caller.
+ *TransColour = Transparent;
+ if (Delay)
+ {
+ *Delay = m_Delay;
+ }
+ if (Restore)
+ {
+ *Restore = m_Restore;
+ }
+
+ // Free up the bit of memory for a palette we grabbed, if present & no more images to read
+ if (lpGlobalPalette && nBitmapToRead == -1)
+ {
+ CCFree(lpGlobalPalette);
+ lpGlobalPalette = NULL;
+ }
+
+ // If started, then stop then progress bar
+ if (ProgressString != NULL)
+ EndSlowJob();
+
+ // Must set the exception throwing and reporting flags back to their entry states
+ File->SetThrowExceptions( OldThrowingState );
+ File->SetReportErrors( OldReportingState );
+
+ // er, we seem to have finished OK so say so
+ return TRUE;
+ }
+ catch( CFileException e )
+ {
+ // catch our form of a file exception
+ TRACE( _T("GIFUtil::ReadFromFile CC catch handler
") );
+
+ FreeDIB( *Info, *Bits ); // free any alloced memory
+ *Info = NULL; // and NULL the pointers
+ *Bits = NULL;
+
+ // Free up the bit of memory for a palette we grabbed, if present
+ if (lpGlobalPalette)
+ {
+ CCFree(lpGlobalPalette);
+ lpGlobalPalette = NULL;
+ }
+
+ // If started, then stop then progress bar
+ if (ProgressString != NULL)
+ EndSlowJob();
+
+ // Must set the exception throwing and reporting flags back to their entry states
+ File->SetThrowExceptions( OldThrowingState );
+ File->SetReportErrors( OldReportingState );
+
+ return FALSE;
+ }
+
+ ERROR2( FALSE, "Escaped exception clause somehow" );
+}
+
+
+/********************************************************************************************
+
+> static BOOL GIFUtil::ProcessExtension(CCLexFile *fd)
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Inputs: fd pointer to a CCLexFile to read the data from
+ Outputs: -
+ Returns: True if worked ok, False otherwise.
+ Purpose:
+ SeeAlso:
+
+********************************************************************************************/
+
+BOOL GIFUtil::ProcessExtension(CCLexFile *fd)
+{
+ static char buf[256];
+
+ // Get the type of this extension and then process it
+ unsigned char ExtensionType;
+ fd->read( &ExtensionType, 1 );
+
+ switch (ExtensionType)
+ {
+ case TRANSPARENTBLOCK:
+ {
+ // The next image in the file might need to start here to get transparency
+ // information. So remember the position
+ m_NextImageStartPosition = fd->tellIn() - 2;
+
+ // Graphic Control Extension
+ // We have read in the identfier and the type of extension block so we
+ // really need to read the data from that point onwards
+ GIFTRANSBLOCK TransBlock;
+
+ // This is really sizeof(GIFTRANSBLOCK) but this returns 14 instead of 13
+ // as it rounds to the nearest word boundary
+ const size_t TransBlockSize = sizeof(WORD) * 1 + sizeof(BYTE) * 6;
+ fd->read( &(TransBlock.gtbBlockSize), TransBlockSize - 2);
+
+ // Contains lots of random rubbish we are not interested in.
+ // Just skip to the crux of the matter and read in the transparency colour,
+ // if the transparency flag is set.
+
+ if (!m_bImageRead)
+ {
+ BOOL fTrans = TransBlock.gtbFlags & 0x1;
+ if (fTrans != 0)
+ Transparent = TransBlock.gtbTransparency;
+ else
+ {
+ Transparent = -1; // no transparency
+ }
+
+ TRACEUSER("Neville", _T("ProcessExtension - transparent fTrans = %d Transparent = %d
"), fTrans, Transparent );
+
+ // Animation Restore\Delay values.
+ m_Delay = TransBlock.gtbDelay;
+ m_Restore = GIFDisposalMethod((TransBlock.gtbFlags >> 2) & 0x03);
+ }
+
+ return TRUE;
+ }
+
+ case PLAINTEXTBLOCK:
+ {
+ // We need to bin any transparency information we have since
+ // "The scope of this [Graphic Control (TRANSPARENTBLOCK)] Extension is the
+ // graphic rendering block that follows it"
+
+ if (m_bImageRead)
+ {
+ // We've read the image but don't need to start with any TRANSPARENT block
+ // that might have been read after the image, so make sure we don't
+ m_NextImageStartPosition = 0;
+ }
+ else
+ {
+ // We haven't read any image yet so just make sure no transparency
+ Transparent = -1;
+ }
+ // ...and drop through
+ }
+
+ default:
+ break;
+ }
+
+ // Must set this as otherwise, if this is after we have loaded an image then we have
+ // the possibility that the zero block has been encountered and GetDataBlock will
+ // always return 0, so force it not to.
+ ZeroDataBlock = FALSE;
+
+ // If not recognised then read the rest of that extension
+ while (GetDataBlock(fd, (unsigned char*) buf) != 0)
+ ;
+
+ return FALSE;
+}
+
+/********************************************************************************************
+
+> static BOOL GIFUtil::ReadColourMap(CCLexFile *fd, int number, LPRGBQUAD lpPalette)
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Inputs: fd pointer to a CCLexFile to read the data from
+ Outputs: -
+ Returns: True if worked ok, False otherwise.
+ Purpose:
+ SeeAlso:
+
+********************************************************************************************/
+
+BOOL GIFUtil::ReadColourMap(CCLexFile *fd, int number, LPRGBQUAD lpPalette)
+{
+ GIFRGBTRIPLE rgb;
+ for (int i = 0; i < number; ++i)
+ {
+ fd->read( &rgb, sizeof(GIFRGBTRIPLE) );
+ lpPalette->rgbBlue = rgb.grgbtBlue;
+ lpPalette->rgbGreen = rgb.grgbtGreen;
+ lpPalette->rgbRed = rgb.grgbtRed;
+ lpPalette->rgbReserved = 0;
+ lpPalette++;
+ }
+
+ return TRUE;
+}
+
+
+
+/********************************************************************************************
+
+> static int GIFUtil::GetDataBlock(CCLexFile *fd, unsigned char *buf)
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Inputs: fd pointer to a CCLexFile to read the data from
+ Outputs: -
+ Returns: Number of bytes read
+ Purpose: To read in a block of data from the specifed file. Reads a 1 byte count
+ and then reads that many bytes in, as long as the count is non-zero.
+ Any non-image calls must set ZeroDataBlock to False before calling this as
+ otherwise it may just return zero.
+ SeeAlso:
+
+********************************************************************************************/
+
+int GIFUtil::GetDataBlock(CCLexFile *fd, unsigned char *buf)
+{
+ unsigned char count;
+
+ // Added, as if we encounter the zero block then that is the end of this image
+ // and we should never read any more info from that image. (added 14/8/95)
+ if (ZeroDataBlock)
+ return 0;
+
+ fd->read( &count, 1 );
+
+ // If there is a count then read that many bytes in
+ // If zero then this is a terminator so return that
+ if (count == 0)
+ {
+ ZeroDataBlock = TRUE;
+ // Fall through to return 0
+ }
+ else
+ {
+ ZeroDataBlock = FALSE;
+ fd->read( buf, count );
+ // fall through to return the number of bytes found
+ }
+
+ return count;
+}
+
+/********************************************************************************************
+
+> static int GIFUtil::GetCode(CCLexFile *fd, int code_size, int flag)
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Inputs: fd pointer to a CCLexFile to read the data from
+ code_size
+ flag
+ Outputs: -
+ Returns: The code found.
+ Purpose: Returns the next code in the stream.
+ SeeAlso:
+
+********************************************************************************************/
+
+int GIFUtil::GetCode(CCLexFile *fd, int code_size, int flag)
+{
+ static unsigned char buf[280];
+ static int curbit;
+ static int lastbit;
+ static int done;
+ static int last_byte;
+ int i;
+ int j;
+ int ret;
+ unsigned char count;
+
+ if (flag)
+ {
+ curbit = 0;
+ lastbit = 0;
+ done = FALSE;
+ return 0;
+ }
+
+ if ( (curbit+code_size) >= lastbit)
+ {
+ if (done)
+ {
+ if (curbit >= lastbit)
+ {
+ /* Oh well */
+ }
+ return -1;
+ }
+ buf[0] = buf[last_byte-2];
+ buf[1] = buf[last_byte-1];
+
+ if ((count = GetDataBlock(fd, &buf[2])) == 0)
+ done = TRUE;
+
+ last_byte = 2 + count;
+ curbit = (curbit - lastbit) + 16;
+ lastbit = (2+count)*8 ;
+ }
+
+ ret = 0;
+ for (i = curbit, j = 0; j < code_size; ++i, ++j)
+ ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
+
+ curbit += code_size;
+
+ return ret;
+}
+
+
+/********************************************************************************************
+
+> static int GIFUtil::LWZReadByte(CCLexFile *fd, int flag, int input_code_size)
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Inputs: fd pointer to a CCLexFile to read the data from
+ flag
+ input_code_size
+ Outputs: -
+ Returns: The next LZW byte in the stream.
+ Purpose: To read the next LZW byte from the stream.
+ SeeAlso:
+
+********************************************************************************************/
+
+int GIFUtil::LWZReadByte(CCLexFile *fd, int flag, int input_code_size)
+{
+ static int fresh = FALSE;
+ int code;
+ int incode;
+ static int code_size;
+ static int set_code_size;
+ static int max_code;
+ static int max_code_size;
+ static int firstcode;
+ static int oldcode;
+ static int clear_code;
+ static int end_code;
+ static int table[2][(1<< MAX_LWZ_BITS)];
+ static int stack[(1<<(MAX_LWZ_BITS))*2];
+ static int *sp;
+ int i;
+
+ if (flag)
+ {
+ set_code_size = input_code_size;
+ code_size = set_code_size+1;
+ clear_code = 1 << set_code_size ;
+ end_code = clear_code + 1;
+ max_code_size = 2*clear_code;
+ max_code = clear_code+2;
+
+ GetCode(fd, 0, TRUE);
+
+ fresh = TRUE;
+
+ for (i = 0; i < clear_code; ++i)
+ {
+ table[0][i] = 0;
+ table[1][i] = i;
+ }
+ for (; i < (1<<MAX_LWZ_BITS); ++i)
+ table[0][i] = table[1][0] = 0;
+
+ sp = stack;
+
+ return 0;
+ }
+ else if (fresh)
+ {
+ fresh = FALSE;
+ do
+ {
+ firstcode = oldcode = GetCode(fd, code_size, FALSE);
+ } while (firstcode == clear_code);
+
+ return firstcode;
+ }
+
+ if (sp > stack)
+ return *--sp;
+
+ while ((code = GetCode(fd, code_size, FALSE)) >= 0)
+ {
+ if (code == clear_code)
+ {
+ for (i = 0; i < clear_code; ++i)
+ {
+ table[0][i] = 0;
+ table[1][i] = i;
+ }
+
+ for (; i < (1<<MAX_LWZ_BITS); ++i)
+ table[0][i] = table[1][i] = 0;
+
+ code_size = set_code_size+1;
+ max_code_size = 2*clear_code;
+ max_code = clear_code+2;
+ sp = stack;
+ firstcode = oldcode = GetCode(fd, code_size, FALSE);
+
+ return firstcode;
+ }
+ else if (code == end_code)
+ {
+ int count;
+ unsigned char buf[260];
+
+ if (ZeroDataBlock)
+ return -2;
+
+ while ((count = GetDataBlock(fd, buf)) > 0)
+ ;
+
+ if (count != 0)
+ return -2;
+ }
+
+ incode = code;
+
+ if (code >= max_code)
+ {
+ *sp++ = firstcode;
+ code = oldcode;
+ }
+
+ while (code >= clear_code)
+ {
+ *sp++ = table[1][code];
+ if (code == table[0][code])
+ {
+ /* Oh well */
+ }
+ code = table[0][code];
+ }
+
+ *sp++ = firstcode = table[1][code];
+
+ if ((code = max_code) <(1<<MAX_LWZ_BITS))
+ {
+ table[0][code] = oldcode;
+ table[1][code] = firstcode;
+ ++max_code;
+ if ((max_code >= max_code_size) && (max_code_size < (1<<MAX_LWZ_BITS)))
+ {
+ max_code_size *= 2;
+ ++code_size;
+ }
+ }
+
+ oldcode = incode;
+
+ if (sp > stack)
+ return *--sp;
+ }
+ return code;
+}
+
+/********************************************************************************************
+
+> static BOOL GIFUtil::ReadImage(CCLexFile *fd, LPBYTE pBitsData, int width, int height,
+ BOOL interlace, BaseCamelotFilter *pFilter = NULL )
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Inputs: fd pointer to a CCLexFile to read the data from
+ pBitsData pointer to the place to put the bitmap data, should have been
+ claimed so that it is the correct size to contain it.
+ width width of the bitmap in pixels
+ height height of the bitmap in pixels
+ bpp colour depth of the bitmap in bits per pixel
+ interlace flag to say if this data is interlaced or not.
+ pFilter is an alternative way of handling the progress bar, assume the
+ progress bar has been start and just call the IncProgressBarCount in
+ BaseCamelotFilter to do the progress bar update.
+ Defaults to NULL i.e. no progress bar.
+ Purpose: The read the bitmap data into the specified buffer. It decompresses the
+ data from the specified file and then puts the pixel data into the buffer.
+ Copes with interlaced GIFs.
+ Assumes progress hourglass has been started with 100.
+ SeeAlso: GIFUtil::ReadFromFile;
+
+********************************************************************************************/
+
+BOOL GIFUtil::ReadImage(CCLexFile *fd, LPBYTE pBitsData, int width, int height, int bpp,
+ BOOL interlace, BaseCamelotFilter *pFilter)
+{
+ ERROR2IF(pBitsData == NULL, FALSE, "GIFUtil::ReadImage given null pointer to bits data");
+ ERROR2IF(bpp != 8 && bpp != 4 && bpp != 1, FALSE, "GIFUtil::ReadImage - bpp invalid");
+
+ unsigned char c;
+ int v = 0;
+ int xpos = 0;
+ int ypos = 0;
+ int pass = 0;
+ int yposcount = 0;
+
+ ZeroDataBlock = FALSE;
+
+ // Work out how often we need to update the progress bar
+ int UpdateEvery = 1;
+ INT32 UpdateValue = 1;
+ if (pFilter == NULL)
+ UpdateEvery = height/100 + 1;
+ else
+ {
+ // Ask the filter what the record size for this bitmap is and hence
+ // what the allocation we have for progress bar updates are.
+ // We will then have to update our progress bar by
+ // current scanline/total number of scanlines * allocation
+ // so that we get update by a proportion of the value.
+ // We can assume no interlacing as in native/web files this is turned off.
+ INT32 RecordSize = pFilter->GetCurrentRecordSize();
+ if (RecordSize == 0)
+ RecordSize = 1;
+ UpdateValue = RecordSize/height;
+ UpdateEvery = 0; // So it updates every time round the loop
+ }
+
+ int LastProgressUpdate = 0;
+
+ // Work out the word/byte rounded line width rather than the pixel width
+ INT32 WidthOfLine = DIBUtil::ScanlineSize( width, bpp );
+
+ // Initialize the Compression routines
+ fd->read( &c, 1 );
+ ERROR3IF(c > GIFBITS,"Bad code size in GIFUtil ReadImage");
+
+ if (LWZReadByte(fd, TRUE, c) < 0)
+ {
+ return FALSE;
+ }
+
+ while ((v = LWZReadByte(fd, FALSE, c)) >= 0 )
+ {
+ //GIFSetPixel(pBitsData, xpos, ypos, v);
+ // Check that the specified pixel is within the bounds specified and that we
+ // have a buffer to write to
+
+// if ( !(((ypos < 0) || (ypos >= height)) || ((xpos < 0) || (xpos >= width))) && pBitsData )
+// {
+ // Our DIBs are the wrong way up so we must output the data from the last
+ // line of the image and go up to the start
+ // -1 as height = 1 .. Height whereas y goes from 0 .. Height - 1
+ // Use the word/byte rounded line width rather than the pixel width
+ if (bpp == 8)
+ {
+ // If 8 bpp then just use the whole byte straight
+ LPBYTE pData = pBitsData + xpos + ((height - 1 - ypos) * WidthOfLine);
+ *(pData) = v;
+ }
+ else if (bpp == 4)
+ {
+ // 4bpp so we must put the data into either the high or low nibble.
+ // This will be dependent on whether we are on an odd or even pixel.
+ // So test the LSBit of the curx, if set we will be odd.
+ // Only move onto next byte every other pixel hence curx/2.
+ LPBYTE pData = pBitsData + xpos/2 + ((height - 1 - ypos) * WidthOfLine);
+ // Get whole present byte
+ if (xpos & 1)
+ *(pData) = ((*(pData)) & 0xF0) | (v & 0x0F); // add into low nibble
+ else
+ *(pData) = ((*(pData)) & 0x0F) | ((v << 4) & 0xF0); // add into top nibble
+ }
+ else if (bpp == 1)
+ {
+ // 1bpp so we must put the data into either the high or low nibble.
+ // This will be dependent on whether we are on an odd or even pixel.
+ // So test the LSBit of the curx, if set we will be odd.
+ // Only move onto next byte every other pixel hence curx/2.
+ LPBYTE pOutputBitmap = pBitsData + (xpos / 8) + ((height - 1 - ypos) * WidthOfLine);
+ // Get whole present byte
+ UINT32 BitPosition = 7 - (xpos % 8);
+ BYTE SetBit = v << BitPosition;
+ BYTE Mask = ~(1 << BitPosition);
+
+ *pOutputBitmap = ((*pOutputBitmap) & Mask) | SetBit;
+ }
+ else
+ {
+ ERROR3IF(TRUE, "GIFUtil::ReadImage() - Invalid bpp");
+ // bad bpp but should not get here so do nothing
+ }
+
+// }
+
+ ++xpos;
+
+ BOOL JobState = TRUE;
+ // if we have reached the end of the current line then work out the next
+ // line that we must do, if interlacing is on
+ if (xpos >= width)
+ {
+ xpos = 0;
+
+ // Do different filing methods depending on whether interlaced on non-interlaced.
+ if (interlace)
+ {
+ // We are interlaced so learn not to count properly!
+ switch (pass)
+ {
+ case 0:
+ case 1:
+ ypos += 8; break;
+ case 2:
+ ypos += 4; break;
+ case 3:
+ ypos += 2; break;
+ }
+
+ while (ypos >= height && pass <= 3)
+ {
+ ++pass;
+ switch (pass)
+ {
+ case 1:
+ ypos = 4;
+ break;
+ case 2:
+ ypos = 2;
+ break;
+ case 3:
+ ypos = 1;
+ break;
+ default:
+ goto finish;
+ }
+ }
+ }
+ else
+ {
+ // Non-interlaced case
+ ++ypos;
+ }
+
+ yposcount++;
+
+ if (yposcount > (LastProgressUpdate + UpdateEvery))
+ {
+ // Note the update point so that we know the next one
+ LastProgressUpdate = yposcount;
+
+ // Now update the progress display, started with 100
+ if (pFilter == NULL)
+ JobState = ContinueSlowJob( (long)(100 * yposcount/height) );
+ else
+ JobState = pFilter->IncProgressBarCount(UpdateValue);
+
+ // If JobState is False then the user has probably pressed escape and we should
+ // immediately stop what we are doing.
+ if (!JobState)
+ {
+ fd->GotError( _R(IDW_CANCELLEDBMPIMPORT) ); // Expects error set on cancel
+ return FALSE;
+ }
+ }
+ }
+
+ if (ypos >= height)
+ break;
+ }
+
+finish:
+ if (LWZReadByte(fd, FALSE, c) >= 0)
+ {
+ /* Ignore extra */
+ }
+
+ // Everything seemed to go ok
+ return TRUE;
+}
+
+
+/********************************************************************************************
+
+> static void GIFUtil::GIFSetPixel(LPBYTE pBitsData, int x, int y, int colour)
+
+ Author: Neville Humphrys
+ Created: 29/6/95
+ Inputs:
+ Outputs:
+ Returns:
+ Purpose:
+ SeeAlso:
+
+********************************************************************************************/
+
+//void GIFUtil::GIFSetPixel(LPBYTE pBitsData, int x, int y, int colour)
+//{
+// // Check that the specified pixel is within the bounds specified and that we
+// // have a buffer to write to
+// if ( !(((y < 0) || (y >= Height)) || ((x < 0) || (x >= Width))) && pBitsData )
+// {
+// // Our DIBs are the wrong way up so we must output the data from the last
+// // line of the image and go up to the start
+// // -1 as height = 1 .. Height whereas y goes from 0 .. Height - 1
+// // Use the word/byte rounded line width rather than the pixel width
+// LPBYTE pData = pBitsData + x + ((Height - 1 - y) * WidthOfLine);
+// *(pData) = colour;
+// }
+//}
+
+/********************************************************************************************
+
+> static BOOL ReadColourMap(CCLexFile *fd, Palette& NewPalette)
+
+ Author: Colin
+ Created: 29/6/95
+ Inputs: fd pointer to a CCLexFile to read the data from
+ Outputs: -
+ Returns: True if worked ok, False otherwise.
+ Purpose:
+ SeeAlso:
+
+********************************************************************************************/
+BOOL Palette::SetSize(const UINT32 nNewSize)
+{
+ if (nNewSize == m_nSize) return TRUE;
+ if (m_pColours != NULL)
+ {
+ delete [] m_pColours;
+ }
+ if (nNewSize == 0)
+ {
+ m_pColours = NULL;
+ return TRUE;
+ }
+ m_pColours = new RGBQUAD[nNewSize];
+// m_StartIterator;
+// m_EndIterator;
+ return (m_pColours == NULL) ? FALSE : TRUE;
+}
+
+
+static BOOL ReadColourMap(CCLexFile *fd, Palette& NewPalette)
+{
+ GIFRGBTRIPLE rgb;
+ PaletteIterator PalColour;
+ for (PalColour = NewPalette.Start(); PalColour < NewPalette.End(); ++PalColour)
+ {
+ fd->read(&rgb, sizeof(GIFRGBTRIPLE));
+
+ PalColour.SetBlue(rgb.grgbtBlue);
+ PalColour.SetGreen(rgb.grgbtGreen);
+ PalColour.SetRed(rgb.grgbtRed);
+ PalColour.SetTransparent(0);
+ }
+
+ return TRUE;
+}
+
+/********************************************************************************************
+
+> BOOL GIFUtil::ProcessHeader()
+
+ Author: Colin
+ Created: 11/06/96
+ Inputs:
+ Outputs:
+ Returns:
+ Purpose:
+ SeeAlso:
+
+********************************************************************************************/
+BOOL GIFUtil::ProcessHeader()
+{
+ ERROR3("GIFUtil::ProcessHeader : not implemented");
+ if (TRUE) return FALSE;
+
+ CCLexFile* File;
+ GIFINFOHEADER Header;
+ // This is really sizeof(GIFINFOHEADER) but this returns 14 instead of 13
+ // as it rounds to the nearest word boundary
+ const size_t HeaderSize = sizeof(char)* 6 + sizeof(WORD) * 2 + sizeof(BYTE) * 3;
+// const size_t HeaderSize = (sizeof(GIFINFOHEADER)* sizeof(WORD)) / sizeof(WORD);
+
+ File->read( &Header, HeaderSize );
+ if (File->bad())
+ File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
+
+ // Just double check that the signature is correct, if not then fail immediately
+ if (
+ ( strncmp( Header.giName, "GIF89a", 6 ) != 0 ) &&
+ ( strncmp( Header.giName, "GIF87a", 6 ) != 0 )
+ )
+ File->GotError( _R(IDE_BADFORMAT) );
+
+ // Note the overall size of the GIF from the header, may be the animation size
+ m_GlobalWidth = Header.giWidth;
+ m_GlobalHeight = Header.giHeight;
+// int ColorResolution = (((Header.giFlags >> 4) & 0x07) + 1);
+// int AspectRatio = Header.giAspect;
+
+ UINT32 nGlobalPaletteSize = 2 << (Header.giFlags & 0x07);
+// m_nBackground = Header.giBackground;
+
+ // Check if we have a global colour map present or not, if so then read it in.
+ if (BitSet(Header.giFlags, GLOBALCOLOURMAP))
+ {
+ // Read in the global colour map into a palette structure for possible later use
+ if (m_GlobalPalette.SetSize(nGlobalPaletteSize) == FALSE)
+ {
+ ERROR3("GIFUtil::ProcessHeader() - can't renew palette");
+ return FALSE;
+ }
+ ::ReadColourMap(File, m_GlobalPalette);
+ }
+ m_nCurrentBitmap = 0;
+}
+
+
+/********************************************************************************************
+
+> BOOL GIFUtil::ProcessImageBlock(CCLexFile* File, LPBITMAPINFO *Info, LPBYTE *Bits,
+ UINT32 * pLeftOffset = NULL, UINT32 * pTopOffset = NULL,
+ BOOL * pLocalPalette = NULL)
+
+ Author: Colin
+ Created: 11/06/96
+ Inputs:
+ Outputs:
+ Returns:
+ Purpose:
+ SeeAlso:
+
+********************************************************************************************/
+BOOL GIFUtil::ProcessImageBlock(CCLexFile* File, LPBITMAPINFO *Info, LPBYTE *Bits,
+ UINT32 * pLeftOffset, UINT32 * pTopOffset, BOOL * pLocalPalette)
+{
+ GIFIMAGEBLOCK ImageBlock;
+ // This is really sizeof(GIFIMAGEBLOCK) but this returns 10 instead of 9 as it rounds to the nearest word boundary
+ const size_t ImageHeaderSize = sizeof(WORD) * 4 + sizeof(BYTE) * 1;
+ File->read( &ImageBlock, ImageHeaderSize );
+
+ // Check whether we there is a local colour map or not
+ // If there is use that otherwise use the global one read in earlier
+ BOOL UseLocalColourMap = BitSet(ImageBlock.gibFlags, LOCALCOLOURMAP);
+ int LocalColourMapSize = 1 << ((ImageBlock.gibFlags & 0x07) + 1);
+
+ int Width = ImageBlock.gibWidth; //LM_to_uint(buf[4],buf[5]);
+ int Height = ImageBlock.gibDepth; //LM_to_uint(buf[6],buf[7]);
+
+ // If the user asked for them and they are within the animation's boundaries
+ // Then return the offsets to the user
+ if (pLeftOffset && ImageBlock.gibLeft < m_GlobalWidth)
+ *pLeftOffset = ImageBlock.gibLeft;
+ if (pTopOffset && ImageBlock.gibTop < m_GlobalHeight)
+ *pTopOffset = ImageBlock.gibTop;
+ if (pLocalPalette)
+ *pLocalPalette = UseLocalColourMap;
+
+ Interlace = BitSet(ImageBlock.gibFlags, INTERLACE);
+
+ int ColoursInPalette = UseLocalColourMap ? LocalColourMapSize : GlobalPaletteSize;
+ int BitsPerPixel;
+ if (ColoursInPalette > 16)
+ BitsPerPixel = 8;
+ else if (ColoursInPalette > 2)
+ BitsPerPixel = 4;
+ else
+ BitsPerPixel = 1;
+
+TRACEUSER("Neville", _T("Colours in palette = %d bpp = %d
"), ColoursInPalette, BitsPerPixel );
+
+ // Allocate the space that we require for this bitmap
+ // Sanity checks on the file that we have been asked to load.
+ if ((BitsPerPixel != 8) && (BitsPerPixel != 4) && (BitsPerPixel != 1) && (Width != 0) && (Height != 0))
+ File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
+
+ // we know what sort of bitmap we are - lets allocate a new LPBITMAPINFO and some bytes
+ *Info = AllocDIB( Width, Height, BitsPerPixel, Bits, NULL );
+
+ if (*Info == NULL || *Bits == NULL)
+ File->GotError( _R(IDS_OUT_OF_MEMORY) );
+
+ // if the clrUsed field is zero, put a sensible value in it
+
+ BOOL ok = FALSE;
+ if (UseLocalColourMap)
+ {
+ // There is a local colour table specified so read this directly into
+ // the palette of the DIB
+ if (LocalColourMapSize > (1 << BitsPerPixel))
+ File->GotError( _R(IDE_BADFORMAT) );
+
+ ReadColourMap(File, LocalColourMapSize, (*Info)->bmiColors);
+ }
+ else
+ {
+ // No local palette so copy the global palette into the palette of the DIB, if
+ if (lpGlobalPalette && ((*Info)->bmiColors))
+ {
+ const size_t TotalPal = sizeof(RGBQUAD) * GlobalPaletteSize;
+ memcpy((*Info)->bmiColors, lpGlobalPalette, TotalPal);
+ }
+ }
+
+ // Note how many colours are in the palette
+ (*Info)->bmiHeader.biClrUsed = ColoursInPalette;
+
+ ok = ReadImage(File, *Bits, Width, Height, BitsPerPixel, Interlace);
+ // Now read all that lovely data in
+ if (!ok)
+ File->GotError( _R(IDE_BADFORMAT) );
+
+ return TRUE;
+}
+
+
Index: Trunk/XaraLX/wxOil/Makefile.am
===================================================================
--- Trunk/XaraLX/wxOil/Makefile.am (revision 1347)
+++ Trunk/XaraLX/wxOil/Makefile.am (revision 1348)
@@ -23,7 +23,7 @@
memblk.cpp memory.cpp monotime.cpp mtrand.cpp oilbitmap.cpp oilcoord.cpp \
oildbug.cpp oilrect.cpp pathname.cpp pathnmex.cpp pen.cpp sgliboil.cpp \
tunemem.cpp unicdman.cpp vstate.cpp wincoord.cpp oilfiles.cpp oilmenus.cpp \
- winrect.cpp grndrgn.cpp osrndrgn.cpp grndbmp.cpp rendbits.cpp \
+ gifutil.cpp giffiltr.cpp winrect.cpp grndrgn.cpp osrndrgn.cpp grndbmp.cpp rendbits.cpp \
palman.cpp gdrawcon.cpp fuzzclip.cpp cursor.cpp pngfiltr.cpp pngutil.cpp \
maskfilt.cpp oilfltrs.cpp speedtst.cpp gbrush.cpp grnddib.cpp grndclik.cpp \
offscrn.cpp camprofile.cpp localenv.cpp camresource.cpp oilmods.cpp \
Index: Trunk/XaraLX/wxOil/giffiltr.cpp
===================================================================
--- Trunk/XaraLX/wxOil/giffiltr.cpp (revision 1347)
+++ Trunk/XaraLX/wxOil/giffiltr.cpp (revision 1348)
@@ -119,10 +119,10 @@
//#include "will3.h" // for _R(IDS_GENOPTPALMSGID)
#include "maskfilt.h" // MaskedFilter class
-//#include "bmpsdlg.h"
-//#include "frameops.h" // GIFAnimationExportParam
+#include "bmpsdlg.h"
+#include "frameops.h" // GIFAnimationExportParam
//#include "spread.h" // Pasteboard rect - in camtypes.h [AUTOMATICALLY REMOVED]
-//#include "bmapprev.h" // tab preview dialog
+#include "bmapprev.h" // tab preview dialog
#include "palman.h" // MakePaletteBrowserCompatible
#include "sprdmsg.h" // SpreadMsg::ANIMATIONPROPERTIESCHANGED
#include "impexpop.h"
@@ -133,7 +133,6 @@
#include "menuops.h"
//#include "outptdib.h" - in camtypes.h [AUTOMATICALLY REMOVED]
-//#include "bmapprev.h"
//#include "cxfrec.h" // for CXaraFileRecord - in camtypes.h [AUTOMATICALLY REMOVED]
#include "mrhbits.h" // For CBMPBits::RenderSelectionToBMP
@@ -745,8 +744,8 @@
// Try to import bitmap as usual binary BMP file.
CWxBitmap* pWBitmap = (CWxBitmap*) pOilBitmap;
-// LPBITMAPINFO *pInfo = &(pWBitmap->BMInfo);
-// LPBYTE *pBytes = &(pWBitmap->BMBytes);
+ LPBITMAPINFO *pInfo = &(pWBitmap->BMInfo);
+ LPBYTE *pBytes = &(pWBitmap->BMBytes);
// Set a default transparent colour
INT32 TransColour = -1;
@@ -758,12 +757,7 @@
// Read from file, no header and using pFilter for progress bar updates
// 20/01/97 In fact pFilter is not used so NULL ptr ok
-PORTNOTE("GIFFilter", "Removed use of gif code")
-#ifndef EXCLUDE_FROM_XARALX
if (!GIFUtil::ReadFromFile(pFile, pInfo, pBytes, &TransColour, NULL, pFilter))
-#else
- if (FALSE)
-#endif
{
if (!pFilter)
EndSlowJob();
@@ -818,10 +812,10 @@
SetTransColour(TransColour);
INT32 nBitmapToRead = GetBitmapNumber();
-// CWxBitmap* pWBitmap = (CWxBitmap*)pOilBitmap;
+ CWxBitmap* pWBitmap = (CWxBitmap*)pOilBitmap;
-// LPBITMAPINFO *pInfo = &(pWBitmap->BMInfo);
-// LPBYTE *pBytes = &(pWBitmap->BMBytes);
+ LPBITMAPINFO *pInfo = &(pWBitmap->BMInfo);
+ LPBYTE *pBytes = &(pWBitmap->BMBytes);
// Receives the Bitmap delay/Restore value from the Import.
UINT32 Delay=0;
GIFDisposalMethod Restore = GDM_LEAVE;
@@ -831,13 +825,8 @@
m_TopOffset = 0;
// The GIF filter liked it very much and so use it, showing progress bar
-PORTNOTE("GIFFilter", "Removed use of gif code")
-#ifndef EXCLUDE_FROM_XARALX
if (GIFUtil::ReadFromFile(pImportFile, pInfo, pBytes, &TransColour,nBitmapToRead, &ProgressString, NULL,
&Delay, &Restore, &m_LeftOffset, &m_TopOffset))
-#else
- if (FALSE)
-#endif
{
// Set the Delay\Restore value of the OILBitmap.
pOilBitmap->SetBitmapAnimDelay(Delay);
@@ -892,8 +881,6 @@
BOOL TI_GIFFilter::GetDragAndDropTranslation(ImportPosition *pPos, DocRect BoundsRect,
Coord* Offset)
{
-PORTNOTE("GIFFilter", "Removed use of gif code")
-#if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
// First check to se if we actually have a drag and drop point.
if (pPos == NULL || pPos->pSpread == NULL)
{
@@ -978,11 +965,6 @@
// Whatever happened, we can fit it on the spread.
return TRUE;
-#else
- Offset->x = 0;
- Offset->y = 0;
- return FALSE;
-#endif
}
/********************************************************************************************
@@ -1005,8 +987,6 @@
BOOL TI_GIFFilter::SetFlagsFromBitmap(Layer * pLayer, KernelBitmap * pBitmap,
UINT32 nBitmapToRead)
{
-PORTNOTE("GIFFilter", "Removed use of gif code")
-#if !defined(EXCLUDE_FROM_XARALX)
if (pBitmap && pLayer)
{
// transfer the disposal method from the bitmap to the layer
@@ -1047,9 +1027,6 @@
}
return TRUE;
-#else
- return FALSE;
-#endif
}
/********************************************************************************************
@@ -1107,8 +1084,6 @@
BOOL TI_GIFFilter::SetAnimationPropertiesFromLoaded(Spread * pSpread)
{
-//PORTNOTE("GIFFilter", "Removed use of gif code")
-//#if !defined(EXCLUDE_FROM_XARALX)
ERROR2IF(pSpread == NULL,FALSE,"SetAnimationPropertiesFromLoaded pSpread = NULL");
// Find out about the palettes that the bitmaps have
@@ -1159,9 +1134,6 @@
}
return TRUE;
-//#else
-// return FALSE;
-//#endif
}
/********************************************************************************************
@@ -1226,8 +1198,6 @@
//[MD]
#ifndef STANDALONE
-PORTNOTE("GIFFilter", "Removed use of gif code")
-#if !defined(EXCLUDE_FROM_XARALX)
ERROR2IF(pOptions == NULL, FALSE, "NULL Args");
GIFExportOptions* pGIFOptions = (GIFExportOptions*)pOptions;
@@ -1248,7 +1218,7 @@
// on/off interlaced and on/off transparent
// Determine the filter type currently in use in Accusoft format
- s_FilterType = (pGIFOptions->GetSelectionType() == SOMEBITMAPS) ? TI_GIF_ANIM : TI_GIF);
+ s_FilterType = (pGIFOptions->GetSelectionType() == SOMEBITMAPS) ? TI_GIF_ANIM : TI_GIF;
pGIFOptions->SetFilterType(s_FilterType);
m_DoingAnimation = (pGIFOptions->GetSelectionType() == SOMEBITMAPS);
@@ -1281,15 +1251,14 @@
}
else
{
+#ifndef EXCLUDE_FROM_XARALX
// invoke the dialog
Ok = BmpPrefsDlg::InvokeDialog( pOptions);
+#endif
}
// Return with the ok/cancel state used on the dialog box
return Ok;
-#else
- return FALSE;
-#endif
#else
return FALSE;
@@ -1551,9 +1520,7 @@
BOOL TI_GIFFilter::SaveExportBitmapsToFile(CCLexFile* pFile, PathName* pPath, BitmapExportParam* pParam,
BOOL DontShowFileName)
{
-#ifdef DO_EXPORT
-PORTNOTE("GIFFilter", "Removed use of gif code")
-#if !defined(EXCLUDE_FROM_XARALX)
+#if defined(DO_EXPORT) && !defined(EXCLUDE_FROM_XARALX)
ERROR2IF(pFile == NULL || pPath == NULL, FALSE,"NULL Parameters");
ERROR2IF(pParam == NULL,FALSE,"TI_GIFFilter::DoExportBitmaps null BitmapExportParam specified");
@@ -1794,7 +1761,7 @@
// Check that we have an animation size information block
ERROR2IF(pTrueInfoHeader==NULL,FALSE,"TI_GIFFilter::WriteToFile BitmapInfoHeader pointer is null");
- Index = 0;
+ UINT32 Index = 0;
AnimatedGIFImage * pCurrentGIFImage = (AnimatedGIFImage *)BitmapFrameList.GetHead();
while ( ok && pCurrentGIFImage)
{
@@ -1904,10 +1871,7 @@
CleanUpAfterExport();
return ok;
-#else
- return FALSE;
#endif
-#endif
return FALSE;
}
@@ -1972,14 +1936,12 @@
return 0;
}
-PORTNOTE("GIFFilter", "Removed use of gif code")
-#if !defined(EXCLUDE_FROM_XARALX)
// Check the header for the "GIF" signature.
LPGIFINFOHEADER pHeader = (LPGIFINFOHEADER) HeaderStart;
if (
- (camStrncmp(pHeader->giName, "GIF89a", 6) == 0) ||
- (camStrncmp(pHeader->giName, "GIF87a", 6) == 0)
+ ( strncmp( pHeader->giName, "GIF89a", 6 ) == 0 ) ||
+ ( strncmp( pHeader->giName, "GIF87a", 6 ) == 0 )
)
{
// the other fields in the GIFINFOHEADER don't really hold any useful information
@@ -1990,7 +1952,6 @@
GIFHowCompatible = 10;
}
else
-#endif
{
// No GIF signature - we don't want this file.
GIFHowCompatible = 0;
Index: Trunk/XaraLX/wxOil/outptgif.cpp
===================================================================
--- Trunk/XaraLX/wxOil/outptgif.cpp (revision 1347)
+++ Trunk/XaraLX/wxOil/outptgif.cpp (revision 1348)
@@ -108,7 +108,7 @@
//#include "andy.h"
//#include "dibconv.h" - in camtypes.h [AUTOMATICALLY REMOVED]
#include "progress.h" // For hourglass stuff
-//#include "gifutil.h" // GIF header definitions
+#include "gifutil.h" // GIF header definitions
//#include "string.h" // memcpy
//#include "camfiltr.h" // BaseCamelotFilter - in camtypes.h [AUTOMATICALLY REMOVED]
@@ -444,8 +444,6 @@
********************************************************************************************/
BOOL OutputGIF::OutputGifFileHeader(CCLexFile *File, LPBITMAPINFOHEADER pInfo, BOOL Enhanced, INT32 TransColour, LPLOGPALETTE pPalette, LPRGBQUAD pQuadPalette)
{
-PORTNOTETRACE("GIFFilter", "Removed use of GIF code");
-#ifndef EXCLUDE_FROM_XARALX
ERROR2IF(File==NULL,FALSE,"OutputGIF::OutputGifHeader File pointer is null");
ERROR2IF(pInfo==NULL,FALSE,"OutputGIF::OutputGifHeader BitmapInfo pointer is null");
ERROR2IF(pPalette==NULL && pQuadPalette==NULL,FALSE,"OutputGIF::OutputGifHeader Bitmap palette pointer is null");
@@ -599,9 +597,6 @@
}
ERROR2( FALSE, "Escaped exception clause somehow" );
-#else
- return FALSE;
-#endif
}
@@ -622,8 +617,6 @@
********************************************************************************************/
BOOL OutputGIF::OutputGifImageExtensionHeader(CCLexFile *File, BOOL InterlaceState, INT32 TransparentColour, UINT32 Delay, UINT32 RestoreType)
{
-PORTNOTETRACE("GIFFilter", "Removed use of GIF code");
-#ifndef EXCLUDE_FROM_XARALX
ERROR2IF(File==NULL,FALSE,"OutputGIF::OutputGifHeader File pointer is null");
ERROR3IF(RestoreType > 3, "Unknown GIF image restore type");
@@ -675,9 +668,6 @@
}
ERROR2( FALSE, "Escaped exception clause somehow" );
-#else
- return FALSE;
-#endif
}
@@ -855,8 +845,6 @@
LPRGBQUAD pDestPalette, UINT32 PaletteColourDepth, UINT32 NewBitsPerPixel)
{
-PORTNOTETRACE("GIFFilter", "Removed use of GIF code");
-#ifndef EXCLUDE_FROM_XARALX
ERROR2IF(File==NULL,FALSE,"OutputGIF::OutputGifHeader File pointer is null");
ERROR2IF(pBlockStart==NULL,FALSE,"OutputGIF::OutputGifHeader BitmapInfo pointer is null");
@@ -1014,9 +1002,6 @@
}
ERROR2( FALSE, "Escaped exception clause somehow" );
-#else
- return FALSE;
-#endif
}
@@ -1391,8 +1376,6 @@
void OutputGIF::OutputCode( code_int code )
{
-PORTNOTETRACE("GIFFilter", "Removed use of GIF code");
-#ifndef EXCLUDE_FROM_XARALX
cur_accum &= masks[ cur_bits ];
if( cur_bits > 0 )
@@ -1442,7 +1425,6 @@
OutputFile->flush();
}
-#endif
}
/********************************************************************************************
Xara