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