Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
5.7 KiB

  1. //
  2. // mxToolKit (c) 1999 by Mete Ciragan
  3. //
  4. // file: mxBmp.cpp
  5. // implementation: all
  6. // last modified: Apr 15 1999, Mete Ciragan
  7. // copyright: The programs and associated files contained in this
  8. // distribution were developed by Mete Ciragan. The programs
  9. // are not in the public domain, but they are freely
  10. // distributable without licensing fees. These programs are
  11. // provided without guarantee or warrantee expressed or
  12. // implied.
  13. // lbmlib.c
  14. #include "mxtk/mxBmp.h"
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. mxImage *
  19. mxBmpRead (const char *filename)
  20. {
  21. int i;
  22. FILE *pfile = 0;
  23. mxBitmapFileHeader bmfh;
  24. mxBitmapInfoHeader bmih;
  25. mxBitmapRGBQuad rgrgbPalette[256];
  26. int cbBmpBits;
  27. byte *pbBmpBits;
  28. byte *pb, *pbPal = 0;
  29. int cbPalBytes;
  30. int biTrueWidth;
  31. mxImage *image = 0;
  32. // File exists?
  33. if ((pfile = fopen (filename, "rb")) == 0)
  34. return 0;
  35. // Read file header
  36. if (fread (&bmfh, sizeof bmfh, 1/*count*/, pfile) != 1)
  37. goto GetOut;
  38. // Bogus file header check
  39. if (!(bmfh.bfReserved1 == 0 && bmfh.bfReserved2 == 0))
  40. goto GetOut;
  41. // Read info header
  42. if (fread (&bmih, sizeof bmih, 1/*count*/, pfile) != 1)
  43. goto GetOut;
  44. // Bogus info header check
  45. if (!(bmih.biSize == sizeof bmih && bmih.biPlanes == 1))
  46. goto GetOut;
  47. // Bogus bit depth? Only 8-bit supported.
  48. if (bmih.biBitCount != 8)
  49. goto GetOut;
  50. // Bogus compression? Only non-compressed supported.
  51. if (bmih.biCompression != 0) //BI_RGB)
  52. goto GetOut;
  53. // Figure out how many entires are actually in the table
  54. if (bmih.biClrUsed == 0)
  55. {
  56. bmih.biClrUsed = 256;
  57. cbPalBytes = (1 << bmih.biBitCount) * sizeof (mxBitmapRGBQuad);
  58. }
  59. else
  60. {
  61. cbPalBytes = bmih.biClrUsed * sizeof (mxBitmapRGBQuad);
  62. }
  63. // Read palette (bmih.biClrUsed entries)
  64. if (fread (rgrgbPalette, cbPalBytes, 1/*count*/, pfile) != 1)
  65. goto GetOut;
  66. image = new mxImage ();
  67. if (!image)
  68. goto GetOut;
  69. if (!image->create (bmih.biWidth, bmih.biHeight, 8))
  70. {
  71. delete image;
  72. goto GetOut;
  73. }
  74. pb = (byte *) image->palette;
  75. // Copy over used entries
  76. for (i = 0; i < (int) bmih.biClrUsed; i++)
  77. {
  78. *pb++ = rgrgbPalette[i].rgbRed;
  79. *pb++ = rgrgbPalette[i].rgbGreen;
  80. *pb++ = rgrgbPalette[i].rgbBlue;
  81. }
  82. // Fill in unused entires will 0,0,0
  83. for (i = bmih.biClrUsed; i < 256; i++)
  84. {
  85. *pb++ = 0;
  86. *pb++ = 0;
  87. *pb++ = 0;
  88. }
  89. // Read bitmap bits (remainder of file)
  90. cbBmpBits = bmfh.bfSize - ftell (pfile);
  91. pb = (byte *) malloc (cbBmpBits * sizeof (byte));
  92. if (pb == 0)
  93. {
  94. free (pbPal);
  95. goto GetOut;
  96. }
  97. if (fread (pb, cbBmpBits, 1/*count*/, pfile) != 1)
  98. {
  99. free (pb);
  100. free (pbPal);
  101. goto GetOut;
  102. }
  103. /*
  104. pbBmpBits = malloc(cbBmpBits);
  105. if (pbBmpBits == 0)
  106. {
  107. free (pb);
  108. free (pbPal);
  109. goto GetOut;
  110. }
  111. */
  112. pbBmpBits = (byte *) image->data;
  113. // data is actually stored with the width being rounded up to a multiple of 4
  114. biTrueWidth = (bmih.biWidth + 3) & ~3;
  115. // reverse the order of the data.
  116. pb += (bmih.biHeight - 1) * biTrueWidth;
  117. for(i = 0; i < bmih.biHeight; i++)
  118. {
  119. memmove (&pbBmpBits[biTrueWidth * i], pb, biTrueWidth);
  120. pb -= biTrueWidth;
  121. }
  122. pb += biTrueWidth;
  123. free (pb);
  124. GetOut:
  125. if (pfile)
  126. fclose (pfile);
  127. return image;
  128. }
  129. bool
  130. mxBmpWrite (const char *filename, mxImage *image)
  131. {
  132. int i;
  133. FILE *pfile = 0;
  134. mxBitmapFileHeader bmfh;
  135. mxBitmapInfoHeader bmih;
  136. mxBitmapRGBQuad rgrgbPalette[256];
  137. int cbBmpBits;
  138. byte *pbBmpBits;
  139. byte *pb = 0;
  140. int cbPalBytes;
  141. int biTrueWidth;
  142. if (!image || !image->data || !image->palette)
  143. return false;
  144. // File exists?
  145. if ((pfile = fopen(filename, "wb")) == 0)
  146. return false;
  147. biTrueWidth = ((image->width + 3) & ~3);
  148. cbBmpBits = biTrueWidth * image->height;
  149. cbPalBytes = 256 * sizeof (mxBitmapRGBQuad);
  150. // Bogus file header check
  151. //bmfh.bfType = MAKEWORD( 'B', 'M' );
  152. bmfh.bfType = (word) (('M' << 8) | 'B');
  153. bmfh.bfSize = sizeof bmfh + sizeof bmih + cbBmpBits + cbPalBytes;
  154. bmfh.bfReserved1 = 0;
  155. bmfh.bfReserved2 = 0;
  156. bmfh.bfOffBits = sizeof bmfh + sizeof bmih + cbPalBytes;
  157. // Write file header
  158. if (fwrite (&bmfh, sizeof bmfh, 1/*count*/, pfile) != 1)
  159. {
  160. fclose (pfile);
  161. return false;
  162. }
  163. // Size of structure
  164. bmih.biSize = sizeof bmih;
  165. // Width
  166. bmih.biWidth = biTrueWidth;
  167. // Height
  168. bmih.biHeight = image->height;
  169. // Only 1 plane
  170. bmih.biPlanes = 1;
  171. // Only 8-bit supported.
  172. bmih.biBitCount = 8;
  173. // Only non-compressed supported.
  174. bmih.biCompression = 0; //BI_RGB;
  175. bmih.biSizeImage = 0;
  176. // huh?
  177. bmih.biXPelsPerMeter = 0;
  178. bmih.biYPelsPerMeter = 0;
  179. // Always full palette
  180. bmih.biClrUsed = 256;
  181. bmih.biClrImportant = 0;
  182. // Write info header
  183. if (fwrite (&bmih, sizeof bmih, 1/*count*/, pfile) != 1)
  184. {
  185. fclose (pfile);
  186. return false;
  187. }
  188. // convert to expanded palette
  189. pb = (byte *) image->palette;
  190. // Copy over used entries
  191. for (i = 0; i < (int) bmih.biClrUsed; i++)
  192. {
  193. rgrgbPalette[i].rgbRed = *pb++;
  194. rgrgbPalette[i].rgbGreen = *pb++;
  195. rgrgbPalette[i].rgbBlue = *pb++;
  196. rgrgbPalette[i].rgbReserved = 0;
  197. }
  198. // Write palette (bmih.biClrUsed entries)
  199. cbPalBytes = bmih.biClrUsed * sizeof (mxBitmapRGBQuad);
  200. if (fwrite (rgrgbPalette, cbPalBytes, 1/*count*/, pfile) != 1)
  201. {
  202. fclose (pfile);
  203. return false;
  204. }
  205. pbBmpBits = (byte *) malloc (cbBmpBits * sizeof (byte));
  206. if (!pbBmpBits)
  207. {
  208. fclose (pfile);
  209. return false;
  210. }
  211. pb = (byte *) image->data;
  212. // reverse the order of the data.
  213. pb += (image->height - 1) * image->width;
  214. for(i = 0; i < bmih.biHeight; i++)
  215. {
  216. memmove (&pbBmpBits[biTrueWidth * i], pb, image->width);
  217. pb -= image->width;
  218. }
  219. // Write bitmap bits (remainder of file)
  220. if (fwrite (pbBmpBits, cbBmpBits, 1/*count*/, pfile) != 1)
  221. {
  222. free (pbBmpBits);
  223. fclose (pfile);
  224. return false;
  225. }
  226. free (pbBmpBits);
  227. fclose (pfile);
  228. return true;
  229. }