bitmapBmp.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 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 "graphics/gBitmap.h"
  23. #include "graphics/gPalette.h"
  24. #include "io/stream.h"
  25. #include "platform/platform.h"
  26. //-Mat used when checking for palleted textures
  27. #include "console/console.h"
  28. //Luma: Moved this here from bm8
  29. bool sgForcePalletedBMPsTo16Bit = false;
  30. // structures mirror those defined by the win32 API
  31. struct RGBQUAD {
  32. U8 rgbBlue;
  33. U8 rgbGreen;
  34. U8 rgbRed;
  35. U8 rgbReserved;
  36. };
  37. struct BITMAPFILEHEADER {
  38. U16 bfType;
  39. U32 bfSize;
  40. U16 bfReserved1;
  41. U16 bfReserved2;
  42. U32 bfOffBits;
  43. };
  44. struct BITMAPINFOHEADER{
  45. U32 biSize;
  46. S32 biWidth;
  47. S32 biHeight;
  48. U16 biPlanes;
  49. U16 biBitCount;
  50. U32 biCompression;
  51. U32 biSizeImage;
  52. S32 biXPelsPerMeter;
  53. S32 biYPelsPerMeter;
  54. U32 biClrUsed;
  55. U32 biClrImportant;
  56. };
  57. // constants for the biCompression field
  58. #define BI_RGB 0L
  59. #define BI_RLE8 1L
  60. #define BI_RLE4 2L
  61. #define BI_BITFIELDS 3L
  62. //------------------------------------------------------------------------------
  63. //-------------------------------------- Supplimentary I/O (Partially located in
  64. // bitmapPng.cc)
  65. //
  66. bool GBitmap::readMSBmp(Stream& stream)
  67. {
  68. BITMAPINFOHEADER bi;
  69. BITMAPFILEHEADER bf;
  70. RGBQUAD rgb[256];
  71. stream.read(&bf.bfType);
  72. stream.read(&bf.bfSize);
  73. stream.read(&bf.bfReserved1);
  74. stream.read(&bf.bfReserved2);
  75. stream.read(&bf.bfOffBits);
  76. stream.read(&bi.biSize);
  77. stream.read(&bi.biWidth);
  78. stream.read(&bi.biHeight);
  79. stream.read(&bi.biPlanes);
  80. stream.read(&bi.biBitCount);
  81. stream.read(&bi.biCompression);
  82. stream.read(&bi.biSizeImage);
  83. stream.read(&bi.biXPelsPerMeter);
  84. stream.read(&bi.biYPelsPerMeter);
  85. stream.read(&bi.biClrUsed);
  86. stream.read(&bi.biClrImportant);
  87. BitmapFormat fmt = RGB;
  88. if(bi.biBitCount == 8)
  89. {
  90. fmt = Palettized;
  91. if(!bi.biClrUsed)
  92. bi.biClrUsed = 256;
  93. stream.read(sizeof(RGBQUAD) * bi.biClrUsed, rgb);
  94. pPalette = new GPalette;
  95. for (U32 i = 0; i < 256; i++)
  96. {
  97. (pPalette->getColors())[i].red = rgb[i].rgbRed;
  98. (pPalette->getColors())[i].green = rgb[i].rgbGreen;
  99. (pPalette->getColors())[i].blue = rgb[i].rgbBlue;
  100. (pPalette->getColors())[i].alpha = 255;
  101. }
  102. }
  103. U8 *rowBuffer = new U8[bi.biWidth * 4];
  104. allocateBitmap(bi.biWidth, bi.biHeight, false, fmt);
  105. S32 width = getWidth();
  106. S32 height = getHeight();
  107. for(int i = 0; i < bi.biHeight; i++)
  108. {
  109. U8 *rowDest = getAddress(0, height - i - 1);
  110. stream.read(bytesPerPixel * width, rowDest);
  111. }
  112. if(bytesPerPixel == 3) // do BGR swap
  113. {
  114. U8 *ptr = getAddress(0,0);
  115. for(int i = 0; i < width * height; i++)
  116. {
  117. U8 tmp = ptr[0];
  118. ptr[0] = ptr[2];
  119. ptr[2] = tmp;
  120. ptr += 3;
  121. }
  122. }
  123. delete[] rowBuffer;
  124. //-Mat set the mForce16Bit to true for these, if the script variable is set
  125. sgForcePalletedBMPsTo16Bit = Con::getVariable("$pref::iPhone::ForcePalletedBMPsTo16Bit");
  126. if( bi.biBitCount == 8 && sgForcePalletedBMPsTo16Bit ) {
  127. mForce16Bit = true;
  128. }
  129. return true;
  130. }
  131. bool GBitmap::writeMSBmp(Stream& io_rStream) const
  132. {
  133. RGBQUAD rgb[256];
  134. BITMAPINFOHEADER bi;
  135. BITMAPFILEHEADER bf;
  136. bi.biSize = sizeof(BITMAPINFOHEADER);
  137. bi.biWidth = getWidth();
  138. bi.biHeight = getHeight(); //our data is top-down
  139. bi.biPlanes = 1;
  140. if(getFormat() == Palettized)
  141. {
  142. bi.biBitCount = 8;
  143. bi.biCompression = BI_RGB;
  144. bi.biClrUsed = 256;
  145. AssertFatal(pPalette != NULL, "Error, must have a palette");
  146. }
  147. else if(getFormat() == RGB)
  148. {
  149. bi.biBitCount = 24;
  150. bi.biCompression = BI_RGB;
  151. bi.biClrUsed = 0;
  152. }
  153. U32 bytesPP = bi.biBitCount >> 3;
  154. bi.biSizeImage = getWidth() * getHeight() * bytesPP;
  155. bi.biXPelsPerMeter = 0;
  156. bi.biYPelsPerMeter = 0;
  157. bi.biClrUsed = 0;
  158. bi.biClrImportant = 0;
  159. bf.bfType = makeFourCCTag('B','M',0,0); //Type of file 'BM'
  160. bf.bfOffBits= sizeof(BITMAPINFOHEADER)
  161. + sizeof(BITMAPFILEHEADER)
  162. + (sizeof(RGBQUAD)*bi.biClrUsed);
  163. bf.bfSize = bf.bfOffBits + bi.biSizeImage;
  164. bf.bfReserved1 = 0;
  165. bf.bfReserved2 = 0;
  166. io_rStream.write(bf.bfType);
  167. io_rStream.write(bf.bfSize);
  168. io_rStream.write(bf.bfReserved1);
  169. io_rStream.write(bf.bfReserved2);
  170. io_rStream.write(bf.bfOffBits);
  171. io_rStream.write(bi.biSize);
  172. io_rStream.write(bi.biWidth);
  173. io_rStream.write(bi.biHeight);
  174. io_rStream.write(bi.biPlanes);
  175. io_rStream.write(bi.biBitCount);
  176. io_rStream.write(bi.biCompression);
  177. io_rStream.write(bi.biSizeImage);
  178. io_rStream.write(bi.biXPelsPerMeter);
  179. io_rStream.write(bi.biYPelsPerMeter);
  180. io_rStream.write(bi.biClrUsed);
  181. io_rStream.write(bi.biClrImportant);
  182. if(getFormat() == Palettized)
  183. {
  184. for (S32 ndx=0; ndx<256; ndx++)
  185. {
  186. rgb[ndx].rgbRed = pPalette->getColor(ndx).red;
  187. rgb[ndx].rgbGreen = pPalette->getColor(ndx).green;
  188. rgb[ndx].rgbBlue = pPalette->getColor(ndx).blue;
  189. rgb[ndx].rgbReserved = 0;
  190. }
  191. io_rStream.write(sizeof(RGBQUAD)*256, (U8*)&rgb);
  192. }
  193. //write the bitmap bits
  194. U8* pMSUpsideDownBits = new U8[bi.biSizeImage];
  195. for (U32 i = 0; i < getHeight(); i++) {
  196. const U8* pSrc = getAddress(0, i);
  197. U8* pDst = pMSUpsideDownBits + (getHeight() - i - 1) * getWidth() * bytesPP;
  198. dMemcpy(pDst, pSrc, getWidth() * bytesPP);
  199. }
  200. io_rStream.write(bi.biSizeImage, pMSUpsideDownBits);
  201. delete [] pMSUpsideDownBits;
  202. return io_rStream.getStatus() == Stream::Ok;
  203. }