/src/canvas/default/ftk_image_png_decoder.c

http://ftk.googlecode.com/ · C · 283 lines · 219 code · 34 blank · 30 comment · 41 complexity · cc74fd30e7c9c590347680629d9a8a81 MD5 · raw file

  1. /*
  2. * File: ftk_image_png_decoder.c
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: png 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-10-03 Li XianJing <xianjimli@hotmail.com> created
  28. * 2010-10-02 Jiao JinXing <jiaojinxing1987@gmail.com> add rt-thread support.
  29. *
  30. */
  31. #define PNG_SKIP_SETJMP_CHECK
  32. #include "ftk_log.h"
  33. #include "ftk_image_png_decoder.h"
  34. #include <png.h>
  35. #ifdef RT_THREAD
  36. static void ftk_image_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
  37. {
  38. int fd = (int)png_ptr->io_ptr;
  39. read(fd, data, length);
  40. }
  41. static png_voidp ftk_png_malloc(png_structp png_ptr, png_size_t size)
  42. {
  43. return malloc(size);
  44. }
  45. static void ftk_png_free(png_structp png_ptr, png_voidp ptr)
  46. {
  47. free(ptr);
  48. }
  49. #endif
  50. static Ret ftk_image_png_decoder_match(FtkImageDecoder* thiz, const char* filename)
  51. {
  52. return_val_if_fail(filename != NULL, RET_FAIL);
  53. return (strstr(filename, ".png") != NULL) ? RET_OK : RET_FAIL;
  54. }
  55. static FtkBitmap* load_png (const char *filename)
  56. {
  57. int x = 0;
  58. int y = 0;
  59. int w = 0;
  60. int h = 0;
  61. #ifndef RT_THREAD
  62. FILE *fp = NULL;
  63. #else
  64. int fd = -1;
  65. #endif
  66. int passes_nr = 0;
  67. FtkColor* dst = NULL;
  68. unsigned char* src = NULL;
  69. FtkBitmap* bitmap = NULL;
  70. FtkColor bg = {0};
  71. png_structp png_ptr = NULL;
  72. png_infop info_ptr = NULL;
  73. png_bytep * row_pointers = NULL;
  74. bg.a = 0xff;
  75. #ifndef RT_THREAD
  76. if ((fp = fopen (filename, "rb")) == NULL)
  77. {
  78. ftk_logd("%s: open %s failed.\n", __func__, filename);
  79. return NULL;
  80. }
  81. if((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
  82. {
  83. fclose(fp);
  84. return NULL;
  85. }
  86. if((info_ptr = png_create_info_struct(png_ptr)) == NULL)
  87. {
  88. fclose(fp);
  89. return NULL;
  90. }
  91. #else
  92. if ((fd = open (filename, O_RDONLY, 0)) < 0)
  93. {
  94. ftk_logd("%s: open %s failed.\n", __func__, filename);
  95. return NULL;
  96. }
  97. if((png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, NULL, ftk_png_malloc, ftk_png_free)) == NULL)
  98. {
  99. close(fd);
  100. return NULL;
  101. }
  102. if((info_ptr = png_create_info_struct(png_ptr)) == NULL)
  103. {
  104. close(fd);
  105. return NULL;
  106. }
  107. #endif
  108. #ifdef PNG_SETJMP_SUPPORTED
  109. setjmp(png_jmpbuf(png_ptr));
  110. #endif
  111. #ifndef RT_THREAD
  112. png_init_io(png_ptr, fp);
  113. #else
  114. png_set_read_fn(png_ptr, (void *)fd, ftk_image_png_read_data);
  115. #endif
  116. memset(info_ptr, 0x00, sizeof(*info_ptr));
  117. png_read_info(png_ptr, info_ptr);
  118. w = info_ptr->width;
  119. h = info_ptr->height;
  120. passes_nr = png_set_interlace_handling(png_ptr);
  121. png_read_update_info(png_ptr, info_ptr);
  122. #ifdef PNG_SETJMP_SUPPORTED
  123. setjmp(png_jmpbuf(png_ptr));
  124. #endif
  125. row_pointers = (png_bytep*) FTK_ZALLOC(h * sizeof(png_bytep));
  126. for (y=0; y< h; y++)
  127. {
  128. row_pointers[y] = (png_byte*) FTK_ZALLOC(info_ptr->rowbytes);
  129. }
  130. png_read_image(png_ptr, row_pointers);
  131. bitmap = ftk_bitmap_create(w, h, bg);
  132. dst = ftk_bitmap_lock(bitmap);
  133. if (info_ptr->color_type == PNG_COLOR_TYPE_RGBA)
  134. {
  135. for(y = 0; y < h; y++)
  136. {
  137. src = row_pointers[y];
  138. for(x = 0; x < w; x++)
  139. {
  140. if(src[3])
  141. {
  142. dst->r = src[0];
  143. dst->g = src[1];
  144. dst->b = src[2];
  145. dst->a = src[3];
  146. }
  147. else
  148. {
  149. dst->r = 0xff;
  150. dst->g = 0xff;
  151. dst->b = 0xff;
  152. dst->a = 0;
  153. }
  154. src +=4;
  155. dst++;
  156. }
  157. }
  158. }
  159. else if(info_ptr->color_type == PNG_COLOR_TYPE_RGB)
  160. {
  161. if(0 == info_ptr->num_trans)
  162. {
  163. for(y = 0; y < h; y++)
  164. {
  165. src = row_pointers[y];
  166. for(x = 0; x < w; x++)
  167. {
  168. dst->r = src[0];
  169. dst->g = src[1];
  170. dst->b = src[2];
  171. dst->a = 0xff;
  172. src += 3;
  173. dst++;
  174. }
  175. }
  176. }
  177. else
  178. {
  179. #if PNG_LIBPNG_VER > 10399
  180. png_byte red = png_ptr->trans_color.red & 0xff;
  181. png_byte green = png_ptr->trans_color.green & 0xff;
  182. png_byte blue = png_ptr->trans_color.blue & 0xff;
  183. #else
  184. png_byte red = png_ptr->trans_values.red & 0xff;
  185. png_byte green = png_ptr->trans_values.green & 0xff;
  186. png_byte blue = png_ptr->trans_values.blue & 0xff;
  187. #endif
  188. for(y = 0; y < h; y++)
  189. {
  190. src = row_pointers[y];
  191. for(x = 0; x < w; x++)
  192. {
  193. if(src[0] == red && src[1] == green && src[2] == blue)
  194. {
  195. dst->a = 0;
  196. }
  197. else
  198. {
  199. dst->a = 0xff;
  200. }
  201. dst->r = src[0];
  202. dst->g = src[1];
  203. dst->b = src[2];
  204. src += 3;
  205. dst++;
  206. }
  207. }
  208. }
  209. }
  210. else
  211. {
  212. assert(!"not supported.");
  213. }
  214. for(y = 0; y < h; y++)
  215. {
  216. FTK_FREE(row_pointers[y]);
  217. }
  218. FTK_FREE(row_pointers);
  219. png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  220. #ifndef RT_THREAD
  221. fclose(fp);
  222. #else
  223. close(fd);
  224. #endif
  225. return bitmap;
  226. }
  227. static FtkBitmap* ftk_image_png_decoder_decode(FtkImageDecoder* thiz, const char* filename)
  228. {
  229. return_val_if_fail(ftk_image_png_decoder_match(thiz, filename) == RET_OK, NULL);
  230. return load_png(filename);
  231. }
  232. static void ftk_image_png_decoder_destroy(FtkImageDecoder* thiz)
  233. {
  234. if(thiz != NULL)
  235. {
  236. FTK_ZFREE(thiz, sizeof(thiz));
  237. }
  238. }
  239. FtkImageDecoder* ftk_image_png_decoder_create(void)
  240. {
  241. FtkImageDecoder* thiz = (FtkImageDecoder*)FTK_ZALLOC(sizeof(FtkImageDecoder));
  242. if(thiz != NULL)
  243. {
  244. thiz->match = ftk_image_png_decoder_match;
  245. thiz->decode = ftk_image_png_decoder_decode;
  246. thiz->destroy = ftk_image_png_decoder_destroy;
  247. }
  248. return thiz;
  249. }