/src/canvas/default/ftk_image_bmp_decoder.c

http://ftk.googlecode.com/ · C · 339 lines · 264 code · 43 blank · 32 comment · 41 complexity · 2abb7c6667aecdb0222c0d2708d21846 MD5 · raw file

  1. /*
  2. * File: ftk_image_bmp_decoder.h
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: bmp format image decoder.
  5. *
  6. * Copyright (c) 2009 - 2010 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2009-11-28 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include "ftk_mmap.h"
  31. #include "ftk_image_bmp_decoder.h"
  32. /**
  33. * http://atlc.sourceforge.net/bmp.html
  34. */
  35. static Ret ftk_image_bmp_decoder_match(FtkImageDecoder* thiz, const char* filename)
  36. {
  37. return_val_if_fail(filename != NULL, RET_FAIL);
  38. return (strstr(filename, ".bmp") != NULL) ? RET_OK : RET_FAIL;
  39. }
  40. static Ret ftk_image_bmp_copy32(FtkBitmap* bitmap, int compress, const unsigned char* data)
  41. {
  42. int x = 0;
  43. int y = 0;
  44. const unsigned char* src = data;
  45. int width = ftk_bitmap_width(bitmap);
  46. int height = ftk_bitmap_height(bitmap);
  47. FtkColor* bits = ftk_bitmap_lock(bitmap);
  48. for(y = 0; y < height; y++)
  49. {
  50. for(x = 0; x < width; x++, bits++)
  51. {
  52. bits->r = src[0];
  53. bits->g = src[1];
  54. bits->b = src[2];
  55. bits->a = 0xff;//src[3];
  56. src += 4;
  57. }
  58. }
  59. return RET_OK;
  60. }
  61. static Ret ftk_image_bmp_copy24(FtkBitmap* bitmap, int compress, const unsigned char* data)
  62. {
  63. int x = 0;
  64. int y = 0;
  65. const unsigned char* src = data;
  66. const unsigned char* lsrc = data;
  67. int width = ftk_bitmap_width(bitmap);
  68. int height = ftk_bitmap_height(bitmap);
  69. FtkColor* bits = ftk_bitmap_lock(bitmap);
  70. int line_delta = (width * 3 + 3) & 0xfffffffc;
  71. lsrc += line_delta * (height - 1);
  72. for(y = 0; y < height; y++)
  73. {
  74. src = lsrc;
  75. for(x = 0; x < width; x++, bits++)
  76. {
  77. bits->b = src[0];
  78. bits->g = src[1];
  79. bits->r = src[2];
  80. bits->a = 0xff;
  81. src += 3;
  82. }
  83. lsrc -= line_delta;
  84. }
  85. return RET_OK;
  86. }
  87. static Ret ftk_image_bmp_copy8(FtkBitmap* bitmap, int compress, FtkColor* palette, unsigned char* data)
  88. {
  89. int x = 0;
  90. int y = 0;
  91. unsigned char index = 0;
  92. const unsigned char* src = data;
  93. const unsigned char* lsrc = data;
  94. int width = ftk_bitmap_width(bitmap);
  95. int height = ftk_bitmap_height(bitmap);
  96. FtkColor* bits = ftk_bitmap_lock(bitmap);
  97. int line_delta = (width + 3) & 0xfffffffc;
  98. lsrc +=line_delta * (height - 1);
  99. for(y = 0; y < height; y++)
  100. {
  101. src = lsrc;
  102. for(x = 0; x < width; x++, bits++)
  103. {
  104. index = src[x];
  105. bits->r = palette[index].r;
  106. bits->g = palette[index].g;
  107. bits->b = palette[index].b;
  108. bits->a = 0xff;
  109. }
  110. lsrc -= line_delta;
  111. }
  112. return RET_OK;
  113. }
  114. static Ret ftk_image_bmp_copy4(FtkBitmap* bitmap, int compress, FtkColor* palette, unsigned char* data)
  115. {
  116. int x = 0;
  117. int y = 0;
  118. int r = 0;
  119. int w = 0;
  120. unsigned char index = 0;
  121. const unsigned char* src = data;
  122. const unsigned char* lsrc = data;
  123. int width = ftk_bitmap_width(bitmap);
  124. int height = ftk_bitmap_height(bitmap);
  125. FtkColor* bits = ftk_bitmap_lock(bitmap);
  126. int line_delta = (((width & 0x01) ? (width + 1) : width )/2 + 3) & 0xfffffffc;
  127. w = width>>1;
  128. r = width & 0x01;
  129. lsrc += line_delta * (height - 1);
  130. for(y = 0; y < height; y++)
  131. {
  132. src = lsrc;
  133. for(x = 0; x < w; x++)
  134. {
  135. index = (src[x] >> 4) & 0x0f;
  136. bits->r = palette[index].r;
  137. bits->g = palette[index].g;
  138. bits->b = palette[index].b;
  139. bits->a = 0xff;
  140. bits++;
  141. index = src[x] & 0x0f;
  142. bits->r = palette[index].r;
  143. bits->g = palette[index].g;
  144. bits->b = palette[index].b;
  145. bits->a = 0xff;
  146. bits++;
  147. }
  148. if(r)
  149. {
  150. index = (src[x] >> 4) & 0x0f;
  151. bits->r = palette[index].r;
  152. bits->g = palette[index].g;
  153. bits->b = palette[index].b;
  154. bits->a = 0xff;
  155. bits++;
  156. }
  157. lsrc -= line_delta;
  158. }
  159. return RET_OK;
  160. }
  161. #define SET_COLOR_1BIT(bit, color) if(bit) {color->r=color->g=color->b=0xff;color->a=0xff;}\
  162. else{color->r=color->g=color->b=0x00;color->a=0xff;}
  163. static Ret ftk_image_bmp_copy1(FtkBitmap* bitmap, int compress, FtkColor* palette, unsigned char* data)
  164. {
  165. int x = 0;
  166. int y = 0;
  167. int r = 0;
  168. int w = 0;
  169. unsigned char c = 0;
  170. const unsigned char* src = data;
  171. const unsigned char* lsrc = data;
  172. int width = ftk_bitmap_width(bitmap);
  173. int height = ftk_bitmap_height(bitmap);
  174. FtkColor* bits = ftk_bitmap_lock(bitmap);
  175. int line_delta = (width/8 + 3) & 0xfffffffc;
  176. w = (width+7)>>3;
  177. r = width % 8;
  178. lsrc += line_delta * (height - 1);
  179. for(y = 0; y < height; y++)
  180. {
  181. src = lsrc;
  182. for(x = 0; x < w; x++)
  183. {
  184. c = src[x];
  185. if(x == (w - 1))
  186. {
  187. SET_COLOR_1BIT(c & 0x80, bits);bits++; if(r == 1) break;
  188. SET_COLOR_1BIT(c & 0x40, bits);bits++; if(r == 2) break;
  189. SET_COLOR_1BIT(c & 0x20, bits);bits++; if(r == 3) break;
  190. SET_COLOR_1BIT(c & 0x10, bits);bits++; if(r == 4) break;
  191. SET_COLOR_1BIT(c & 0x08 , bits);bits++; if(r == 5) break;
  192. SET_COLOR_1BIT(c & 0x04, bits);bits++; if(r == 6) break;
  193. SET_COLOR_1BIT(c & 0x02, bits);bits++; if(r == 7) break;
  194. SET_COLOR_1BIT(c & 0x01, bits);bits++;
  195. }
  196. else
  197. {
  198. SET_COLOR_1BIT(c & 0x80, bits);bits++;
  199. SET_COLOR_1BIT(c & 0x40, bits);bits++;
  200. SET_COLOR_1BIT(c & 0x20, bits);bits++;
  201. SET_COLOR_1BIT(c & 0x10, bits);bits++;
  202. SET_COLOR_1BIT(c & 0x08 , bits);bits++;
  203. SET_COLOR_1BIT(c & 0x04, bits);bits++;
  204. SET_COLOR_1BIT(c & 0x02, bits);bits++;
  205. SET_COLOR_1BIT(c & 0x01, bits);bits++;
  206. }
  207. }
  208. lsrc -= line_delta;
  209. }
  210. return RET_OK;
  211. }
  212. static FtkBitmap* load_bmp (const char *filename)
  213. {
  214. size_t bpp = 0;
  215. size_t width = 0;
  216. size_t height = 0;
  217. size_t doffset = 0;
  218. int compress = 0;
  219. FtkColor bg = {0};
  220. FtkBitmap* bitmap = NULL;
  221. FtkColor* palette = NULL;
  222. unsigned char* src = NULL;
  223. unsigned char* data = NULL;
  224. FtkMmap* m = ftk_mmap_create(filename, 0, -1);
  225. return_val_if_fail(m != NULL, NULL);
  226. data = (unsigned char*)ftk_mmap_data(m);
  227. if(data[0] != 'B' || data[1] != 'M')
  228. {
  229. ftk_mmap_destroy(m);
  230. return NULL;
  231. }
  232. bg.a = 0xff;
  233. doffset = *(unsigned int*)(data + 0x000a);
  234. width = *(unsigned int*)(data + 0x0012);
  235. height = *(unsigned int*)(data + 0x0016);
  236. bpp = *(unsigned short*)(data + 0x001c);
  237. compress = *(unsigned int*)(data + 0x001e);
  238. palette = (FtkColor*)(data + 0x0036);
  239. src = data + doffset;
  240. bitmap = ftk_bitmap_create(width, height, bg);
  241. switch(bpp)
  242. {
  243. case 32:
  244. {
  245. ftk_image_bmp_copy32(bitmap, compress, src);
  246. break;
  247. }
  248. case 24:
  249. {
  250. ftk_image_bmp_copy24(bitmap, compress, src);
  251. break;
  252. }
  253. case 8:
  254. {
  255. ftk_image_bmp_copy8(bitmap, compress, palette, src);
  256. break;
  257. }
  258. case 4:
  259. {
  260. ftk_image_bmp_copy4(bitmap, compress, palette, src);
  261. break;
  262. }
  263. case 1:
  264. {
  265. ftk_image_bmp_copy1(bitmap, compress, palette, src);
  266. break;
  267. }
  268. default:break;
  269. }
  270. ftk_mmap_destroy(m);
  271. return bitmap;
  272. }
  273. static FtkBitmap* ftk_image_bmp_decoder_decode(FtkImageDecoder* thiz, const char* filename)
  274. {
  275. return_val_if_fail(ftk_image_bmp_decoder_match(thiz, filename) == RET_OK, NULL);
  276. return load_bmp(filename);
  277. }
  278. static void ftk_image_bmp_decoder_destroy(FtkImageDecoder* thiz)
  279. {
  280. if(thiz != NULL)
  281. {
  282. FTK_ZFREE(thiz, sizeof(thiz));
  283. }
  284. return;
  285. }
  286. FtkImageDecoder* ftk_image_bmp_decoder_create(void)
  287. {
  288. FtkImageDecoder* thiz = (FtkImageDecoder*)FTK_ZALLOC(sizeof(FtkImageDecoder));
  289. if(thiz != NULL)
  290. {
  291. thiz->match = ftk_image_bmp_decoder_match;
  292. thiz->decode = ftk_image_bmp_decoder_decode;
  293. thiz->destroy = ftk_image_bmp_decoder_destroy;
  294. }
  295. return thiz;
  296. }