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*/