acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_bmp.c (7381B)

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