bitmapGif.cpp 7.7 KB

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