image_png.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #include "libpng/png.h"
  2. #include <rtthread.h>
  3. #include <rtgui/image_png.h>
  4. #include <rtgui/rtgui_system.h>
  5. #define PNG_MAGIC_LEN 8
  6. struct rtgui_image_png
  7. {
  8. rt_bool_t is_loaded;
  9. struct rtgui_filerw* filerw;
  10. /* png image information */
  11. png_structp png_ptr;
  12. png_infop info_ptr;
  13. rt_uint8_t *pixels;
  14. rt_uint8_t *line_pixels;
  15. };
  16. static rt_bool_t rtgui_image_png_check(struct rtgui_filerw* file);
  17. static rt_bool_t rtgui_image_png_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
  18. static void rtgui_image_png_unload(struct rtgui_image* image);
  19. static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
  20. struct rtgui_image_engine rtgui_image_png_engine =
  21. {
  22. "png",
  23. { RT_NULL },
  24. rtgui_image_png_check,
  25. rtgui_image_png_load,
  26. rtgui_image_png_unload,
  27. rtgui_image_png_blit
  28. };
  29. static void rtgui_image_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
  30. {
  31. struct rtgui_filerw* filerw = (struct rtgui_filerw*)png_ptr->io_ptr;
  32. rtgui_filerw_read(filerw, data, length, 1);
  33. }
  34. static rt_bool_t rtgui_image_png_process(png_structp png_ptr, png_infop info_ptr, struct rtgui_image_png* png)
  35. {
  36. int x, y;
  37. png_bytep row;
  38. png_bytep data;
  39. rtgui_color_t *ptr;
  40. row = (png_bytep) rtgui_malloc (png_get_rowbytes(png_ptr, info_ptr));
  41. if (row == RT_NULL) return RT_FALSE;
  42. ptr = (rtgui_color_t *)png->pixels;
  43. switch (info_ptr->color_type)
  44. {
  45. case PNG_COLOR_TYPE_RGBA:
  46. for (y = 0; y < info_ptr->height; y++)
  47. {
  48. png_read_row(png_ptr, row, png_bytep_NULL);
  49. for (x = 0; x < info_ptr->width; x++)
  50. {
  51. data = &(row[x * 4]);
  52. ptr[x+y*info_ptr->width] = RTGUI_ARGB((255 - data[3]), data[0], data[1], data[2]);
  53. }
  54. }
  55. break;
  56. case PNG_COLOR_TYPE_PALETTE:
  57. for (y = 0; y < info_ptr->height; y++)
  58. {
  59. png_read_row(png_ptr, row, png_bytep_NULL);
  60. for (x = 0; x < info_ptr->width; x++)
  61. {
  62. data = &(row[x]);
  63. ptr[x] = RTGUI_ARGB(0, info_ptr->palette[data[0]].red,
  64. info_ptr->palette[data[0]].green,
  65. info_ptr->palette[data[0]].blue);
  66. }
  67. }
  68. default:
  69. break;
  70. };
  71. rtgui_free(row);
  72. return RT_TRUE;
  73. }
  74. static rt_bool_t rtgui_image_png_check(struct rtgui_filerw* file)
  75. {
  76. int start;
  77. rt_bool_t is_PNG;
  78. rt_uint8_t magic[4];
  79. if ( !file ) return 0;
  80. start = rtgui_filerw_tell(file);
  81. /* move to the begining of file */
  82. rtgui_filerw_seek(file, 0, SEEK_SET);
  83. is_PNG = RT_FALSE;
  84. if ( rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic) )
  85. {
  86. if ( magic[0] == 0x89 &&
  87. magic[1] == 'P' &&
  88. magic[2] == 'N' &&
  89. magic[3] == 'G' )
  90. {
  91. is_PNG = RT_TRUE;
  92. }
  93. }
  94. rtgui_filerw_seek(file, start, SEEK_SET);
  95. return(is_PNG);
  96. }
  97. static rt_bool_t rtgui_image_png_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
  98. {
  99. png_uint_32 width;
  100. png_uint_32 height;
  101. int bit_depth;
  102. int color_type;
  103. double gamma;
  104. struct rtgui_image_png* png;
  105. png = (struct rtgui_image_png*) rtgui_malloc(sizeof(struct rtgui_image_png));
  106. png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  107. if (png->png_ptr == RT_NULL)
  108. {
  109. rtgui_free(png);
  110. return RT_FALSE;
  111. }
  112. png->info_ptr = png_create_info_struct(png->png_ptr);
  113. if (png->info_ptr == RT_NULL)
  114. {
  115. png_destroy_read_struct(&png->png_ptr, NULL, NULL);
  116. rtgui_free(png);
  117. return RT_FALSE;
  118. }
  119. png->filerw = file;
  120. png_set_read_fn (png->png_ptr, png->filerw, rtgui_image_png_read_data);
  121. png_read_info(png->png_ptr, png->info_ptr);
  122. png_get_IHDR(png->png_ptr, png->info_ptr, &width, &height, &bit_depth,
  123. &color_type, NULL, NULL, NULL);
  124. /* set image information */
  125. image->w = width; image->h = height;
  126. image->engine = &rtgui_image_png_engine;
  127. image->data = png;
  128. if (bit_depth == 16)
  129. png_set_strip_16(png->png_ptr);
  130. if (color_type == PNG_COLOR_TYPE_PALETTE)
  131. png_set_expand(png->png_ptr);
  132. if (bit_depth < 8)
  133. png_set_expand(png->png_ptr);
  134. if (png_get_valid(png->png_ptr, png->info_ptr, PNG_INFO_tRNS))
  135. png_set_expand(png->png_ptr);
  136. if (color_type == PNG_COLOR_TYPE_GRAY ||
  137. color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  138. png_set_gray_to_rgb(png->png_ptr);
  139. /* Ignore background color */
  140. /* set gamma conversion */
  141. if (png_get_gAMA(png->png_ptr, png->info_ptr, &gamma))
  142. png_set_gamma(png->png_ptr, (double)2.2, gamma);
  143. png_read_update_info(png->png_ptr, png->info_ptr);
  144. if (load == RT_TRUE)
  145. {
  146. /* load all pixels */
  147. png->pixels = rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t));
  148. png->line_pixels = RT_NULL;
  149. rtgui_image_png_process(png->png_ptr, png->info_ptr, png);
  150. }
  151. else
  152. {
  153. png->line_pixels = rtgui_malloc(image->w * sizeof(rtgui_color_t));
  154. png->pixels = RT_NULL;
  155. }
  156. return RT_TRUE;
  157. }
  158. static void rtgui_image_png_unload(struct rtgui_image* image)
  159. {
  160. struct rtgui_image_png* png;
  161. if (image != RT_NULL)
  162. {
  163. png = (struct rtgui_image_png*) image->data;
  164. png_read_end(png->png_ptr, NULL);
  165. /* destroy png struct */
  166. png_destroy_info_struct(png->png_ptr, &png->info_ptr);
  167. png_destroy_read_struct(&png->png_ptr, NULL, NULL);
  168. if (png->pixels != RT_NULL) rtgui_free(png->pixels);
  169. if (png->line_pixels != RT_NULL) rtgui_free(png->line_pixels);
  170. /* release data */
  171. rtgui_free(png);
  172. }
  173. }
  174. static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect)
  175. {
  176. rt_uint16_t x, y;
  177. rtgui_color_t* ptr;
  178. rtgui_color_t foreground;
  179. struct rtgui_image_png* png;
  180. RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
  181. RT_ASSERT(image->data != RT_NULL);
  182. png = (struct rtgui_image_png*) image->data;
  183. ptr = png->pixels;
  184. /* save foreground color */
  185. foreground = rtgui_dc_get_color(dc);
  186. /* draw each point within dc */
  187. for (y = 0; y < image->h; y ++)
  188. {
  189. for (x = 0; x < image->w; x++)
  190. {
  191. /* not alpha */
  192. if ((*ptr >> 24) != 255)
  193. {
  194. rtgui_dc_set_color(dc, *ptr);
  195. rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1);
  196. }
  197. /* move to next color buffer */
  198. ptr ++;
  199. }
  200. }
  201. /* restore foreground */
  202. rtgui_dc_set_color(dc, foreground);
  203. }
  204. void rtgui_image_png_init()
  205. {
  206. /* register jpeg on image system */
  207. rtgui_image_register_engine(&rtgui_image_png_engine);
  208. }