gd_bmp.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. /*
  2. gd_bmp.c
  3. Bitmap format support for libgd
  4. * Written 2007, Scott MacVicar
  5. ---------------------------------------------------------------------------
  6. Todo:
  7. Bitfield encoding
  8. ----------------------------------------------------------------------------
  9. */
  10. /* $Id$ */
  11. #ifdef HAVE_CONFIG_H
  12. #include "config.h"
  13. #endif
  14. #include <stdio.h>
  15. #include <math.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include "gd.h"
  19. #include "gdhelpers.h"
  20. #include "bmp.h"
  21. static int compress_row(unsigned char *uncompressed_row, int length);
  22. static int build_rle_packet(unsigned char *row, int packet_type, int length, unsigned char *data);
  23. static int bmp_read_header(gdIOCtxPtr infile, bmp_hdr_t *hdr);
  24. static int bmp_read_info(gdIOCtxPtr infile, bmp_info_t *info);
  25. static int bmp_read_windows_v3_info(gdIOCtxPtr infile, bmp_info_t *info);
  26. static int bmp_read_os2_v1_info(gdIOCtxPtr infile, bmp_info_t *info);
  27. static int bmp_read_os2_v2_info(gdIOCtxPtr infile, bmp_info_t *info);
  28. static int bmp_read_direct(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header);
  29. static int bmp_read_1bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header);
  30. static int bmp_read_4bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header);
  31. static int bmp_read_8bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header);
  32. static int bmp_read_rle(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info);
  33. #define BMP_DEBUG(s)
  34. static int gdBMPPutWord(gdIOCtx *out, int w)
  35. {
  36. /* Byte order is little-endian */
  37. gdPutC(w & 0xFF, out);
  38. gdPutC((w >> 8) & 0xFF, out);
  39. return 0;
  40. }
  41. static int gdBMPPutInt(gdIOCtx *out, int w)
  42. {
  43. /* Byte order is little-endian */
  44. gdPutC(w & 0xFF, out);
  45. gdPutC((w >> 8) & 0xFF, out);
  46. gdPutC((w >> 16) & 0xFF, out);
  47. gdPutC((w >> 24) & 0xFF, out);
  48. return 0;
  49. }
  50. /*
  51. Function: gdImageBmpPtr
  52. */
  53. void * gdImageBmpPtr(gdImagePtr im, int *size, int compression)
  54. {
  55. void *rv;
  56. gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
  57. if (out == NULL) return NULL;
  58. gdImageBmpCtx(im, out, compression);
  59. rv = gdDPExtractData(out, size);
  60. out->gd_free(out);
  61. return rv;
  62. }
  63. /*
  64. Function: gdImageBmp
  65. */
  66. void gdImageBmp(gdImagePtr im, FILE *outFile, int compression)
  67. {
  68. gdIOCtx *out = gdNewFileCtx(outFile);
  69. if (out == NULL) return;
  70. gdImageBmpCtx(im, out, compression);
  71. out->gd_free(out);
  72. }
  73. /*
  74. Function: gdImageBmpCtx
  75. */
  76. void gdImageBmpCtx(gdImagePtr im, gdIOCtxPtr out, int compression)
  77. {
  78. int bitmap_size = 0, info_size, total_size, padding;
  79. int i, row, xpos, pixel;
  80. int error = 0;
  81. unsigned char *uncompressed_row = NULL, *uncompressed_row_start = NULL;
  82. FILE *tmpfile_for_compression = NULL;
  83. gdIOCtxPtr out_original = NULL;
  84. /* No compression if its true colour or we don't support seek */
  85. if (im->trueColor) {
  86. compression = 0;
  87. }
  88. if (compression == 1 && !out->seek) {
  89. /* Try to create a temp file where we can seek */
  90. if ((tmpfile_for_compression = tmpfile()) == NULL) {
  91. compression = 0;
  92. } else {
  93. out_original = out;
  94. if ((out = (gdIOCtxPtr)gdNewFileCtx(tmpfile_for_compression)) == NULL) {
  95. out = out_original;
  96. out_original = NULL;
  97. compression = 0;
  98. }
  99. }
  100. }
  101. bitmap_size = ((im->sx * (im->trueColor ? 24 : 8)) / 8) * im->sy;
  102. /* 40 byte Windows v3 header */
  103. info_size = BMP_WINDOWS_V3;
  104. /* data for the palette */
  105. if (!im->trueColor) {
  106. info_size += im->colorsTotal * 4;
  107. if (compression) {
  108. bitmap_size = 0;
  109. }
  110. }
  111. /* bitmap header + info header + data */
  112. total_size = 14 + info_size + bitmap_size;
  113. /* write bmp header info */
  114. gdPutBuf("BM", 2, out);
  115. gdBMPPutInt(out, total_size);
  116. gdBMPPutWord(out, 0);
  117. gdBMPPutWord(out, 0);
  118. gdBMPPutInt(out, 14 + info_size);
  119. /* write Windows v3 headers */
  120. gdBMPPutInt(out, BMP_WINDOWS_V3); /* header size */
  121. gdBMPPutInt(out, im->sx); /* width */
  122. gdBMPPutInt(out, im->sy); /* height */
  123. gdBMPPutWord(out, 1); /* colour planes */
  124. gdBMPPutWord(out, (im->trueColor ? 24 : 8)); /* bit count */
  125. gdBMPPutInt(out, (compression ? BMP_BI_RLE8 : BMP_BI_RGB)); /* compression */
  126. gdBMPPutInt(out, bitmap_size); /* image size */
  127. gdBMPPutInt(out, 0); /* H resolution */
  128. gdBMPPutInt(out, 0); /* V ressolution */
  129. gdBMPPutInt(out, im->colorsTotal); /* colours used */
  130. gdBMPPutInt(out, 0); /* important colours */
  131. /* The line must be divisible by 4, else its padded with NULLs */
  132. padding = ((int)(im->trueColor ? 3 : 1) * im->sx) % 4;
  133. if (padding) {
  134. padding = 4 - padding;
  135. }
  136. /* 8-bit colours */
  137. if (!im->trueColor) {
  138. for(i = 0; i< im->colorsTotal; ++i) {
  139. Putchar(gdImageBlue(im, i), out);
  140. Putchar(gdImageGreen(im, i), out);
  141. Putchar(gdImageRed(im, i), out);
  142. Putchar(0, out);
  143. }
  144. if (compression) {
  145. /* Can potentially change this to X + ((X / 128) * 3) */
  146. uncompressed_row = uncompressed_row_start = (unsigned char *) gdCalloc(gdImageSX(im) * 2, sizeof(char));
  147. if (!uncompressed_row) {
  148. /* malloc failed */
  149. goto cleanup;
  150. }
  151. }
  152. for (row = (im->sy - 1); row >= 0; row--) {
  153. if (compression) {
  154. memset (uncompressed_row, 0, gdImageSX(im));
  155. }
  156. for (xpos = 0; xpos < im->sx; xpos++) {
  157. if (compression) {
  158. *uncompressed_row++ = (unsigned char)gdImageGetPixel(im, xpos, row);
  159. } else {
  160. Putchar(gdImageGetPixel(im, xpos, row), out);
  161. }
  162. }
  163. if (!compression) {
  164. /* Add padding to make sure we have n mod 4 == 0 bytes per row */
  165. for (xpos = padding; xpos > 0; --xpos) {
  166. Putchar('\0', out);
  167. }
  168. } else {
  169. int compressed_size = 0;
  170. uncompressed_row = uncompressed_row_start;
  171. if ((compressed_size = compress_row(uncompressed_row, gdImageSX(im))) < 0) {
  172. error = 1;
  173. break;
  174. }
  175. bitmap_size += compressed_size;
  176. gdPutBuf(uncompressed_row, compressed_size, out);
  177. Putchar(BMP_RLE_COMMAND, out);
  178. Putchar(BMP_RLE_ENDOFLINE, out);
  179. bitmap_size += 2;
  180. }
  181. }
  182. if (compression && uncompressed_row) {
  183. gdFree(uncompressed_row);
  184. if (error != 0) {
  185. goto cleanup;
  186. }
  187. /* Update filesize based on new values and set compression flag */
  188. Putchar(BMP_RLE_COMMAND, out);
  189. Putchar(BMP_RLE_ENDOFBITMAP, out);
  190. bitmap_size += 2;
  191. /* Write new total bitmap size */
  192. gdSeek(out, 2);
  193. gdBMPPutInt(out, total_size + bitmap_size);
  194. /* Total length of image data */
  195. gdSeek(out, 34);
  196. gdBMPPutInt(out, bitmap_size);
  197. }
  198. } else {
  199. for (row = (im->sy - 1); row >= 0; row--) {
  200. for (xpos = 0; xpos < im->sx; xpos++) {
  201. pixel = gdImageGetPixel(im, xpos, row);
  202. Putchar(gdTrueColorGetBlue(pixel), out);
  203. Putchar(gdTrueColorGetGreen(pixel), out);
  204. Putchar(gdTrueColorGetRed(pixel), out);
  205. }
  206. /* Add padding to make sure we have n mod 4 == 0 bytes per row */
  207. for (xpos = padding; xpos > 0; --xpos) {
  208. Putchar('\0', out);
  209. }
  210. }
  211. }
  212. /* If we needed a tmpfile for compression copy it over to out_original */
  213. if (tmpfile_for_compression) {
  214. unsigned char* copy_buffer = NULL;
  215. int buffer_size = 0;
  216. gdSeek(out, 0);
  217. copy_buffer = (unsigned char *) gdMalloc(1024 * sizeof(unsigned char));
  218. if (copy_buffer == NULL) {
  219. goto cleanup;
  220. }
  221. while ((buffer_size = gdGetBuf(copy_buffer, 1024, out)) != EOF) {
  222. if (buffer_size == 0) {
  223. break;
  224. }
  225. gdPutBuf(copy_buffer , buffer_size, out_original);
  226. }
  227. gdFree(copy_buffer);
  228. /* Replace the temp with the original which now has data */
  229. out->gd_free(out);
  230. out = out_original;
  231. out_original = NULL;
  232. }
  233. cleanup:
  234. if (tmpfile_for_compression) {
  235. #ifdef _WIN32
  236. _rmtmp();
  237. #else
  238. fclose(tmpfile_for_compression);
  239. #endif
  240. tmpfile_for_compression = NULL;
  241. }
  242. if (out_original) {
  243. out_original->gd_free(out_original);
  244. }
  245. return;
  246. }
  247. static int compress_row(unsigned char *row, int length)
  248. {
  249. int rle_type = 0;
  250. int compressed_length = 0;
  251. int pixel = 0, compressed_run = 0, rle_compression = 0;
  252. unsigned char *uncompressed_row = NULL, *uncompressed_rowp = NULL, *uncompressed_start = NULL;
  253. uncompressed_row = (unsigned char *) gdMalloc(length);
  254. if (!uncompressed_row) {
  255. return -1;
  256. }
  257. memcpy(uncompressed_row, row, length);
  258. uncompressed_start = uncompressed_rowp = uncompressed_row;
  259. for (pixel = 0; pixel < length; pixel++) {
  260. if (compressed_run == 0) {
  261. uncompressed_row = uncompressed_rowp;
  262. compressed_run++;
  263. uncompressed_rowp++;
  264. rle_type = BMP_RLE_TYPE_RAW;
  265. continue;
  266. }
  267. if (compressed_run == 1) {
  268. /* Compare next byte */
  269. if (memcmp(uncompressed_rowp, uncompressed_rowp - 1, 1) == 0) {
  270. rle_type = BMP_RLE_TYPE_RLE;
  271. }
  272. }
  273. if (rle_type == BMP_RLE_TYPE_RLE) {
  274. if (compressed_run >= 128 || memcmp(uncompressed_rowp, uncompressed_rowp - 1, 1) != 0) {
  275. /* more than what we can store in a single run or run is over due to non match, force write */
  276. rle_compression = build_rle_packet(row, rle_type, compressed_run, uncompressed_row);
  277. row += rle_compression;
  278. compressed_length += rle_compression;
  279. compressed_run = 0;
  280. pixel--;
  281. } else {
  282. compressed_run++;
  283. uncompressed_rowp++;
  284. }
  285. } else {
  286. if (compressed_run >= 128 || memcmp(uncompressed_rowp, uncompressed_rowp - 1, 1) == 0) {
  287. /* more than what we can store in a single run or run is over due to match, force write */
  288. rle_compression = build_rle_packet(row, rle_type, compressed_run, uncompressed_row);
  289. row += rle_compression;
  290. compressed_length += rle_compression;
  291. compressed_run = 0;
  292. pixel--;
  293. } else {
  294. /* add this pixel to the row */
  295. compressed_run++;
  296. uncompressed_rowp++;
  297. }
  298. }
  299. }
  300. if (compressed_run) {
  301. if (rle_type == BMP_RLE_TYPE_RLE) {
  302. compressed_length += build_rle_packet(row, rle_type, compressed_run, uncompressed_row);
  303. }
  304. }
  305. gdFree(uncompressed_start);
  306. return compressed_length;
  307. }
  308. static int build_rle_packet(unsigned char *row, int packet_type, int length, unsigned char *data)
  309. {
  310. int compressed_size = 0;
  311. if (length < 1 || length > 128) {
  312. return 0;
  313. }
  314. /* Bitmap specific cases is that we can't have uncompressed rows of length 1 or 2 */
  315. if (packet_type == BMP_RLE_TYPE_RAW && length < 3) {
  316. int i = 0;
  317. for (i = 0; i < length; i++) {
  318. compressed_size += 2;
  319. memset(row, 1, 1);
  320. row++;
  321. memcpy(row, data++, 1);
  322. row++;
  323. }
  324. } else if (packet_type == BMP_RLE_TYPE_RLE) {
  325. compressed_size = 2;
  326. memset(row, length, 1);
  327. row++;
  328. memcpy(row, data, 1);
  329. row++;
  330. } else {
  331. compressed_size = 2 + length;
  332. memset(row, BMP_RLE_COMMAND, 1);
  333. row++;
  334. memset(row, length, 1);
  335. row++;
  336. memcpy(row, data, length);
  337. row += length;
  338. /* Must be an even number for an uncompressed run */
  339. if (length % 2) {
  340. memset(row, 0, 1);
  341. row++;
  342. compressed_size++;
  343. }
  344. }
  345. return compressed_size;
  346. }
  347. /*
  348. Function: gdImageCreateFromBmp
  349. */
  350. gdImagePtr gdImageCreateFromBmp(FILE * inFile)
  351. {
  352. gdImagePtr im = 0;
  353. gdIOCtx *in = gdNewFileCtx(inFile);
  354. if (in == NULL) return NULL;
  355. im = gdImageCreateFromBmpCtx(in);
  356. in->gd_free(in);
  357. return im;
  358. }
  359. /*
  360. Function: gdImageCreateFromBmpPtr
  361. */
  362. gdImagePtr gdImageCreateFromBmpPtr(int size, void *data)
  363. {
  364. gdImagePtr im;
  365. gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
  366. if (in == NULL) return NULL;
  367. im = gdImageCreateFromBmpCtx(in);
  368. in->gd_free(in);
  369. return im;
  370. }
  371. /*
  372. Function: gdImageCreateFromBmpCtx
  373. */
  374. gdImagePtr gdImageCreateFromBmpCtx(gdIOCtxPtr infile)
  375. {
  376. bmp_hdr_t *hdr;
  377. bmp_info_t *info;
  378. gdImagePtr im = NULL;
  379. int error = 0;
  380. if (!(hdr= (bmp_hdr_t *)gdCalloc(1, sizeof(bmp_hdr_t)))) {
  381. return NULL;
  382. }
  383. if (bmp_read_header(infile, hdr)) {
  384. gdFree(hdr);
  385. return NULL;
  386. }
  387. if (hdr->magic != 0x4d42) {
  388. gdFree(hdr);
  389. return NULL;
  390. }
  391. if (!(info = (bmp_info_t *)gdCalloc(1, sizeof(bmp_info_t)))) {
  392. gdFree(hdr);
  393. return NULL;
  394. }
  395. if (bmp_read_info(infile, info)) {
  396. gdFree(hdr);
  397. gdFree(info);
  398. return NULL;
  399. }
  400. BMP_DEBUG(printf("Numcolours: %d\n", info->numcolors));
  401. BMP_DEBUG(printf("Width: %d\n", info->width));
  402. BMP_DEBUG(printf("Height: %d\n", info->height));
  403. BMP_DEBUG(printf("Planes: %d\n", info->numplanes));
  404. BMP_DEBUG(printf("Depth: %d\n", info->depth));
  405. BMP_DEBUG(printf("Offset: %d\n", hdr->off));
  406. if (info->depth >= 16) {
  407. im = gdImageCreateTrueColor(info->width, info->height);
  408. } else {
  409. im = gdImageCreate(info->width, info->height);
  410. }
  411. if (!im) {
  412. gdFree(hdr);
  413. gdFree(info);
  414. return NULL;
  415. }
  416. switch (info->depth) {
  417. case 1:
  418. BMP_DEBUG(printf("1-bit image\n"));
  419. error = bmp_read_1bit(im, infile, info, hdr);
  420. break;
  421. case 4:
  422. BMP_DEBUG(printf("4-bit image\n"));
  423. error = bmp_read_4bit(im, infile, info, hdr);
  424. break;
  425. case 8:
  426. BMP_DEBUG(printf("8-bit image\n"));
  427. error = bmp_read_8bit(im, infile, info, hdr);
  428. break;
  429. case 16:
  430. case 24:
  431. case 32:
  432. BMP_DEBUG(printf("Direct BMP image\n"));
  433. error = bmp_read_direct(im, infile, info, hdr);
  434. break;
  435. default:
  436. BMP_DEBUG(printf("Unknown bit count\n"));
  437. error = 1;
  438. }
  439. gdFree(hdr);
  440. gdFree(info);
  441. if (error) {
  442. gdImageDestroy(im);
  443. return NULL;
  444. }
  445. return im;
  446. }
  447. static int bmp_read_header(gdIOCtx *infile, bmp_hdr_t *hdr)
  448. {
  449. if(
  450. !gdGetWordLSB(&hdr->magic, infile) ||
  451. !gdGetIntLSB(&hdr->size, infile) ||
  452. !gdGetWordLSB(&hdr->reserved1, infile) ||
  453. !gdGetWordLSB(&hdr->reserved2 , infile) ||
  454. !gdGetIntLSB(&hdr->off , infile)
  455. ) {
  456. return 1;
  457. }
  458. return 0;
  459. }
  460. static int bmp_read_info(gdIOCtx *infile, bmp_info_t *info)
  461. {
  462. /* read BMP length so we can work out the version */
  463. if (!gdGetIntLSB(&info->len, infile)) {
  464. return 1;
  465. }
  466. switch (info->len) {
  467. /* For now treat Windows v4 + v5 as v3 */
  468. case BMP_WINDOWS_V3:
  469. case BMP_WINDOWS_V4:
  470. case BMP_WINDOWS_V5:
  471. BMP_DEBUG(printf("Reading Windows Header\n"));
  472. if (bmp_read_windows_v3_info(infile, info)) {
  473. return 1;
  474. }
  475. break;
  476. case BMP_OS2_V1:
  477. if (bmp_read_os2_v1_info(infile, info)) {
  478. return 1;
  479. }
  480. break;
  481. case BMP_OS2_V2:
  482. if (bmp_read_os2_v2_info(infile, info)) {
  483. return 1;
  484. }
  485. break;
  486. default:
  487. BMP_DEBUG(printf("Unhandled bitmap\n"));
  488. return 1;
  489. }
  490. return 0;
  491. }
  492. static int bmp_read_windows_v3_info(gdIOCtxPtr infile, bmp_info_t *info)
  493. {
  494. if (
  495. !gdGetIntLSB(&info->width, infile) ||
  496. !gdGetIntLSB(&info->height, infile) ||
  497. !gdGetWordLSB(&info->numplanes, infile) ||
  498. !gdGetWordLSB(&info->depth, infile) ||
  499. !gdGetIntLSB(&info->enctype, infile) ||
  500. !gdGetIntLSB(&info->size, infile) ||
  501. !gdGetIntLSB(&info->hres, infile) ||
  502. !gdGetIntLSB(&info->vres, infile) ||
  503. !gdGetIntLSB(&info->numcolors, infile) ||
  504. !gdGetIntLSB(&info->mincolors, infile)
  505. ) {
  506. return 1;
  507. }
  508. if (info->height < 0) {
  509. info->topdown = 1;
  510. info->height = -info->height;
  511. } else {
  512. info->topdown = 0;
  513. }
  514. info->type = BMP_PALETTE_4;
  515. if (info->width <= 0 || info->height <= 0 || info->numplanes <= 0 ||
  516. info->depth <= 0 || info->numcolors < 0 || info->mincolors < 0) {
  517. return 1;
  518. }
  519. return 0;
  520. }
  521. static int bmp_read_os2_v1_info(gdIOCtxPtr infile, bmp_info_t *info)
  522. {
  523. if (
  524. !gdGetWordLSB((signed short int *)&info->width, infile) ||
  525. !gdGetWordLSB((signed short int *)&info->height, infile) ||
  526. !gdGetWordLSB(&info->numplanes, infile) ||
  527. !gdGetWordLSB(&info->depth, infile)
  528. ) {
  529. return 1;
  530. }
  531. /* OS2 v1 doesn't support topdown */
  532. info->topdown = 0;
  533. info->numcolors = 1 << info->depth;
  534. info->type = BMP_PALETTE_3;
  535. if (info->width <= 0 || info->height <= 0 || info->numplanes <= 0 ||
  536. info->depth <= 0 || info->numcolors < 0) {
  537. return 1;
  538. }
  539. return 0;
  540. }
  541. static int bmp_read_os2_v2_info(gdIOCtxPtr infile, bmp_info_t *info)
  542. {
  543. char useless_bytes[24];
  544. if (
  545. !gdGetIntLSB(&info->width, infile) ||
  546. !gdGetIntLSB(&info->height, infile) ||
  547. !gdGetWordLSB(&info->numplanes, infile) ||
  548. !gdGetWordLSB(&info->depth, infile) ||
  549. !gdGetIntLSB(&info->enctype, infile) ||
  550. !gdGetIntLSB(&info->size, infile) ||
  551. !gdGetIntLSB(&info->hres, infile) ||
  552. !gdGetIntLSB(&info->vres, infile) ||
  553. !gdGetIntLSB(&info->numcolors, infile) ||
  554. !gdGetIntLSB(&info->mincolors, infile)
  555. ) {
  556. return 1;
  557. }
  558. /* Lets seek the next 24 pointless bytes, we don't care too much about it */
  559. if (!gdGetBuf(useless_bytes, 24, infile)) {
  560. return 1;
  561. }
  562. if (info->height < 0) {
  563. info->topdown = 1;
  564. info->height = -info->height;
  565. } else {
  566. info->topdown = 0;
  567. }
  568. info->type = BMP_PALETTE_4;
  569. if (info->width <= 0 || info->height <= 0 || info->numplanes <= 0 ||
  570. info->depth <= 0 || info->numcolors < 0 || info->mincolors < 0) {
  571. return 1;
  572. }
  573. return 0;
  574. }
  575. static int bmp_read_direct(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header)
  576. {
  577. int ypos = 0, xpos = 0, row = 0;
  578. int padding = 0, alpha = 0, red = 0, green = 0, blue = 0;
  579. signed short int data = 0;
  580. switch(info->enctype) {
  581. case BMP_BI_RGB:
  582. /* no-op */
  583. break;
  584. case BMP_BI_BITFIELDS:
  585. if (info->depth == 24) {
  586. BMP_DEBUG(printf("Bitfield compression isn't supported for 24-bit\n"));
  587. return 1;
  588. }
  589. BMP_DEBUG(printf("Currently no bitfield support\n"));
  590. return 1;
  591. break;
  592. case BMP_BI_RLE8:
  593. if (info->depth != 8) {
  594. BMP_DEBUG(printf("RLE is only valid for 8-bit images\n"));
  595. return 1;
  596. }
  597. break;
  598. case BMP_BI_RLE4:
  599. if (info->depth != 4) {
  600. BMP_DEBUG(printf("RLE is only valid for 4-bit images\n"));
  601. return 1;
  602. }
  603. break;
  604. case BMP_BI_JPEG:
  605. case BMP_BI_PNG:
  606. default:
  607. BMP_DEBUG(printf("Unsupported BMP compression format\n"));
  608. return 1;
  609. }
  610. /* There is a chance the data isn't until later, would be weird but it is possible */
  611. if (gdTell(infile) != header->off) {
  612. /* Should make sure we don't seek past the file size */
  613. if (!gdSeek(infile, header->off)) {
  614. return 1;
  615. }
  616. }
  617. /* The line must be divisible by 4, else its padded with NULLs */
  618. padding = ((int)(info->depth / 8) * info->width) % 4;
  619. if (padding) {
  620. padding = 4 - padding;
  621. }
  622. for (ypos = 0; ypos < info->height; ++ypos) {
  623. if (info->topdown) {
  624. row = ypos;
  625. } else {
  626. row = info->height - ypos - 1;
  627. }
  628. for (xpos = 0; xpos < info->width; xpos++) {
  629. if (info->depth == 16) {
  630. if (!gdGetWordLSB(&data, infile)) {
  631. return 1;
  632. }
  633. BMP_DEBUG(printf("Data: %X\n", data));
  634. red = ((data & 0x7C00) >> 10) << 3;
  635. green = ((data & 0x3E0) >> 5) << 3;
  636. blue = (data & 0x1F) << 3;
  637. BMP_DEBUG(printf("R: %d, G: %d, B: %d\n", red, green, blue));
  638. } else if (info->depth == 24) {
  639. if (!gdGetByte(&blue, infile) || !gdGetByte(&green, infile) || !gdGetByte(&red, infile)) {
  640. return 1;
  641. }
  642. } else {
  643. if (!gdGetByte(&blue, infile) || !gdGetByte(&green, infile) || !gdGetByte(&red, infile) || !gdGetByte(&alpha, infile)) {
  644. return 1;
  645. }
  646. }
  647. /*alpha = gdAlphaMax - (alpha >> 1);*/
  648. gdImageSetPixel(im, xpos, row, gdTrueColor(red, green, blue));
  649. }
  650. for (xpos = padding; xpos > 0; --xpos) {
  651. if (!gdGetByte(&red, infile)) {
  652. return 1;
  653. }
  654. }
  655. }
  656. return 0;
  657. }
  658. static int bmp_read_palette(gdImagePtr im, gdIOCtxPtr infile, int count, int read_four)
  659. {
  660. int i;
  661. int r, g, b, z;
  662. for (i = 0; i < count; i++) {
  663. if (
  664. !gdGetByte(&b, infile) ||
  665. !gdGetByte(&g, infile) ||
  666. !gdGetByte(&r, infile) ||
  667. (read_four && !gdGetByte(&z, infile))
  668. ) {
  669. return 1;
  670. }
  671. im->red[i] = r;
  672. im->green[i] = g;
  673. im->blue[i] = b;
  674. im->open[i] = 1;
  675. }
  676. return 0;
  677. }
  678. static int bmp_read_1bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header)
  679. {
  680. int ypos = 0, xpos = 0, row = 0, index = 0;
  681. int padding = 0, current_byte = 0, bit = 0;
  682. if (info->enctype != BMP_BI_RGB) {
  683. return 1;
  684. }
  685. if (!info->numcolors) {
  686. info->numcolors = 2;
  687. } else if (info->numcolors < 0 || info->numcolors > 2) {
  688. return 1;
  689. }
  690. if (bmp_read_palette(im, infile, info->numcolors, (info->type == BMP_PALETTE_4))) {
  691. return 1;
  692. }
  693. im->colorsTotal = info->numcolors;
  694. /* There is a chance the data isn't until later, would be weird but it is possible */
  695. if (gdTell(infile) != header->off) {
  696. /* Should make sure we don't seek past the file size */
  697. if (!gdSeek(infile, header->off)) {
  698. return 1;
  699. }
  700. }
  701. /* The line must be aligned on a 32 bits word, else it is padded with zeros */
  702. padding = (info->width + 7) / 8 % 4;
  703. if (padding) {
  704. padding = 4 - padding;
  705. }
  706. for (ypos = 0; ypos < info->height; ++ypos) {
  707. if (info->topdown) {
  708. row = ypos;
  709. } else {
  710. row = info->height - ypos - 1;
  711. }
  712. for (xpos = 0; xpos < info->width; xpos += 8) {
  713. /* Bitmaps are always aligned in bytes so we'll never overflow */
  714. if (!gdGetByte(&current_byte, infile)) {
  715. return 1;
  716. }
  717. for (bit = 0; bit < 8; bit++) {
  718. index = ((current_byte & (0x80 >> bit)) != 0 ? 0x01 : 0x00);
  719. if (im->open[index]) {
  720. im->open[index] = 0;
  721. }
  722. gdImageSetPixel(im, xpos + bit, row, index);
  723. /* No need to read anything extra */
  724. if ((xpos + bit) >= info->width) {
  725. break;
  726. }
  727. }
  728. }
  729. for (xpos = padding; xpos > 0; --xpos) {
  730. if (!gdGetByte(&index, infile)) {
  731. return 1;
  732. }
  733. }
  734. }
  735. return 0;
  736. }
  737. static int bmp_read_4bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header)
  738. {
  739. int ypos = 0, xpos = 0, row = 0, index = 0;
  740. int padding = 0, current_byte = 0;
  741. if (info->enctype != BMP_BI_RGB && info->enctype != BMP_BI_RLE4) {
  742. return 1;
  743. }
  744. if (!info->numcolors) {
  745. info->numcolors = 16;
  746. } else if (info->numcolors < 0 || info->numcolors > 16) {
  747. return 1;
  748. }
  749. if (bmp_read_palette(im, infile, info->numcolors, (info->type == BMP_PALETTE_4))) {
  750. return 1;
  751. }
  752. im->colorsTotal = info->numcolors;
  753. /* There is a chance the data isn't until later, would be weird but it is possible */
  754. if (gdTell(infile) != header->off) {
  755. /* Should make sure we don't seek past the file size */
  756. if (!gdSeek(infile, header->off)) {
  757. return 1;
  758. }
  759. }
  760. /* The line must be divisible by 4, else its padded with NULLs */
  761. padding = ((int)ceil(0.5 * info->width)) % 4;
  762. if (padding) {
  763. padding = 4 - padding;
  764. }
  765. switch (info->enctype) {
  766. case BMP_BI_RGB:
  767. for (ypos = 0; ypos < info->height; ++ypos) {
  768. if (info->topdown) {
  769. row = ypos;
  770. } else {
  771. row = info->height - ypos - 1;
  772. }
  773. for (xpos = 0; xpos < info->width; xpos += 2) {
  774. if (!gdGetByte(&current_byte, infile)) {
  775. return 1;
  776. }
  777. index = (current_byte >> 4) & 0x0f;
  778. if (im->open[index]) {
  779. im->open[index] = 0;
  780. }
  781. gdImageSetPixel(im, xpos, row, index);
  782. /* This condition may get called often, potential optimsations */
  783. if (xpos >= info->width) {
  784. break;
  785. }
  786. index = current_byte & 0x0f;
  787. if (im->open[index]) {
  788. im->open[index] = 0;
  789. }
  790. gdImageSetPixel(im, xpos + 1, row, index);
  791. }
  792. for (xpos = padding; xpos > 0; --xpos) {
  793. if (!gdGetByte(&index, infile)) {
  794. return 1;
  795. }
  796. }
  797. }
  798. break;
  799. case BMP_BI_RLE4:
  800. if (bmp_read_rle(im, infile, info)) {
  801. return 1;
  802. }
  803. break;
  804. default:
  805. return 1;
  806. }
  807. return 0;
  808. }
  809. static int bmp_read_8bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header)
  810. {
  811. int ypos = 0, xpos = 0, row = 0, index = 0;
  812. int padding = 0;
  813. if (info->enctype != BMP_BI_RGB && info->enctype != BMP_BI_RLE8) {
  814. return 1;
  815. }
  816. if (!info->numcolors) {
  817. info->numcolors = 256;
  818. } else if (info->numcolors < 0 || info->numcolors > 256) {
  819. return 1;
  820. }
  821. if (bmp_read_palette(im, infile, info->numcolors, (info->type == BMP_PALETTE_4))) {
  822. return 1;
  823. }
  824. im->colorsTotal = info->numcolors;
  825. /* There is a chance the data isn't until later, would be weird but it is possible */
  826. if (gdTell(infile) != header->off) {
  827. /* Should make sure we don't seek past the file size */
  828. if (!gdSeek(infile, header->off)) {
  829. return 1;
  830. }
  831. }
  832. /* The line must be divisible by 4, else its padded with NULLs */
  833. padding = (1 * info->width) % 4;
  834. if (padding) {
  835. padding = 4 - padding;
  836. }
  837. switch (info->enctype) {
  838. case BMP_BI_RGB:
  839. for (ypos = 0; ypos < info->height; ++ypos) {
  840. if (info->topdown) {
  841. row = ypos;
  842. } else {
  843. row = info->height - ypos - 1;
  844. }
  845. for (xpos = 0; xpos < info->width; ++xpos) {
  846. if (!gdGetByte(&index, infile)) {
  847. return 1;
  848. }
  849. if (im->open[index]) {
  850. im->open[index] = 0;
  851. }
  852. gdImageSetPixel(im, xpos, row, index);
  853. }
  854. /* Could create a new variable, but it isn't really worth it */
  855. for (xpos = padding; xpos > 0; --xpos) {
  856. if (!gdGetByte(&index, infile)) {
  857. return 1;
  858. }
  859. }
  860. }
  861. break;
  862. case BMP_BI_RLE8:
  863. if (bmp_read_rle(im, infile, info)) {
  864. return 1;
  865. }
  866. break;
  867. default:
  868. return 1;
  869. }
  870. return 0;
  871. }
  872. static int bmp_read_rle(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info)
  873. {
  874. int ypos = 0, xpos = 0, row = 0, index = 0;
  875. int rle_length = 0, rle_data = 0;
  876. int padding = 0;
  877. int i = 0, j = 0;
  878. int pixels_per_byte = 8 / info->depth;
  879. for (ypos = 0; ypos < info->height && xpos <= info->width;) {
  880. if (!gdGetByte(&rle_length, infile) || !gdGetByte(&rle_data, infile)) {
  881. return 1;
  882. }
  883. row = info->height - ypos - 1;
  884. if (rle_length != BMP_RLE_COMMAND) {
  885. if (im->open[rle_data]) {
  886. im->open[rle_data] = 0;
  887. }
  888. for (i = 0; (i < rle_length) && (xpos < info->width);) {
  889. for (j = 1; (j <= pixels_per_byte) && (xpos < info->width) && (i < rle_length); j++, xpos++, i++) {
  890. index = (rle_data & (((1 << info->depth) - 1) << (8 - (j * info->depth)))) >> (8 - (j * info->depth));
  891. if (im->open[index]) {
  892. im->open[index] = 0;
  893. }
  894. gdImageSetPixel(im, xpos, row, index);
  895. }
  896. }
  897. } else if (rle_length == BMP_RLE_COMMAND && rle_data > 2) {
  898. /* Uncompressed RLE needs to be even */
  899. padding = 0;
  900. for (i = 0; (i < rle_data) && (xpos < info->width); i += pixels_per_byte) {
  901. int max_pixels = pixels_per_byte;
  902. if (!gdGetByte(&index, infile)) {
  903. return 1;
  904. }
  905. padding++;
  906. if (rle_data - i < max_pixels) {
  907. max_pixels = rle_data - i;
  908. }
  909. for (j = 1; (j <= max_pixels) && (xpos < info->width); j++, xpos++) {
  910. int temp = (index >> (8 - (j * info->depth))) & ((1 << info->depth) - 1);
  911. if (im->open[temp]) {
  912. im->open[temp] = 0;
  913. }
  914. gdImageSetPixel(im, xpos, row, temp);
  915. }
  916. }
  917. /* Make sure the bytes read are even */
  918. if (padding % 2 && !gdGetByte(&index, infile)) {
  919. return 1;
  920. }
  921. } else if (rle_length == BMP_RLE_COMMAND && rle_data == BMP_RLE_ENDOFLINE) {
  922. /* Next Line */
  923. xpos = 0;
  924. ypos++;
  925. } else if (rle_length == BMP_RLE_COMMAND && rle_data == BMP_RLE_DELTA) {
  926. /* Delta Record, used for bmp files that contain other data*/
  927. if (!gdGetByte(&rle_length, infile) || !gdGetByte(&rle_data, infile)) {
  928. return 1;
  929. }
  930. xpos += rle_length;
  931. ypos += rle_data;
  932. } else if (rle_length == BMP_RLE_COMMAND && rle_data == BMP_RLE_ENDOFBITMAP) {
  933. /* End of bitmap */
  934. break;
  935. }
  936. }
  937. return 0;
  938. }