PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/bmpfile.c

http://libbmp.googlecode.com/
C | 710 lines | 536 code | 116 blank | 58 comment | 101 complexity | f9877a3f200f403779bb5157c5b9ec1a MD5 | raw file
Possible License(s): GPL-3.0
  1. /**
  2. * @file bmpfile.c
  3. * @brief The BMP library implementation
  4. *
  5. * libbmp - BMP library
  6. * Copyright (C) 2009 lidaibin(????)
  7. * mail: lidaibin@gmail.com
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the
  21. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  22. * Boston, MA 02111-1307, USA.
  23. *
  24. * $Id: bmpfile.c 3 2010-02-01 03:31:44Z lidaibin $
  25. */
  26. /*
  27. * BMP File Header Stores general information about the BMP file.
  28. * DIB header Stores detailed information about the bitmap image.
  29. * Color Palette Stores the definition of the colors being used for
  30. * indexed color bitmaps.
  31. * Bitmap Data Stores the actual image, pixel by pixel.
  32. */
  33. #include <math.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include "bmpfile.h"
  38. #define DEFAULT_DPI_X 3780
  39. #define DEFAULT_DPI_Y 3780
  40. #define DPI_FACTOR 39.37007874015748
  41. struct _bmpfile {
  42. bmp_header_t header;
  43. bmp_dib_v3_header_t dib;
  44. rgb_pixel_t **pixels;
  45. rgb_pixel_t *colors;
  46. };
  47. static uint32_t
  48. uint32_pow(uint32_t base, uint32_t depth)
  49. {
  50. uint32_t i, result = 1;
  51. for (i = 0; i < depth; ++i)
  52. result *= base;
  53. return result;
  54. }
  55. /**
  56. * Create the standard color table for BMP object
  57. */
  58. static void
  59. bmp_create_standard_color_table(bmpfile_t *bmp)
  60. {
  61. int i, j, k, ell;
  62. switch (bmp->dib.depth) {
  63. case 1:
  64. for (i = 0; i < 2; ++i) {
  65. bmp->colors[i].red = i * 255;
  66. bmp->colors[i].green = i * 255;
  67. bmp->colors[i].blue = i * 255;
  68. bmp->colors[i].alpha = 0;
  69. }
  70. break;
  71. case 4:
  72. i = 0;
  73. for (ell = 0; ell < 2; ++ell) {
  74. for (k = 0; k < 2; ++k) {
  75. for (j = 0; j < 2; ++j) {
  76. bmp->colors[i].red = j * 128;
  77. bmp->colors[i].green = k * 128;
  78. bmp->colors[i].blue = ell * 128;
  79. bmp->colors[i].alpha = 0;
  80. ++i;
  81. }
  82. }
  83. }
  84. for (ell = 0; ell < 2; ++ell) {
  85. for (k = 0; k < 2; ++k) {
  86. for (j = 0; j < 2; ++j) {
  87. bmp->colors[i].red = j * 255;
  88. bmp->colors[i].green = k * 255;
  89. bmp->colors[i].blue = ell * 255;
  90. bmp->colors[i].alpha = 0;
  91. ++i;
  92. }
  93. }
  94. }
  95. i = 8;
  96. bmp->colors[i].red = 192;
  97. bmp->colors[i].green = 192;
  98. bmp->colors[i].blue = 192;
  99. bmp->colors[i].alpha = 0;
  100. break;
  101. case 8:
  102. i = 0;
  103. for (ell = 0; ell < 4; ++ell) {
  104. for (k = 0; k < 8; ++k) {
  105. for (j = 0; j < 8; ++j) {
  106. bmp->colors[i].red = j * 32;
  107. bmp->colors[i].green = k * 32;
  108. bmp->colors[i].blue = ell * 64;
  109. bmp->colors[i].alpha = 0;
  110. ++i;
  111. }
  112. }
  113. }
  114. i = 0;
  115. for (ell = 0; ell < 2; ++ell) {
  116. for (k = 0; k < 2; ++k) {
  117. for (j = 0; j < 2; ++j) {
  118. bmp->colors[i].red = j * 128;
  119. bmp->colors[i].green = k * 128;
  120. bmp->colors[i].blue = ell * 128;
  121. ++i;
  122. }
  123. }
  124. }
  125. // overwrite colors 7, 8, 9
  126. i = 7;
  127. bmp->colors[i].red = 192;
  128. bmp->colors[i].green = 192;
  129. bmp->colors[i].blue = 192;
  130. i++; // 8
  131. bmp->colors[i].red = 192;
  132. bmp->colors[i].green = 220;
  133. bmp->colors[i].blue = 192;
  134. i++; // 9
  135. bmp->colors[i].red = 166;
  136. bmp->colors[i].green = 202;
  137. bmp->colors[i].blue = 240;
  138. // overwrite colors 246 to 255
  139. i = 246;
  140. bmp->colors[i].red = 255;
  141. bmp->colors[i].green = 251;
  142. bmp->colors[i].blue = 240;
  143. i++; // 247
  144. bmp->colors[i].red = 160;
  145. bmp->colors[i].green = 160;
  146. bmp->colors[i].blue = 164;
  147. i++; // 248
  148. bmp->colors[i].red = 128;
  149. bmp->colors[i].green = 128;
  150. bmp->colors[i].blue = 128;
  151. i++; // 249
  152. bmp->colors[i].red = 255;
  153. bmp->colors[i].green = 0;
  154. bmp->colors[i].blue = 0;
  155. i++; // 250
  156. bmp->colors[i].red = 0;
  157. bmp->colors[i].green = 255;
  158. bmp->colors[i].blue = 0;
  159. i++; // 251
  160. bmp->colors[i].red = 255;
  161. bmp->colors[i].green = 255;
  162. bmp->colors[i].blue = 0;
  163. i++; // 252
  164. bmp->colors[i].red = 0;
  165. bmp->colors[i].green = 0;
  166. bmp->colors[i].blue = 255;
  167. i++; // 253
  168. bmp->colors[i].red = 255;
  169. bmp->colors[i].green = 0;
  170. bmp->colors[i].blue = 255;
  171. i++; // 254
  172. bmp->colors[i].red = 0;
  173. bmp->colors[i].green = 255;
  174. bmp->colors[i].blue = 255;
  175. i++; // 255
  176. bmp->colors[i].red = 255;
  177. bmp->colors[i].green = 255;
  178. bmp->colors[i].blue = 255;
  179. break;
  180. }
  181. }
  182. /**
  183. * Create grayscale color table for BMP object
  184. */
  185. static void
  186. bmp_create_grayscale_color_table(bmpfile_t *bmp)
  187. {
  188. int i;
  189. uint8_t step_size;
  190. if (!bmp->colors) return;
  191. if (bmp->dib.depth != 1)
  192. step_size = 255 / (bmp->dib.ncolors - 1);
  193. else
  194. step_size = 255;
  195. for (i = 0; i < bmp->dib.ncolors; ++i) {
  196. uint8_t value = i * step_size;
  197. rgb_pixel_t color = {value, value, value, 0};
  198. bmp->colors[i] = color;
  199. }
  200. }
  201. /**
  202. * Malloc the memory for color palette
  203. */
  204. static void
  205. bmp_malloc_colors(bmpfile_t *bmp)
  206. {
  207. bmp->dib.ncolors = uint32_pow(2, bmp->dib.depth);
  208. if (bmp->dib.depth == 1 || bmp->dib.depth == 4 || bmp->dib.depth == 8) {
  209. bmp->colors = malloc(sizeof(rgb_pixel_t) * bmp->dib.ncolors);
  210. bmp_create_standard_color_table(bmp);
  211. }
  212. }
  213. /**
  214. * Free the memory of color palette
  215. */
  216. static void
  217. bmp_free_colors(bmpfile_t *bmp)
  218. {
  219. if (bmp->colors)
  220. free(bmp->colors);
  221. }
  222. /**
  223. * Malloc the memory for pixels
  224. */
  225. static void
  226. bmp_malloc_pixels(bmpfile_t *bmp)
  227. {
  228. int i, j;
  229. bmp->pixels = malloc(sizeof(rgb_pixel_t *) * bmp->dib.width);
  230. for (i = 0; i < bmp->dib.width; ++i) {
  231. bmp->pixels[i] = malloc(sizeof(rgb_pixel_t) * bmp->dib.height);
  232. for (j = 0; j < bmp->dib.height; ++j) {
  233. bmp->pixels[i][j].red = 255;
  234. bmp->pixels[i][j].green = 255;
  235. bmp->pixels[i][j].blue = 255;
  236. bmp->pixels[i][j].alpha = 0;
  237. }
  238. }
  239. }
  240. /**
  241. * Free the memory of pixels
  242. */
  243. static void
  244. bmp_free_pixels(bmpfile_t *bmp)
  245. {
  246. int i;
  247. for (i = 0; i < bmp->dib.width; ++i)
  248. free(bmp->pixels[i]);
  249. free(bmp->pixels), bmp->pixels = NULL;
  250. }
  251. /**
  252. * Create the BMP object with specified width and height and depth.
  253. */
  254. bmpfile_t *
  255. bmp_create(uint32_t width, uint32_t height, uint32_t depth)
  256. {
  257. bmpfile_t *result;
  258. double bytes_per_pixel;
  259. uint32_t bytes_per_line;
  260. uint32_t palette_size;
  261. if (depth != 1 && depth != 4 && depth != 8 && depth != 16 && depth != 24 &&
  262. depth != 32)
  263. return NULL;
  264. result = malloc(sizeof(bmpfile_t));
  265. memset(result, 0, sizeof(bmpfile_t));
  266. result->header.magic[0] = 'B';
  267. result->header.magic[1] = 'M';
  268. result->dib.header_sz = 40;
  269. result->dib.width = width;
  270. result->dib.height = height;
  271. result->dib.nplanes = 1;
  272. result->dib.depth = depth;
  273. result->dib.hres = DEFAULT_DPI_X;
  274. result->dib.vres = DEFAULT_DPI_Y;
  275. if (depth == 16)
  276. result->dib.compress_type = BI_BITFIELDS;
  277. else
  278. result->dib.compress_type = BI_RGB;
  279. bmp_malloc_pixels(result);
  280. bmp_malloc_colors(result);
  281. /* Calculate the field value of header and DIB */
  282. bytes_per_pixel = (result->dib.depth * 1.0) / 8.0;
  283. bytes_per_line = (int)ceil(bytes_per_pixel * result->dib.width);
  284. if (bytes_per_line % 4 != 0)
  285. bytes_per_line += 4 - bytes_per_line % 4;
  286. result->dib.bmp_bytesz = bytes_per_line * result->dib.height;
  287. palette_size = 0;
  288. if (depth == 1 || depth == 4 || depth == 8)
  289. palette_size = uint32_pow(2, result->dib.depth) * 4;
  290. else if (result->dib.depth == 16)
  291. palette_size = 3 * 4;
  292. result->header.offset = 14 + result->dib.header_sz + palette_size;
  293. result->header.filesz = result->header.offset + result->dib.bmp_bytesz;
  294. return result;
  295. }
  296. void
  297. bmp_destroy(bmpfile_t *bmp)
  298. {
  299. bmp_free_pixels(bmp);
  300. bmp_free_colors(bmp);
  301. free(bmp);
  302. }
  303. uint32_t
  304. bmp_get_width(bmpfile_t *bmp)
  305. {
  306. return bmp->dib.width;
  307. }
  308. uint32_t
  309. bmp_get_height(bmpfile_t *bmp)
  310. {
  311. return bmp->dib.height;
  312. }
  313. uint32_t
  314. bmp_get_depth(bmpfile_t *bmp)
  315. {
  316. return bmp->dib.depth;
  317. }
  318. bmp_header_t
  319. bmp_get_header(bmpfile_t *bmp)
  320. {
  321. return bmp->header;
  322. }
  323. bmp_dib_v3_header_t
  324. bmp_get_dib(bmpfile_t *bmp)
  325. {
  326. return bmp->dib;
  327. }
  328. uint32_t
  329. bmp_get_dpi_x(bmpfile_t *bmp)
  330. {
  331. return (uint32_t)(bmp->dib.hres / DPI_FACTOR);
  332. }
  333. uint32_t
  334. bmp_get_dpi_y(bmpfile_t *bmp)
  335. {
  336. return (uint32_t)(bmp->dib.vres / DPI_FACTOR);
  337. }
  338. void
  339. bmp_set_dpi(bmpfile_t *bmp, uint32_t x, uint32_t y)
  340. {
  341. bmp->dib.hres = (uint32_t)(x * DPI_FACTOR);
  342. bmp->dib.vres = (uint32_t)(y * DPI_FACTOR);
  343. }
  344. rgb_pixel_t *
  345. bmp_get_pixel(bmpfile_t *bmp, uint32_t x, uint32_t y)
  346. {
  347. if ((x >= bmp->dib.width) || (y >= bmp->dib.height))
  348. return NULL;
  349. return &(bmp->pixels[x][y]);
  350. }
  351. bool
  352. bmp_set_pixel(bmpfile_t *bmp, uint32_t x, uint32_t y, rgb_pixel_t pixel)
  353. {
  354. if ((x >= bmp->dib.width) || (y >= bmp->dib.height))
  355. return FALSE;
  356. bmp->pixels[x][y] = pixel;
  357. return TRUE;
  358. }
  359. static bool
  360. _is_big_endian(void)
  361. {
  362. uint16_t value = 0x0001;
  363. return (*(uint8_t *)&value) != 0x01;
  364. }
  365. #define UINT16_SWAP_LE_BE_CONSTANT(val) \
  366. ((uint16_t) \
  367. ( \
  368. (uint16_t) ((uint16_t) (val) >> 8) | \
  369. (uint16_t) ((uint16_t) (val) << 8)))
  370. #define UINT32_SWAP_LE_BE_CONSTANT(val) \
  371. ((uint32_t) \
  372. ( \
  373. (((uint32_t) (val) & (uint32_t) 0x000000ffU) << 24) | \
  374. (((uint32_t) (val) & (uint32_t) 0x0000ff00U) << 8) | \
  375. (((uint32_t) (val) & (uint32_t) 0x00ff0000U) >> 8) | \
  376. (((uint32_t) (val) & (uint32_t) 0xff000000U) >> 24)))
  377. static void
  378. bmp_header_swap_endianess(bmp_header_t *header)
  379. {
  380. header->filesz = UINT32_SWAP_LE_BE_CONSTANT(header->filesz);
  381. header->creator1 = UINT16_SWAP_LE_BE_CONSTANT(header->creator1);
  382. header->creator2 = UINT16_SWAP_LE_BE_CONSTANT(header->creator2);
  383. header->offset = UINT32_SWAP_LE_BE_CONSTANT(header->offset);
  384. }
  385. static void
  386. bmp_dib_v3_header_swap_endianess(bmp_dib_v3_header_t *dib)
  387. {
  388. dib->header_sz = UINT32_SWAP_LE_BE_CONSTANT(dib->header_sz);
  389. dib->width = UINT32_SWAP_LE_BE_CONSTANT(dib->width);
  390. dib->height = UINT32_SWAP_LE_BE_CONSTANT(dib->height);
  391. dib->nplanes = UINT16_SWAP_LE_BE_CONSTANT(dib->nplanes);
  392. dib->depth = UINT16_SWAP_LE_BE_CONSTANT(dib->depth);
  393. dib->compress_type = UINT32_SWAP_LE_BE_CONSTANT(dib->compress_type);
  394. dib->bmp_bytesz = UINT32_SWAP_LE_BE_CONSTANT(dib->bmp_bytesz);
  395. dib->hres = UINT32_SWAP_LE_BE_CONSTANT(dib->hres);
  396. dib->vres = UINT32_SWAP_LE_BE_CONSTANT(dib->vres);
  397. dib->ncolors = UINT32_SWAP_LE_BE_CONSTANT(dib->ncolors);
  398. dib->nimpcolors = UINT32_SWAP_LE_BE_CONSTANT(dib->nimpcolors);
  399. }
  400. static void
  401. bmp_write_header(bmpfile_t *bmp, FILE *fp)
  402. {
  403. bmp_header_t header = bmp->header;
  404. if (_is_big_endian()) bmp_header_swap_endianess(&header);
  405. fwrite(header.magic, sizeof(header.magic), 1, fp);
  406. fwrite(&(header.filesz), sizeof(uint32_t), 1, fp);
  407. fwrite(&(header.creator1), sizeof(uint16_t), 1, fp);
  408. fwrite(&(header.creator2), sizeof(uint16_t), 1, fp);
  409. fwrite(&(header.offset), sizeof(uint32_t), 1, fp);
  410. }
  411. static void
  412. bmp_write_dib(bmpfile_t *bmp, FILE *fp)
  413. {
  414. bmp_dib_v3_header_t dib = bmp->dib;
  415. if (_is_big_endian()) bmp_dib_v3_header_swap_endianess(&dib);
  416. fwrite(&(dib.header_sz), sizeof(uint32_t), 1, fp);
  417. fwrite(&(dib.width), sizeof(uint32_t), 1, fp);
  418. fwrite(&(dib.height), sizeof(uint32_t), 1, fp);
  419. fwrite(&(dib.nplanes), sizeof(uint16_t), 1, fp);
  420. fwrite(&(dib.depth), sizeof(uint16_t), 1, fp);
  421. fwrite(&(dib.compress_type), sizeof(uint32_t), 1, fp);
  422. fwrite(&(dib.bmp_bytesz), sizeof(uint32_t), 1, fp);
  423. fwrite(&(dib.hres), sizeof(uint32_t), 1, fp);
  424. fwrite(&(dib.vres), sizeof(uint32_t), 1, fp);
  425. fwrite(&(dib.ncolors), sizeof(uint32_t), 1, fp);
  426. fwrite(&(dib.nimpcolors), sizeof(uint32_t), 1, fp);
  427. }
  428. static void
  429. bmp_write_palette(bmpfile_t *bmp, FILE *fp)
  430. {
  431. if (bmp->dib.depth == 1 || bmp->dib.depth == 4 || bmp->dib.depth == 8) {
  432. int i;
  433. for (i = 0; i < bmp->dib.ncolors; ++i)
  434. fwrite(&(bmp->colors[i]), sizeof(rgb_pixel_t), 1, fp);
  435. }
  436. else if (bmp->dib.depth == 16) { /* the bit masks, not palette */
  437. uint16_t red_mask = 63488; /* bits 1-5 */
  438. uint16_t green_mask = 2016; /* bits 6-11 */
  439. uint16_t blue_mask = 31; /* bits 12-16 */
  440. uint16_t zero_word = 0;
  441. if (_is_big_endian()) {
  442. red_mask = UINT16_SWAP_LE_BE_CONSTANT(red_mask);
  443. green_mask = UINT16_SWAP_LE_BE_CONSTANT(green_mask);
  444. blue_mask = UINT16_SWAP_LE_BE_CONSTANT(blue_mask);
  445. }
  446. fwrite(&red_mask, sizeof(uint16_t), 1, fp);
  447. fwrite(&zero_word, sizeof(uint16_t), 1, fp);
  448. fwrite(&green_mask, sizeof(uint16_t), 1, fp);
  449. fwrite(&zero_word, sizeof(uint16_t), 1, fp);
  450. fwrite(&blue_mask, sizeof(uint16_t), 1, fp);
  451. fwrite(&zero_word, sizeof(uint16_t), 1, fp);
  452. }
  453. }
  454. #define INT_SQUARE(v) ((int)((v) * (v)))
  455. static int
  456. find_closest_color(bmpfile_t *bmp, rgb_pixel_t pixel)
  457. {
  458. int i, best = 0;
  459. int best_match = 999999;
  460. for (i = 0; i < bmp->dib.ncolors; ++i) {
  461. rgb_pixel_t color = bmp->colors[i];
  462. int temp_match = INT_SQUARE(color.red - pixel.red) +
  463. INT_SQUARE(color.green - pixel.green) +
  464. INT_SQUARE(color.blue - pixel.blue);
  465. if (temp_match < best_match) {
  466. best = i;
  467. best_match = temp_match;
  468. }
  469. if (best_match < 1)
  470. break;
  471. }
  472. return best;
  473. }
  474. static void
  475. bmp_get_row_data_for_1(bmpfile_t *bmp, unsigned char *buf, size_t buf_len,
  476. uint32_t row)
  477. {
  478. uint8_t pos_weights[8] = {128, 64, 32, 16, 8, 4, 2, 1};
  479. uint32_t i = 0, j, k = 0;
  480. uint32_t index;
  481. if (bmp->dib.width > 8 * buf_len) return;
  482. while (i < bmp->dib.width) {
  483. for (j = 0, index = 0; j < 8 && i < bmp->dib.width; ++i, ++j)
  484. index += pos_weights[j] * find_closest_color(bmp, bmp->pixels[i][row]);
  485. buf[k++] = index & 0xff;
  486. }
  487. }
  488. static void
  489. bmp_get_row_data_for_4(bmpfile_t *bmp, unsigned char *buf, size_t buf_len,
  490. uint32_t row)
  491. {
  492. uint8_t pos_weights[2] = {16, 1};
  493. uint32_t i = 0, j, k = 0;
  494. uint32_t index;
  495. if (bmp->dib.width > 2 * buf_len) return;
  496. while (i < bmp->dib.width) {
  497. for (j = 0, index = 0; j < 2 && i < bmp->dib.width; ++i, ++j)
  498. index += pos_weights[j] * find_closest_color(bmp, bmp->pixels[i][row]);
  499. buf[k++] = index & 0xff;
  500. }
  501. }
  502. static void
  503. bmp_get_row_data_for_8(bmpfile_t *bmp, unsigned char *buf, size_t buf_len,
  504. uint32_t row)
  505. {
  506. int i;
  507. if (bmp->dib.width > buf_len) return;
  508. for (i = 0; i < bmp->dib.width; ++i)
  509. buf[i] = find_closest_color(bmp, bmp->pixels[i][row]);
  510. }
  511. static void
  512. bmp_get_row_data_for_24(bmpfile_t *bmp, unsigned char *buf, size_t buf_len,
  513. uint32_t row)
  514. {
  515. int i;
  516. if (bmp->dib.width * 3 > buf_len) return;
  517. for (i = 0; i < bmp->dib.width; ++i)
  518. memcpy(buf + 3 * i, (uint8_t *)&(bmp->pixels[i][row]), 3);
  519. }
  520. static void
  521. bmp_get_row_data_for_32(bmpfile_t *bmp, unsigned char *buf, size_t buf_len,
  522. uint32_t row)
  523. {
  524. int i;
  525. if (bmp->dib.width * 4 > buf_len) return;
  526. for (i = 0; i < bmp->dib.width; ++i)
  527. memcpy(buf + 4 * i, (uint8_t *)&(bmp->pixels[i][row]), 4);
  528. }
  529. bool
  530. bmp_save(bmpfile_t *bmp, const char *filename)
  531. {
  532. FILE *fp;
  533. int row;
  534. unsigned char *buf;
  535. /* Create the file */
  536. if ((fp = fopen(filename, "wb")) == NULL)
  537. return FALSE;
  538. /* Write the file */
  539. bmp_write_header(bmp, fp);
  540. bmp_write_dib(bmp, fp);
  541. bmp_write_palette(bmp, fp);
  542. if (bmp->dib.depth == 16) {
  543. uint32_t data_bytes = bmp->dib.width * 2;
  544. uint32_t padding_bytes = 4 - data_bytes % 4;
  545. for (row = bmp->dib.height - 1; row >= 0; --row) {
  546. int i;
  547. unsigned char zero_byte = 0;
  548. uint32_t write_number = 0;
  549. for (i = 0; write_number < data_bytes; ++i, write_number += 2) {
  550. uint16_t red = (uint16_t)(bmp->pixels[i][row].red / 8);
  551. uint16_t green = (uint16_t)(bmp->pixels[i][row].green / 4);
  552. uint16_t blue = (uint16_t)(bmp->pixels[i][row].blue / 8);
  553. uint16_t value = (red << 11) + (green << 5) + blue;
  554. if (_is_big_endian()) value = UINT16_SWAP_LE_BE_CONSTANT(value);
  555. fwrite(&value, sizeof(uint16_t), 1, fp);
  556. }
  557. for (write_number = 0; write_number < padding_bytes; ++write_number)
  558. fwrite(&zero_byte, 1, 1, fp);
  559. }
  560. }
  561. else {
  562. double bytes_per_pixel;
  563. int bytes_per_line;
  564. bytes_per_pixel = (bmp->dib.depth * 1.0) / 8.0;
  565. bytes_per_line = (int)ceil(bytes_per_pixel * bmp->dib.width);
  566. if (bytes_per_line % 4 != 0)
  567. bytes_per_line += 4 - bytes_per_line % 4;
  568. buf = malloc(bytes_per_line);
  569. for (row = bmp->dib.height - 1; row >= 0; --row) {
  570. memset(buf, 0, bytes_per_line);
  571. switch (bmp->dib.depth) {
  572. case 1:
  573. bmp_get_row_data_for_1(bmp, buf, bytes_per_line, row);
  574. break;
  575. case 4:
  576. bmp_get_row_data_for_4(bmp, buf, bytes_per_line, row);
  577. break;
  578. case 8:
  579. bmp_get_row_data_for_8(bmp, buf, bytes_per_line, row);
  580. break;
  581. case 24:
  582. bmp_get_row_data_for_24(bmp, buf, bytes_per_line, row);
  583. break;
  584. case 32:
  585. bmp_get_row_data_for_32(bmp, buf, bytes_per_line, row);
  586. break;
  587. }
  588. fwrite(buf, bytes_per_line, 1, fp);
  589. }
  590. free(buf);
  591. }
  592. fclose(fp);
  593. return TRUE;
  594. }