lv_png.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /**
  2. * @file lv_png.c
  3. *
  4. */
  5. /*********************
  6. * INCLUDES
  7. *********************/
  8. #define LV_LVGL_H_INCLUDE_SIMPLE
  9. #ifdef LV_LVGL_H_INCLUDE_SIMPLE
  10. #include <lvgl.h>
  11. #else
  12. #include <lvgl/lvgl.h>
  13. #endif
  14. #include "lv_png.h"
  15. #include "lodepng.h"
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. /*********************
  19. * DEFINES
  20. *********************/
  21. /**********************
  22. * TYPEDEFS
  23. **********************/
  24. /**********************
  25. * STATIC PROTOTYPES
  26. **********************/
  27. static lv_res_t decoder_info(struct _lv_img_decoder * decoder, const void * src, lv_img_header_t * header);
  28. static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
  29. static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
  30. static void convert_color_depth(uint8_t * img, uint32_t px_cnt);
  31. /**********************
  32. * STATIC VARIABLES
  33. **********************/
  34. /**********************
  35. * MACROS
  36. **********************/
  37. /**********************
  38. * GLOBAL FUNCTIONS
  39. **********************/
  40. /**
  41. * Register the PNG decoder functions in LittlevGL
  42. */
  43. void lv_png_init(void)
  44. {
  45. lv_img_decoder_t * dec = lv_img_decoder_create();
  46. lv_img_decoder_set_info_cb(dec, decoder_info);
  47. lv_img_decoder_set_open_cb(dec, decoder_open);
  48. lv_img_decoder_set_close_cb(dec, decoder_close);
  49. }
  50. /**********************
  51. * STATIC FUNCTIONS
  52. **********************/
  53. /**
  54. * Get info about a PNG image
  55. * @param src can be file name or pointer to a C array
  56. * @param header store the info here
  57. * @return LV_RES_OK: no error; LV_RES_INV: can't get the info
  58. */
  59. static lv_res_t decoder_info(struct _lv_img_decoder * decoder, const void * src, lv_img_header_t * header)
  60. {
  61. (void) decoder; /*Unused*/
  62. lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/
  63. /*If it's a PNG file...*/
  64. if(src_type == LV_IMG_SRC_FILE) {
  65. const char * fn = src;
  66. if(!strcmp(&fn[strlen(fn) - 3], "png")) { /*Check the extension*/
  67. /* Read the width and height from the file. They have a constant location:
  68. * [16..23]: width
  69. * [24..27]: height
  70. */
  71. uint32_t size[2];
  72. #if LV_PNG_USE_LV_FILESYSTEM
  73. lv_fs_file_t f;
  74. lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD);
  75. if(res != LV_FS_RES_OK) return -1;
  76. lv_fs_seek(&f, 16);
  77. uint32_t rn;
  78. lv_fs_read(&f, &size, 8, &rn);
  79. if(rn != 8) return LV_RES_INV;
  80. lv_fs_close(&f);
  81. #else
  82. FILE* file;
  83. file = fopen(fn, "rb" );
  84. if(!file) return LV_RES_INV;
  85. fseek(file, 16, SEEK_SET);
  86. size_t rn = fread(size, 1 , 8, file);
  87. fclose(file);
  88. if(rn != 8) return LV_RES_INV;
  89. #endif
  90. /*Save the data in the header*/
  91. header->always_zero = 0;
  92. header->cf = LV_IMG_CF_RAW_ALPHA;
  93. /*The width and height are stored in Big endian format so convert them to little endian*/
  94. header->w = (lv_coord_t) ((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8);
  95. header->h = (lv_coord_t) ((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8);
  96. return LV_RES_OK;
  97. }
  98. }
  99. /*If it's a PNG file in a C array...*/
  100. else if(src_type == LV_IMG_SRC_VARIABLE) {
  101. const lv_img_dsc_t * img_dsc = src;
  102. header->always_zero = 0;
  103. header->cf = img_dsc->header.cf; /*Save the color format*/
  104. header->w = img_dsc->header.w; /*Save the color width*/
  105. header->h = img_dsc->header.h; /*Save the color height*/
  106. return LV_RES_OK;
  107. }
  108. return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/
  109. }
  110. /**
  111. * Open a PNG image and return the decided image
  112. * @param src can be file name or pointer to a C array
  113. * @param style style of the image object (unused now but certain formats might use it)
  114. * @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed
  115. */
  116. static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
  117. {
  118. (void) decoder; /*Unused*/
  119. uint32_t error; /*For the return values of PNG decoder functions*/
  120. uint8_t * img_data = NULL;
  121. /*If it's a PNG file...*/
  122. if(dsc->src_type == LV_IMG_SRC_FILE) {
  123. const char * fn = dsc->src;
  124. if(!strcmp(&fn[strlen(fn) - 3], "png")) { /*Check the extension*/
  125. /*Load the PNG file into buffer. It's still compressed (not decoded)*/
  126. unsigned char * png_data; /*Pointer to the loaded data. Same as the original file just loaded into the RAM*/
  127. size_t png_data_size; /*Size of `png_data` in bytes*/
  128. error = lodepng_load_file(&png_data, &png_data_size, fn); /*Load the file*/
  129. if(error) {
  130. LV_LOG_ERROR("error %u: %s", error, lodepng_error_text(error));
  131. return LV_RES_INV;
  132. }
  133. /*Decode the PNG image*/
  134. uint32_t png_width; /*Will be the width of the decoded image*/
  135. uint32_t png_height; /*Will be the width of the decoded image*/
  136. /*Decode the loaded image in ARGB8888 */
  137. error = lodepng_decode32(&img_data, &png_width, &png_height, png_data, png_data_size);
  138. lv_mem_free(png_data); /*Free the loaded file*/
  139. if(error) {
  140. LV_LOG_ERROR("error %u: %s", error, lodepng_error_text(error));
  141. return LV_RES_INV;
  142. }
  143. /*Convert the image to the system's color depth*/
  144. convert_color_depth(img_data, png_width * png_height);
  145. dsc->img_data = img_data;
  146. return LV_RES_OK; /*The image is fully decoded. Return with its pointer*/
  147. }
  148. }
  149. /*If it's a PNG file in a C array...*/
  150. else if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
  151. const lv_img_dsc_t * img_dsc = dsc->src;
  152. uint32_t png_width; /*No used, just required by he decoder*/
  153. uint32_t png_height; /*No used, just required by he decoder*/
  154. /*Decode the image in ARGB8888 */
  155. error = lodepng_decode32(&img_data, &png_width, &png_height, img_dsc->data, img_dsc->data_size);
  156. if(error) {
  157. return LV_RES_INV;
  158. }
  159. /*Convert the image to the system's color depth*/
  160. convert_color_depth(img_data, png_width * png_height);
  161. dsc->img_data = img_data;
  162. return LV_RES_OK; /*Return with its pointer*/
  163. }
  164. return LV_RES_INV; /*If not returned earlier then it failed*/
  165. }
  166. /**
  167. * Free the allocated resources
  168. */
  169. static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
  170. {
  171. (void) decoder; /*Unused*/
  172. if(dsc->img_data) lv_mem_free((uint8_t *)dsc->img_data);
  173. }
  174. /**
  175. * If the display is not in 32 bit format (ARGB888) then covert the image to the current color depth
  176. * @param img the ARGB888 image
  177. * @param px_cnt number of pixels in `img`
  178. */
  179. static void convert_color_depth(uint8_t * img, uint32_t px_cnt)
  180. {
  181. #if LV_COLOR_DEPTH == 32
  182. lv_color32_t * img_argb = (lv_color32_t*)img;
  183. lv_color_t c;
  184. lv_color_t * img_c = (lv_color_t *) img;
  185. uint32_t i;
  186. for(i = 0; i < px_cnt; i++) {
  187. c = LV_COLOR_MAKE(img_argb[i].ch.red, img_argb[i].ch.green, img_argb[i].ch.blue);
  188. img_c[i].ch.red = c.ch.blue;
  189. img_c[i].ch.blue = c.ch.red;
  190. }
  191. #elif LV_COLOR_DEPTH == 16
  192. lv_color32_t * img_argb = (lv_color32_t*)img;
  193. lv_color_t c;
  194. uint32_t i;
  195. for(i = 0; i < px_cnt; i++) {
  196. c = LV_COLOR_MAKE(img_argb[i].ch.blue, img_argb[i].ch.green, img_argb[i].ch.red);
  197. img[i*3 + 2] = img_argb[i].ch.alpha;
  198. img[i*3 + 1] = c.full >> 8;
  199. img[i*3 + 0] = c.full & 0xFF;
  200. }
  201. #elif LV_COLOR_DEPTH == 8
  202. lv_color32_t * img_argb = (lv_color32_t*)img;
  203. lv_color_t c;
  204. uint32_t i;
  205. for(i = 0; i < px_cnt; i++) {
  206. c = LV_COLOR_MAKE(img_argb[i].red, img_argb[i].green, img_argb[i].blue);
  207. img[i*3 + 1] = img_argb[i].alpha;
  208. img[i*3 + 0] = c.full
  209. }
  210. #endif
  211. }