From 464122b639263c81fcbd698bae3826313d2165a2 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Wed, 18 Aug 1999 06:28:20 +0000 Subject: [PATCH] Added gifdecod.cpp git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3407 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/common/gifdecod.cpp | 606 ++++++++++++++++++++++++++++++++++++++++ src/common/imaggif.cpp | 396 ++------------------------ 2 files changed, 625 insertions(+), 377 deletions(-) create mode 100644 src/common/gifdecod.cpp diff --git a/src/common/gifdecod.cpp b/src/common/gifdecod.cpp new file mode 100644 index 0000000000..047189cc51 --- /dev/null +++ b/src/common/gifdecod.cpp @@ -0,0 +1,606 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: gifdecod.cpp +// Purpose: wxGIFDecoder, GIF reader for wxImage and wxAnimation +// Author: Guillermo Rodriguez Garcia +// Version: 3.01 +// Last rev: 1999/08/14 +// Copyright: (c) Guillermo Rodriguez Garcia +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation "gifdecod.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +# pragma hdrstop +#endif + +#ifndef WX_PRECOMP +# include "wx/setup.h" +#endif + +#if wxUSE_STREAMS + +#include +#include +#include "wx/defs.h" +#include "wx/gifdecod.h" + + +//--------------------------------------------------------------------------- +// wxGIFDecoder constructor and destructor +//--------------------------------------------------------------------------- + +wxGIFDecoder::wxGIFDecoder(wxInputStream *s, bool anim) +{ + m_f = s; + m_anim = anim; + + m_background = -1; + m_screenw = 0; + m_screenh = 0; + + m_pimage = NULL; + m_pfirst = NULL; + m_plast = NULL; + m_image = 0; + m_nimages = 0; +} + +wxGIFDecoder::~wxGIFDecoder() +{ + Destroy(); +} + +void wxGIFDecoder::Destroy() +{ + IMAGEN *pimg, *paux; + + pimg = m_pfirst; + + while (pimg != NULL) + { + paux = pimg->next; + free(pimg->p); + free(pimg->pal); + free(pimg); + pimg = paux; + } +} + + +//--------------------------------------------------------------------------- +// Convert this image to a wxImage object +//--------------------------------------------------------------------------- + +// This function was designed by Vaclav Slavik + +bool wxGIFDecoder::ConvertToImage(wxImage *image) const +{ + unsigned char *src, *dst, *pal; + unsigned long i; + int transparent; + + /* create the image */ + image->Create(GetWidth(), GetHeight()); + + if (!image->Ok()) + return FALSE; + + pal = GetPalette(); + src = GetData(); + dst = image->GetData(); + transparent = GetTransparentColour(); + + /* set transparent colour mask */ + if (transparent != -1) + { + for (i = 0; i < 256; i++) + { + if ((pal[3 * i + 0] == 255) && + (pal[3 * i + 1] == 0) && + (pal[3 * i + 2] == 255)) + { + pal[3 * i + 2] = 254; + } + } + + pal[3 * transparent + 0] = 255, + pal[3 * transparent + 1] = 0, + pal[3 * transparent + 2] = 255; + + image->SetMaskColour(255, 0, 255); + } + else + image->SetMask(FALSE); + + /* copy image data */ + for (i = 0; i < (GetWidth() * GetHeight()); i++, src++) + { + *(dst++) = pal[3 * (*src) + 0]; + *(dst++) = pal[3 * (*src) + 1]; + *(dst++) = pal[3 * (*src) + 2]; + } + + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Data accessors +//--------------------------------------------------------------------------- + +// Get data for current frame + +int wxGIFDecoder::GetFrameIndex() const { return m_image; } +unsigned char* wxGIFDecoder::GetData() const { return (m_pimage->p); } +unsigned char* wxGIFDecoder::GetPalette() const { return (m_pimage->pal); } +unsigned int wxGIFDecoder::GetWidth() const { return (m_pimage->w); } +unsigned int wxGIFDecoder::GetHeight() const { return (m_pimage->h); } +unsigned int wxGIFDecoder::GetTop() const { return (m_pimage->top); } +unsigned int wxGIFDecoder::GetLeft() const { return (m_pimage->left); } +int wxGIFDecoder::GetTransparentColour() const { return (m_pimage->transparent); } +int wxGIFDecoder::GetDisposalMethod() const { return (m_pimage->disposal); } +long wxGIFDecoder::GetDelay() const { return (m_pimage->delay); } + +// Get global data + +unsigned int wxGIFDecoder::GetLogicalScreenWidth() const { return m_screenw; } +unsigned int wxGIFDecoder::GetLogicalScreenHeight() const { return m_screenh; } +int wxGIFDecoder::GetBackgroundColour() const { return m_background; } +int wxGIFDecoder::GetNumberOfFrames() const { return m_nimages; } +bool wxGIFDecoder::IsAnimation() const { return (m_nimages > 1); } + + +//--------------------------------------------------------------------------- +// Functions to move through the animation +//--------------------------------------------------------------------------- + +bool wxGIFDecoder::GoFirstFrame() +{ + if (!IsAnimation()) + return FALSE; + + m_image = 1; + m_pimage = m_pfirst; + return TRUE; +} + +bool wxGIFDecoder::GoLastFrame() +{ + if (!IsAnimation()) + return FALSE; + + m_image = m_nimages; + m_pimage = m_plast; + return TRUE; +} + +bool wxGIFDecoder::GoNextFrame(bool cyclic) +{ + if (!IsAnimation()) + return FALSE; + + if ((m_image < m_nimages) || (cyclic)) + { + m_pimage = m_pimage->next; + m_image++; + + if (!m_pimage) + { + m_image = 1; + m_pimage = m_pfirst; + } + + return TRUE; + } + else + return FALSE; +} + +bool wxGIFDecoder::GoPrevFrame(bool cyclic) +{ + if (!IsAnimation()) + return FALSE; + + if ((m_image > 1) || (cyclic)) + { + m_pimage = m_pimage->prev; + m_image--; + + if (!m_pimage) + { + m_image = m_nimages; + m_pimage = m_plast; + } + + return TRUE; + } + else + return FALSE; +} + +bool wxGIFDecoder::GoFrame(int which) +{ + int i; + + if (!IsAnimation()) + return FALSE; + + if ((which >= 1) && (which <= m_nimages)) + { + m_pimage = m_pfirst; + + for (i = 1; i < which; i++) + m_pimage = m_pimage->next; + + return TRUE; + } + else + return FALSE; +} + + +//--------------------------------------------------------------------------- +// GIF reading and decoding +//--------------------------------------------------------------------------- + +// getcode: +// Reads the next code from the file stream, with size 'bits' +// +int wxGIFDecoder::getcode(int bits, int ab_fin) +{ + unsigned int mask; /* bit mask */ + unsigned int code; /* code (result) */ + + + /* get remaining bits from last byte read */ + mask = (1 << bits) - 1; + code = (m_lastbyte >> (8 - m_restbits)) & mask; + + /* keep reading new bytes while needed */ + while (bits > m_restbits) + { + /* if no bytes left in this block, read the next block */ + if (m_restbyte == 0) + { + m_restbyte = (unsigned char)m_f->GetC(); + + /* Some encoders are a bit broken: instead of issuing + * an end-of-image symbol (ab_fin) they come up with + * a zero-length subblock!! We catch this here so + * that the decoder sees an ab_fin code. + */ + if (m_restbyte == 0) + { + code = ab_fin; + break; + } + } + + /* read next byte and isolate the bits we need */ + m_lastbyte = (unsigned char)m_f->GetC(); + mask = (1 << (bits - m_restbits)) - 1; + code = code + ((m_lastbyte & mask) << m_restbits); + m_restbyte--; + + /* adjust total number of bits extracted from the buffer */ + m_restbits = m_restbits + 8; + } + + /* find number of bits remaining for next code */ + m_restbits = (m_restbits - bits); + + return code; +} + + +// dgif: +// GIF decoding function. The initial code size (aka root size) +// is 'bits'. Supports interlaced images (interl == 1). +// +int wxGIFDecoder::dgif(IMAGEN *img, int interl, int bits) +{ + int ab_prefix[4096]; /* alphabet (prefixes) */ + int ab_tail[4096]; /* alphabet (tails) */ + int stack[4096]; /* decompression stack */ + + int ab_clr; /* clear code */ + int ab_fin; /* end of info code */ + int ab_bits; /* actual symbol width, in bits */ + int ab_free; /* first free position in alphabet */ + int ab_max; /* last possible character in alphabet */ + int pass; /* pass number in interlaced images */ + int pos; /* index into decompresion stack */ + unsigned int x, y; /* position in image buffer */ + + int code, readcode, lastcode, abcabca; + + /* these won't change */ + ab_clr = (1 << bits); + ab_fin = (1 << bits) + 1; + + /* these will change through the decompression proccess */ + ab_bits = bits + 1; + ab_free = (1 << bits) + 2; + ab_max = (1 << ab_bits) - 1; + lastcode = -1; + abcabca = -1; + pass = 1; + pos = x = y = 0; + + /* reset static globals */ + m_restbits = 0; + m_restbyte = 0; + m_lastbyte = 0; + + do + { + /* get next code */ + readcode = code = getcode(ab_bits, ab_fin); + + /* end of image? */ + if (code == ab_fin) break; + + /* reset alphabet? */ + if (code == ab_clr) + { + /* reset main variables */ + ab_bits = bits + 1; + ab_free = (1 << bits) + 2; + ab_max = (1 << ab_bits) - 1; + lastcode = -1; + abcabca = -1; + + /* skip to next code */ + continue; + } + + /* unknown code: special case (like in ABCABCA) */ + if (code >= ab_free) + { + code = lastcode; /* take last string */ + stack[pos++] = abcabca; /* add first character */ + } + + /* build the string for this code in the stack */ + while (code > ab_clr) + { + stack[pos++] = ab_tail[code]; + code = ab_prefix[code]; + } + stack[pos] = code; /* push last code into the stack */ + abcabca = code; /* save for special case */ + + /* make new entry in alphabet (only if NOT just cleared) */ + if (lastcode != -1) + { + ab_prefix[ab_free] = lastcode; + ab_tail[ab_free] = code; + ab_free++; + + if ((ab_free > ab_max) && (ab_bits < 12)) + { + ab_bits++; + ab_max = (1 << ab_bits) - 1; + } + } + + /* dump stack data to the buffer */ + while (pos >= 0) + { + (img->p)[x + (y * (img->w))] = (char)stack[pos--]; + + if (++x >= (img->w)) + { + x = 0; + + if (interl) + { + /* support for interlaced images */ + switch (pass) + { + case 1: y += 8; break; + case 2: y += 8; break; + case 3: y += 4; break; + case 4: y += 2; break; + } + if (y >= (img->h)) + { + switch (++pass) + { + case 2: y = 4; break; + case 3: y = 2; break; + case 4: y = 1; break; + } + } + } + else + { + /* non-interlaced */ + y++; + } + } + } + + pos = 0; + lastcode = readcode; + } + while (code != ab_fin); + + return 0; +} + + +// ReadGIF: +// Reads and decodes one or more GIF images, depending on whether +// animated GIF support is enabled. Can read GIFs with any bit +// size (color depth), but the output images are always expanded +// to 8 bits per pixel. Also, the image palettes always contain +// 256 colors, although some of them may be unused. Returns E_OK +// (== 0) on success, or an error code if something fails. Error +// codes are E_ARCHIVO, E_FORMATO, E_MEMORIA (see header file). +// +int wxGIFDecoder::ReadGIF() +{ + int ncolors, bits, interl, transparent, disposal, i; + long size; + long delay; + unsigned char type; + unsigned char pal[768]; + unsigned char buf[16]; + IMAGEN **ppimg, *pimg, *pprev; + + + /* check GIF signature and animated GIF support (ver. >= 89a) */ + m_f->Read(buf, 6); + + if (memcmp(buf, "GIF", 3) != 0) + return E_FORMATO; + + if (memcmp(buf + 3, "89a", 3) < 0) + m_anim = FALSE; + + /* read logical screen descriptor block (LSDB) */ + m_f->Read(buf, 7); + m_screenw = buf[0] + 256 * buf[1]; + m_screenh = buf[2] + 256 * buf[3]; + + /* load global color map if available */ + if ((buf[4] & 0x80) == 0x80) + { + m_background = buf[5]; + + ncolors = 2 << (buf[4] & 0x07); + m_f->Read(pal, 3 * ncolors); + } + + /* transparent colour, disposal method and delay default to unused */ + transparent = -1; + disposal = -1; + delay = -1; + + /* read images */ + ppimg = &m_pfirst; + pprev = NULL; + pimg = NULL; + + while (1) + { + type = (unsigned char)m_f->GetC(); + + /* end of data? */ + if (type == 0x3B) + break; + + /* extension block? */ + if (type == 0x21) + { + if (((unsigned char)m_f->GetC()) == 0xF9) + /* graphics control extension, parse it */ + { + m_f->Read(buf, 6); + + /* read delay and convert from 1/100 of a second to ms */ + delay = 10 * (buf[2] + 256 * buf[3]); + + /* read transparent colour index, if used */ + if (buf[1] & 0x01) + transparent = buf[4]; + + /* read disposal method */ + disposal = (buf[1] & 0x1C) - 1; + } + else + /* other extension, skip */ + { + while ((i = (unsigned char)m_f->GetC()) != 0) + { + /* This line should not be neccessary! + * Some images are not loaded correctly + * without it. A bug in wxStream? + */ + // m_f->SeekI(m_f->TellI(), wxFromStart); + m_f->SeekI(i, wxFromCurrent); + } + } + } + + /* image descriptor block? */ + if (type == 0x2C) + { + /* allocate memory for IMAGEN struct */ + pimg = (*ppimg) = (IMAGEN *) malloc(sizeof(IMAGEN)); + + if (pimg == NULL) + { + Destroy(); + return E_MEMORIA; + } + + /* fill in the data */ + m_f->Read(buf, 9); + pimg->left = buf[4] + 256 * buf[5]; + pimg->top = buf[4] + 256 * buf[5]; + pimg->w = buf[4] + 256 * buf[5]; + pimg->h = buf[6] + 256 * buf[7]; + interl = ((buf[8] & 0x40)? 1 : 0); + size = pimg->w * pimg->h; + + pimg->transparent = transparent; + pimg->disposal = disposal; + pimg->delay = delay; + pimg->next = NULL; + pimg->prev = pprev; + pprev = pimg; + ppimg = &pimg->next; + + /* allocate memory for image and palette */ + pimg->p = (unsigned char *) malloc(size); + pimg->pal = (unsigned char *) malloc(768); + + if ((!pimg->p) || (!pimg->pal)) + { + Destroy(); + return E_MEMORIA; + } + + /* load local color map if available, else use global map */ + if ((buf[8] & 0x80) == 0x80) + { + ncolors = 2 << (buf[8] & 0x07); + m_f->Read(pimg->pal, 3 * ncolors); + } + else + memcpy(pimg->pal, pal, 768); + + /* get initial code size from first byte in raster data */ + bits = (unsigned char)m_f->GetC(); + + /* decode image */ + dgif(pimg, interl, bits); + + m_nimages++; + } + + /* if we have one image and no animated GIF support, exit */ + if (m_nimages == 1 && !m_anim) + break; + } + + /* finish successfully :-) */ + if (m_nimages != 0) + { + m_image = 1; + m_plast = pimg; + m_pimage = m_pfirst; + } + + return E_OK; +} + +#endif // wxUSE_STREAM diff --git a/src/common/imaggif.cpp b/src/common/imaggif.cpp index 37ef878478..785f91da54 100644 --- a/src/common/imaggif.cpp +++ b/src/common/imaggif.cpp @@ -1,28 +1,31 @@ ///////////////////////////////////////////////////////////////////////////// // Name: imaggif.cpp // Purpose: wxGIFHandler -// Author: Guillermo Rodriguez Garcia -// wxWindows adaptation by Vaclav Slavik +// Author: Vaclav Slavik +// Based on wxGIFDecoder by Guillermo Rodriguez Garcia +// RCS-ID: $Id$ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// /* - We don't put pragma implement in this file because it is already present in - src/common/image.cpp +We don't put pragma implement in this file because it is already present in +src/common/image.cpp */ // For compilers that support precompilation, includes "wx.h". #include #ifdef __BORLANDC__ - #pragma hdrstop +# pragma hdrstop #endif #ifndef WX_PRECOMP - #include "wx/defs.h" +# include "wx/defs.h" #endif #include "wx/image.h" +// #include "wx/imaggif.h" +#include "wx/gifdecod.h" #include "wx/wfstream.h" #include "wx/module.h" #include "wx/log.h" @@ -31,390 +34,29 @@ IMPLEMENT_DYNAMIC_CLASS(wxGIFHandler,wxImageHandler) #if wxUSE_STREAMS -/* - -FOLLOWING CODE IS BY G.R.G. : -(except wxInputStream stuff) - -*/ - -/************************************************************************ - READGIF.H - Reads a GIF file - ------------------------------------------------------------------------ - Guillermo Rodriguez Garcia - - - Version: 2.1 -*************************************************************************/ - - -typedef struct -{ - int w; /* width */ - int h; /* height */ - int transparent; /* transparent color (-1 = none) */ - unsigned char *p; /* bitmap */ - unsigned char *pal; /* palette */ -} IMAGEN; - - - -/************************************************************************ - READGIF.C - Reads a GIF file - ------------------------------------------------------------------------ - Guillermo Rodriguez Garcia - - - Version: 2.1 -*************************************************************************/ - - -#include -#include - - -/* error codes */ -#define E_OK 0 /* everything was OK */ -#define E_ARCHIVO -1 /* error opening file */ -#define E_FORMATO -2 /* error in gif header */ -#define E_MEMORIA -3 /* error allocating memory */ - - -/* This class binding is by VS, so all bugs in it are mine ;-) */ - -class gifDecoder -{ - private: - /* globals */ - int restbits; /* remaining valid bits */ - unsigned int restbyte; /* remaining bytes in this block */ - unsigned int lastbyte; /* last byte read */ - - wxInputStream *f; /* input file */ - - public: - gifDecoder(wxInputStream *s) { f = s; } - int getcode(int bits); - int dgif(IMAGEN *img, int interl, int bits); - int readgif(IMAGEN *img); -}; - - - -/* getcode: - * Reads the next code from the file, with size 'bits' - */ -int gifDecoder::getcode(int bits) -{ - unsigned int mask; /* bit mask */ - unsigned int code; /* code (result) */ - - - /* get remaining bits from last byte read */ - mask = (1 << bits) - 1; - code = (lastbyte >> (8 - restbits)) & mask; - - /* keep reading new bytes while needed */ - while (bits > restbits) - { - /* if no bytes left in this block, read the next block */ - if (restbyte == 0) - restbyte = (unsigned char)f->GetC(); - - /* read next byte and isolate the bits we need */ - lastbyte = (unsigned char)f->GetC(); - mask = (1 << (bits - restbits)) - 1; - code = code + ((lastbyte & mask) << restbits); - restbyte--; - - /* adjust total number of bits extracted from the buffer */ - restbits = restbits + 8; - } - - /* find number of bits reamining for next code */ - restbits = (restbits - bits); - - return code; -} - - - -/* dgif: - * GIF decoding function. The initial code size (aka root size) - * is 'bits'. Supports interlaced images (interl == 1). - */ -int gifDecoder::dgif(IMAGEN *img, int interl, int bits) -{ - int ab_prefix[4096]; /* alphabet (prefixes) */ - int ab_tail[4096]; /* alphabet (tails) */ - int stack[4096]; /* decompression stack */ - - int ab_clr; /* clear code */ - int ab_fin; /* end of info code */ - int ab_bits; /* actual symbol width, in bits */ - int ab_free; /* first free position in alphabet */ - int ab_max; /* last possible character in alphabet */ - int pass; /* pass number in interlaced images */ - int pos; /* index into decompresion stack */ - int x, y; /* position in image buffer */ - - int code, readcode, lastcode, abcabca; - - /* these won't change */ - ab_clr = (1 << bits); - ab_fin = (1 << bits) + 1; - - /* these will change through the decompression proccess */ - ab_bits = bits + 1; - ab_free = (1 << bits) + 2; - ab_max = (1 << ab_bits) - 1; - lastcode = -1; - abcabca = -1; - pass = 1; - pos = x = y = 0; - - /* reset static globals */ - restbits = 0; - restbyte = 0; - lastbyte = 0; - - do - { - /* get next code */ - readcode = code = getcode(ab_bits); - - /* end of image? */ - if (code == ab_fin) break; - - /* reset alphabet? */ - if (code == ab_clr) - { - /* reset main variables */ - ab_bits = bits + 1; - ab_free = (1 << bits) + 2; - ab_max = (1 << ab_bits) - 1; - lastcode = -1; - abcabca = -1; - - /* skip to next code */ - continue; - } - - /* unknown code: special case (like in ABCABCA) */ - if (code >= ab_free) - { - code = lastcode; /* take last string */ - stack[pos++] = abcabca; /* add first character */ - } - - /* build the string for this code in the stack */ - while (code > ab_clr) - { - stack[pos++] = ab_tail[code]; - code = ab_prefix[code]; - } - stack[pos] = code; /* push last code into the stack */ - abcabca = code; /* save for special case */ - - /* make new entry in alphabet (only if NOT just cleared) */ - if (lastcode != -1) - { - ab_prefix[ab_free] = lastcode; - ab_tail[ab_free] = code; - ab_free++; - - if ((ab_free > ab_max) && (ab_bits < 12)) - { - ab_bits++; - ab_max = (1 << ab_bits) - 1; - } - } - - /* dump stack data to the buffer */ - while (pos >= 0) - { - (img->p)[x + (y * (img->w))] = (char)stack[pos--]; - - if (++x >= (img->w)) - { - x = 0; - - if (interl) - { - /* support for interlaced images */ - switch (pass) - { - case 1: y += 8; break; - case 2: y += 8; break; - case 3: y += 4; break; - case 4: y += 2; break; - } - if (y >= (img->h)) - { - switch (++pass) - { - case 2: y = 4; break; - case 3: y = 2; break; - case 4: y = 1; break; - } - } - } - else - { - /* non-interlaced */ - y++; - } - } - } - - pos = 0; - lastcode = readcode; - } - while (code != ab_fin); - - return 0; -} - - - -/* readgif: - * Reads a GIF image from the file with filename 'nombre' in the - * IMAGEN structure pointed by 'img'. Can read GIFs with any bit - * size (color depth), but the output image is always expanded - * to 8 bits per pixel. Also, the image palette always contains - * 256 colors, although some of them may be unused. Returns E_OK - * (== 0) on success, or an error code if something fails. Error - * codes are E_ARCHIVO, E_FORMATO, E_MEMORIA (see above). - */ -int gifDecoder::readgif(IMAGEN *img) -{ - int size, ncolors, bits, interl, i; - unsigned char pal[768]; - unsigned char buf[16]; - - - /* read header and logical screen descriptor block (LSDB) */ - f->Read(buf, 13); - - /* check GIF signature */ - if (memcmp(buf, "GIF", 3) != 0) return E_FORMATO; - - /* load global color map if available */ - if ((buf[10] & 0x80) == 0x80) - { - ncolors = 2 << (buf[10] & 0x07); - f->Read(pal, 3 * ncolors); - } - - /* assume no transparent color */ - img->transparent = -1; - - /* skip most extensions */ - while (((unsigned char)f->GetC()) == 0x21) /* separator */ - { - if (((unsigned char)f->GetC()) == 0xF9) /* graphic control ext. */ - { - f->Read(buf, 6); - if (buf[1] & 0x01) - img->transparent = buf[4]; - } - else - while ((i = (unsigned char)f->GetC()) != 0) /* byte count */ - f->SeekI(i, wxFromCurrent); - } - - /* read image descriptor block (IDB) */ - f->Read(buf, 9); - img->w = buf[4] + 256 * buf[5]; - img->h = buf[6] + 256 * buf[7]; - size = img->w * img->h; - interl = ((buf[8] & 0x40)? 1 : 0); - - /* load local color map if available */ - if ((buf[8] & 0x80) == 0x80) - { - ncolors = 2 << (buf[8] & 0x07); - f->Read(pal, 3 * ncolors); - } - - /* get initial code size from first byte in raster data */ - bits = (unsigned char)f->GetC(); - - /* allocate memory for image and palette */ - if ((img->p = (unsigned char*) malloc(size)) == NULL) return E_MEMORIA; - if ((img->pal = (unsigned char*) malloc(768)) == NULL) return E_MEMORIA; - - /* shift palette to fit VGA 6-bit format */ - for (i = 0; i < 768; i++) - (img->pal)[i] = (unsigned char)pal[i]; /* >> 2 not in wxWin */ - - /* decode GIF */ - dgif(img, interl, bits); - - /* finish successfully :-) */ - return E_OK; -} - - - -/* - -FOLLOWING CODE IS BY V.S. : - -*/ - //----------------------------------------------------------------------------- // wxGIFHandler //----------------------------------------------------------------------------- bool wxGIFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool WXUNUSED(verbose) ) { - unsigned char *ptr, *src, *pal; - IMAGEN igif; - int i; - gifDecoder *decod; - - image->Destroy(); + wxGIFDecoder *decod; + bool ok; - decod = new gifDecoder(&stream); - - if (decod->readgif(&igif) != E_OK) { + decod = new wxGIFDecoder(&stream, TRUE); + + if (decod->ReadGIF() != E_OK) + { wxLogDebug(_T("Error reading GIF")); delete decod; return FALSE; } - delete decod; - - image->Create(igif.w, igif.h); - if (!image->Ok()) { - free(igif.pal); - free(igif.p); - return FALSE; - } - ptr = image->GetData(); - src = igif.p; - pal = igif.pal; - - if (igif.transparent != -1) { - for (i = 0; i < 256; i++) - if ((pal[3 * i + 0] == 255) && (pal[3 * i + 1] == 0) && (pal[3 * i + 2] == 255)) pal[3 * i + 2] = 254; - pal[3 * (igif.transparent) + 0] = 255, - pal[3 * (igif.transparent) + 1] = 0, - pal[3 * (igif.transparent) + 2] = 255; - image->SetMaskColour(255, 0, 255); - } - else image->SetMask(FALSE); - - for (i = 0; i < igif.w * igif.h; i++, src++) { - *(ptr++) = pal[3 * (*src) + 0]; - *(ptr++) = pal[3 * (*src) + 1]; - *(ptr++) = pal[3 * (*src) + 2]; - } + image->Destroy(); + ok = decod->ConvertToImage(image); - free(igif.pal); - free(igif.p); - return TRUE; + delete decod; + return ok; } bool wxGIFHandler::SaveFile( wxImage * WXUNUSED(image), -- 2.45.2