lv_bmp.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /**
  2. * @file lv_bmp.c
  3. *
  4. */
  5. /*********************
  6. * INCLUDES
  7. *********************/
  8. #define LV_LVGL_H_INCLUDE_SIMPLE 1
  9. #if LV_LVGL_H_INCLUDE_SIMPLE
  10. #include <lvgl.h>
  11. #else
  12. #include <lvgl/lvgl.h>
  13. #endif
  14. #include <string.h>
  15. /*********************
  16. * DEFINES
  17. *********************/
  18. /**********************
  19. * TYPEDEFS
  20. **********************/
  21. typedef struct {
  22. lv_fs_file_t f;
  23. unsigned int px_offset;
  24. int px_width;
  25. int px_height;
  26. unsigned int bpp;
  27. int row_size_bytes;
  28. } bmp_dsc_t;
  29. /**********************
  30. * STATIC PROTOTYPES
  31. **********************/
  32. static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header);
  33. static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
  34. static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc,
  35. lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf);
  36. static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
  37. /**********************
  38. * STATIC VARIABLES
  39. **********************/
  40. /**********************
  41. * MACROS
  42. **********************/
  43. /**********************
  44. * GLOBAL FUNCTIONS
  45. **********************/
  46. void lv_bmp_init(void)
  47. {
  48. lv_img_decoder_t * dec = lv_img_decoder_create();
  49. lv_img_decoder_set_info_cb(dec, decoder_info);
  50. lv_img_decoder_set_open_cb(dec, decoder_open);
  51. lv_img_decoder_set_read_line_cb(dec, decoder_read_line);
  52. lv_img_decoder_set_close_cb(dec, decoder_close);
  53. }
  54. /**********************
  55. * STATIC FUNCTIONS
  56. **********************/
  57. /**
  58. * Get info about a PNG image
  59. * @param src can be file name or pointer to a C array
  60. * @param header store the info here
  61. * @return LV_RES_OK: no error; LV_RES_INV: can't get the info
  62. */
  63. static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
  64. {
  65. (void) decoder; /*Unused*/
  66. lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/
  67. /*If it's a BMP file...*/
  68. if(src_type == LV_IMG_SRC_FILE) {
  69. const char * fn = src;
  70. if(!strcmp(&fn[strlen(fn) - 3], "bmp")) { /*Check the extension*/
  71. /*Save the data in the header*/
  72. lv_fs_file_t f;
  73. lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD);
  74. if(res != LV_FS_RES_OK) return LV_RES_INV;
  75. uint8_t headers[54];
  76. lv_fs_read(&f, headers, 54, NULL);
  77. uint32_t w;
  78. uint32_t h;
  79. memcpy(&w, headers + 18, 4);
  80. memcpy(&h, headers + 22, 4);
  81. header->w = w;
  82. header->h = h;
  83. header->always_zero = 0;
  84. lv_fs_close(&f);
  85. #if LV_COLOR_DEPTH == 32
  86. uint16_t bpp;
  87. memcpy(&bpp, headers + 28, 2);
  88. header->cf = bpp == 32 ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR;
  89. #else
  90. header->cf = LV_IMG_CF_TRUE_COLOR;
  91. #endif
  92. return LV_RES_OK;
  93. }
  94. }
  95. /* BMP file as data not supported for simplicity.
  96. * Convert them to LVGL compatible C arrays directly. */
  97. else if(src_type == LV_IMG_SRC_VARIABLE) {
  98. return LV_RES_INV;
  99. }
  100. return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/
  101. }
  102. /**
  103. * Open a PNG image and return the decided image
  104. * @param src can be file name or pointer to a C array
  105. * @param style style of the image object (unused now but certain formats might use it)
  106. * @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed
  107. */
  108. static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
  109. {
  110. (void) decoder; /*Unused*/
  111. /*If it's a PNG file...*/
  112. if(dsc->src_type == LV_IMG_SRC_FILE) {
  113. const char * fn = dsc->src;
  114. if(strcmp(&fn[strlen(fn) - 3], "bmp")) return LV_RES_INV; /*Check the extension*/
  115. bmp_dsc_t b;
  116. memset(&b, 0x00, sizeof(b));
  117. lv_fs_res_t res = lv_fs_open(&b.f, dsc->src, LV_FS_MODE_RD);
  118. if(res == LV_RES_OK) return LV_RES_INV;
  119. uint8_t header[54];
  120. lv_fs_read(&b.f, header, 54, NULL);
  121. if (0x42 != header[0] || 0x4d != header[1]) {
  122. return LV_RES_INV;
  123. }
  124. memcpy(&b.px_offset, header + 10, 4);
  125. memcpy(&b.px_width, header + 18, 4);
  126. memcpy(&b.px_height, header + 22, 4);
  127. memcpy(&b.bpp, header + 28, 2);
  128. b.row_size_bytes = (b.bpp * b.px_width) / 8;
  129. dsc->user_data = lv_mem_alloc(sizeof(bmp_dsc_t));
  130. LV_ASSERT_NULL(dsc->user_data);
  131. if(dsc->user_data == NULL) return LV_RES_INV;
  132. memcpy(dsc->user_data, &b, sizeof(b));
  133. dsc->img_data = NULL;
  134. return LV_RES_OK;
  135. }
  136. /* BMP file as data not supported for simplicity.
  137. * Convert them to LVGL compatible C arrays directly. */
  138. else if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
  139. return LV_RES_INV;
  140. }
  141. return LV_RES_INV; /*If not returned earlier then it failed*/
  142. }
  143. static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc,
  144. lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf)
  145. {
  146. bmp_dsc_t * b = dsc->user_data;
  147. y = (b->px_height - 1) - y; /*BMP images are stored upside down*/
  148. uint32_t p = b->px_offset + b->row_size_bytes * y;
  149. p += x * (b->bpp / 8);
  150. lv_fs_seek(&b->f, p);
  151. lv_fs_read(&b->f, buf, len * (b->bpp / 8), NULL);
  152. #if LV_COLOR_DEPTH == 32
  153. if(b->bpp == 32) {
  154. lv_coord_t i;
  155. for(i = 0; i < len; i++) {
  156. uint8_t b0 = buf[i * 4];
  157. uint8_t b1 = buf[i * 4 + 1];
  158. uint8_t b2 = buf[i * 4 + 2];
  159. uint8_t b3 = buf[i * 4 + 3];
  160. lv_color32_t *c = (lv_color32_t*)&buf[i*4];
  161. c->ch.red = b2;
  162. c->ch.green = b1;
  163. c->ch.blue = b0;
  164. c->ch.alpha = b3;
  165. }
  166. }
  167. if(b->bpp == 24) {
  168. lv_coord_t i;
  169. for(i = len - 1; i >= 0; i--) {
  170. uint8_t * t = &buf[i * 3];
  171. lv_color32_t *c = (lv_color32_t*)&buf[i*4];
  172. c->ch.red = t[2];
  173. c->ch.green = t[1];
  174. c->ch.blue = t[0];
  175. c->ch.alpha = 0xff;
  176. }
  177. }
  178. #endif
  179. return LV_RES_OK;
  180. }
  181. /**
  182. * Free the allocated resources
  183. */
  184. static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
  185. {
  186. (void) decoder; /*Unused*/
  187. bmp_dsc_t * b = dsc->user_data;
  188. lv_fs_close(&b->f);
  189. lv_mem_free(dsc->user_data);
  190. }