| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /**
- * @file lv_bmp.c
- *
- */
- /*********************
- * INCLUDES
- *********************/
- #define LV_LVGL_H_INCLUDE_SIMPLE 1
- #if LV_LVGL_H_INCLUDE_SIMPLE
- #include <lvgl.h>
- #else
- #include <lvgl/lvgl.h>
- #endif
- #include <string.h>
- /*********************
- * DEFINES
- *********************/
- /**********************
- * TYPEDEFS
- **********************/
- typedef struct {
- lv_fs_file_t f;
- unsigned int px_offset;
- int px_width;
- int px_height;
- unsigned int bpp;
- int row_size_bytes;
- } bmp_dsc_t;
- /**********************
- * STATIC PROTOTYPES
- **********************/
- static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header);
- static lv_res_t decoder_open(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
- static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc,
- lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf);
- static void decoder_close(lv_img_decoder_t * dec, lv_img_decoder_dsc_t * dsc);
- /**********************
- * STATIC VARIABLES
- **********************/
- /**********************
- * MACROS
- **********************/
- /**********************
- * GLOBAL FUNCTIONS
- **********************/
- void lv_bmp_init(void)
- {
- lv_img_decoder_t * dec = lv_img_decoder_create();
- lv_img_decoder_set_info_cb(dec, decoder_info);
- lv_img_decoder_set_open_cb(dec, decoder_open);
- lv_img_decoder_set_read_line_cb(dec, decoder_read_line);
- lv_img_decoder_set_close_cb(dec, decoder_close);
- }
- /**********************
- * STATIC FUNCTIONS
- **********************/
- /**
- * Get info about a PNG image
- * @param src can be file name or pointer to a C array
- * @param header store the info here
- * @return LV_RES_OK: no error; LV_RES_INV: can't get the info
- */
- static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
- {
- (void) decoder; /*Unused*/
- lv_img_src_t src_type = lv_img_src_get_type(src); /*Get the source type*/
- /*If it's a BMP file...*/
- if(src_type == LV_IMG_SRC_FILE) {
- const char * fn = src;
- if(!strcmp(&fn[strlen(fn) - 3], "bmp")) { /*Check the extension*/
- /*Save the data in the header*/
- lv_fs_file_t f;
- lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD);
- if(res != LV_FS_RES_OK) return LV_RES_INV;
- uint8_t headers[54];
- lv_fs_read(&f, headers, 54, NULL);
- uint32_t w;
- uint32_t h;
- memcpy(&w, headers + 18, 4);
- memcpy(&h, headers + 22, 4);
- header->w = w;
- header->h = h;
- header->always_zero = 0;
- lv_fs_close(&f);
- #if LV_COLOR_DEPTH == 32
- uint16_t bpp;
- memcpy(&bpp, headers + 28, 2);
- header->cf = bpp == 32 ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR;
- #else
- header->cf = LV_IMG_CF_TRUE_COLOR;
- #endif
- return LV_RES_OK;
- }
- }
- /* BMP file as data not supported for simplicity.
- * Convert them to LVGL compatible C arrays directly. */
- else if(src_type == LV_IMG_SRC_VARIABLE) {
- return LV_RES_INV;
- }
- return LV_RES_INV; /*If didn't succeeded earlier then it's an error*/
- }
- /**
- * Open a PNG image and return the decided image
- * @param src can be file name or pointer to a C array
- * @param style style of the image object (unused now but certain formats might use it)
- * @return pointer to the decoded image or `LV_IMG_DECODER_OPEN_FAIL` if failed
- */
- static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
- {
- (void) decoder; /*Unused*/
- /*If it's a PNG file...*/
- if(dsc->src_type == LV_IMG_SRC_FILE) {
- const char * fn = dsc->src;
- if(strcmp(&fn[strlen(fn) - 3], "bmp")) return LV_RES_INV; /*Check the extension*/
- bmp_dsc_t b;
- memset(&b, 0x00, sizeof(b));
- lv_fs_res_t res = lv_fs_open(&b.f, dsc->src, LV_FS_MODE_RD);
- if(res == LV_RES_OK) return LV_RES_INV;
- uint8_t header[54];
- lv_fs_read(&b.f, header, 54, NULL);
- if (0x42 != header[0] || 0x4d != header[1]) {
- return LV_RES_INV;
- }
- memcpy(&b.px_offset, header + 10, 4);
- memcpy(&b.px_width, header + 18, 4);
- memcpy(&b.px_height, header + 22, 4);
- memcpy(&b.bpp, header + 28, 2);
- b.row_size_bytes = (b.bpp * b.px_width) / 8;
- dsc->user_data = lv_mem_alloc(sizeof(bmp_dsc_t));
- LV_ASSERT_NULL(dsc->user_data);
- if(dsc->user_data == NULL) return LV_RES_INV;
- memcpy(dsc->user_data, &b, sizeof(b));
- dsc->img_data = NULL;
- return LV_RES_OK;
- }
- /* BMP file as data not supported for simplicity.
- * Convert them to LVGL compatible C arrays directly. */
- else if(dsc->src_type == LV_IMG_SRC_VARIABLE) {
- return LV_RES_INV;
- }
- return LV_RES_INV; /*If not returned earlier then it failed*/
- }
- static lv_res_t decoder_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc,
- lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf)
- {
- bmp_dsc_t * b = dsc->user_data;
- y = (b->px_height - 1) - y; /*BMP images are stored upside down*/
- uint32_t p = b->px_offset + b->row_size_bytes * y;
- p += x * (b->bpp / 8);
- lv_fs_seek(&b->f, p);
- lv_fs_read(&b->f, buf, len * (b->bpp / 8), NULL);
- #if LV_COLOR_DEPTH == 32
- if(b->bpp == 32) {
- lv_coord_t i;
- for(i = 0; i < len; i++) {
- uint8_t b0 = buf[i * 4];
- uint8_t b1 = buf[i * 4 + 1];
- uint8_t b2 = buf[i * 4 + 2];
- uint8_t b3 = buf[i * 4 + 3];
- lv_color32_t *c = (lv_color32_t*)&buf[i*4];
- c->ch.red = b2;
- c->ch.green = b1;
- c->ch.blue = b0;
- c->ch.alpha = b3;
- }
- }
- if(b->bpp == 24) {
- lv_coord_t i;
- for(i = len - 1; i >= 0; i--) {
- uint8_t * t = &buf[i * 3];
- lv_color32_t *c = (lv_color32_t*)&buf[i*4];
- c->ch.red = t[2];
- c->ch.green = t[1];
- c->ch.blue = t[0];
- c->ch.alpha = 0xff;
- }
- }
- #endif
- return LV_RES_OK;
- }
- /**
- * Free the allocated resources
- */
- static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
- {
- (void) decoder; /*Unused*/
- bmp_dsc_t * b = dsc->user_data;
- lv_fs_close(&b->f);
- lv_mem_free(dsc->user_data);
- }
|