bitmapGif.cpp
Engine/source/gfx/bitmap/loaders/bitmapGif.cpp
Classes:
class
Public Variables
struct _privateRegisterGIF
Public Functions
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
