bitmapGif.cpp

Engine/source/gfx/bitmap/loaders/bitmapGif.cpp

More...

Classes:

Public Variables

struct _privateRegisterGIF

Public Functions

gifReadDataFn(GifFileType * gifinfo, GifByteType * data, S32 length)
bool
sReadGIF(Stream & stream, GBitmap * bitmap)
bool
sWriteGIF(GBitmap * bitmap, Stream & stream, U32 compressionLevel)

Detailed Description

Public Variables

struct _privateRegisterGIF sStaticRegisterGIF 

Public Functions

gifReadDataFn(GifFileType * gifinfo, GifByteType * data, S32 length)

sReadGIF(Stream & stream, GBitmap * bitmap)

sWriteGIF(GBitmap * bitmap, Stream & stream, U32 compressionLevel)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25
 26#include "core/stream/fileStream.h"
 27#include "core/util/path.h"
 28
 29#include "gfx/bitmap/gBitmap.h"
 30
 31// This must come after our headers due to a conflicting definition of VoidPtr
 32#include "lungif/gif_lib.h"
 33
 34
 35using namespace Torque;
 36
 37static bool sReadGIF(Stream &stream, GBitmap *bitmap);
 38static bool sWriteGIF(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
 39
 40static struct _privateRegisterGIF
 41{
 42   _privateRegisterGIF()
 43   {
 44      GBitmap::Registration reg;
 45
 46      reg.extensions.push_back( "gif" );
 47
 48      reg.readFunc = sReadGIF;
 49      reg.writeFunc = sWriteGIF;
 50
 51      GBitmap::sRegisterFormat( reg );
 52   }
 53} sStaticRegisterGIF;
 54
 55//-------------------------------------- Replacement I/O for standard LIBjpeg
 56//                                        functions.  we don't wanna use
 57//                                        FILE*'s...
 58static S32 gifReadDataFn(GifFileType *gifinfo, GifByteType *data, S32 length)
 59{
 60   Stream *stream = (Stream*)gifinfo->UserData;
 61   AssertFatal(stream != NULL, "gifReadDataFn::No stream.");
 62   int pos = stream->getPosition();
 63   if (stream->read(length, data))
 64      return length;
 65
 66   if (stream->getStatus() == Stream::EOS)
 67      return (stream->getPosition()-pos);
 68   else
 69      return 0;
 70}
 71
 72
 73//--------------------------------------
 74#if 0 
 75// CodeReview - until we can write these, get rid of warning by disabling method.
 76static S32 length)
 77{
 78   Stream*)gifinfo->UserData;
 79   NULL, "gifWriteDataFn::No stream.");
 80   if (stream->write(length, data))
 81      return length;
 82   else
 83      return 0;
 84}
 85#endif
 86
 87//--------------------------------------
 88static bool sReadGIF( Stream &stream, GBitmap *bitmap )
 89{
 90   GifFileType *gifinfo = DGifOpen( (void*)&stream, gifReadDataFn);
 91   if (!gifinfo)
 92      return false;
 93
 94   GifRecordType recordType;
 95   do
 96   {
 97      if (DGifGetRecordType(gifinfo, &recordType) == GIF_ERROR)
 98         break;
 99
100      if (recordType == IMAGE_DESC_RECORD_TYPE)
101      {
102         if (DGifGetImageDesc(gifinfo) == GIF_ERROR)
103            break;
104
105         GFXFormat format = (gifinfo->SBackGroundColor == 0 ) ? GFXFormatR8G8B8 : GFXFormatR8G8B8A8;
106         bitmap->allocateBitmap(gifinfo->SWidth, gifinfo->SHeight, false, format);
107
108         // Assume no transparency until proven otherwise
109         bitmap->setHasTransparency(false);
110
111         U32 gwidth = gifinfo->Image.Width ? gifinfo->Image.Width : bitmap->getWidth();
112         U32 gheight= gifinfo->Image.Height ? gifinfo->Image.Height : bitmap->getHeight();
113         U32 gifSize = gwidth * gheight;
114         U8  *data   = new U8[gifSize];
115
116         if (DGifGetLine(gifinfo, data, gifSize) != GIF_ERROR)
117         {
118            // use the global or local color table ?
119            GifColorType *color = NULL;
120            if (gifinfo->Image.ColorMap)
121               color = gifinfo->Image.ColorMap->Colors;
122            else if (gifinfo->SColorMap)
123               color = gifinfo->SColorMap->Colors;
124
125            if (color)
126            {
127               U8 *dst = bitmap->getAddress(gifinfo->Image.Left, gifinfo->Image.Top);
128               U8 *src = data;
129               U32 right  = gifinfo->Image.Left + gwidth;
130               U32 bottom = gifinfo->Image.Top + gheight;
131               U32 next   = (bitmap->getWidth() - gwidth) * bitmap->getBytesPerPixel();
132
133               if (format == GFXFormatR8G8B8A8)
134               {
135                  for (U32 y=gifinfo->Image.Top; y<bottom; y++)
136                  {
137                     for (U32 x=gifinfo->Image.Left; x<right; x++, src++)
138                     {
139                        if (*src == gifinfo->SBackGroundColor)
140                        {
141                           // this is a transparent pixel
142                           dst[0] = 0;    // red
143                           dst[1] = 0;    // green
144                           dst[2] = 0;    // blue
145                           dst[3] = 0;    // alpha
146
147                           bitmap->setHasTransparency(true);
148                        }
149                        else
150                        {
151                           dst[0] = color[*src].Red;
152                           dst[1] = color[*src].Green;
153                           dst[2] = color[*src].Blue;
154                           dst[3] = 0;    // alpha
155                        }
156                        dst += bitmap->getBytesPerPixel();
157                     }
158                     dst += next;
159                  }
160               }
161               else
162               {
163                  for (U32 y=gifinfo->Image.Top; y<bottom; y++)
164                  {
165                     for (U32 x=gifinfo->Image.Left; x<right; x++, src++)
166                     {
167                        dst[0] = color[*src].Red;
168                        dst[1] = color[*src].Green;
169                        dst[2] = color[*src].Blue;
170                        dst += bitmap->getBytesPerPixel();
171                     }
172                     dst += next;
173                  }
174               }
175               delete [] data;
176               DGifCloseFile(gifinfo);
177               return true;
178            }
179         }
180         // failure
181         delete [] data;
182         break;
183      }
184      else if (recordType == EXTENSION_RECORD_TYPE)
185      {
186         GifByteType *extension;
187         S32 extCode;
188
189         // Skip any extension blocks in file
190         if (DGifGetExtension(gifinfo, &extCode, &extension) != GIF_ERROR)
191         {
192            while (extension != NULL)
193            {
194               if (DGifGetExtensionNext(gifinfo, &extension) == GIF_ERROR)
195               {
196                  return false;
197               }
198            }
199         }
200         else
201         {
202            return false;
203         }
204      }
205
206      // There used to be a break right here. This caused the while condition to
207      // never get processed, and so it never looped through all the records in
208      // the GIF. I took a quick peek back at TGB and TGE histories and I am not
209      // sure where this change got made, but I can't figure out why the loading
210      // worked at all, ever, with that break in there. The only case I can think
211      // of is if the first record in the GIF was the bitmap data.
212      // [6/6/2007 Pat]
213
214   }while (recordType != TERMINATE_RECORD_TYPE);
215
216
217   DGifCloseFile(gifinfo);
218   return true;
219}
220
221
222//--------------------------------------------------------------------------
223static bool sWriteGIF(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
224{
225   TORQUE_UNUSED( bitmap );
226   TORQUE_UNUSED( stream );
227   TORQUE_UNUSED( compressionLevel );
228
229   return false;
230}
231
232
233