1 /**
2 * @file lv_image_decoder.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_image_decoder_private.h"
10 #include "../misc/lv_assert.h"
11 #include "../draw/lv_draw_image.h"
12 #include "../misc/lv_ll.h"
13 #include "../stdlib/lv_string.h"
14 #include "../core/lv_global.h"
15
16 /*********************
17 * DEFINES
18 *********************/
19 #define img_decoder_ll_p &(LV_GLOBAL_DEFAULT()->img_decoder_ll)
20 #define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache)
21 #define img_header_cache_p (LV_GLOBAL_DEFAULT()->img_header_cache)
22 #define image_cache_draw_buf_handlers &(LV_GLOBAL_DEFAULT()->image_cache_draw_buf_handlers)
23
24 /**********************
25 * TYPEDEFS
26 **********************/
27
28 /**********************
29 * STATIC PROTOTYPES
30 **********************/
31
32 static uint32_t img_width_to_stride(lv_image_header_t * header);
33
34 /**
35 * Get the header info of an image source, and return the a pointer to the decoder that can open it.
36 * @param dsc Image descriptor containing the source and type of the image and other info.
37 * @param header The header of the image
38 * @return The decoder that can open the image source or NULL if not found (or can't open it).
39 */
40 static lv_image_decoder_t * image_decoder_get_info(lv_image_decoder_dsc_t * dsc, lv_image_header_t * header);
41
42 static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
43
44 /**********************
45 * STATIC VARIABLES
46 **********************/
47
48 /**********************
49 * MACROS
50 **********************/
51
52 /**********************
53 * GLOBAL FUNCTIONS
54 **********************/
55
56 /**
57 * Initialize the image decoder module
58 */
lv_image_decoder_init(uint32_t image_cache_size,uint32_t image_header_count)59 void lv_image_decoder_init(uint32_t image_cache_size, uint32_t image_header_count)
60 {
61 lv_ll_init(img_decoder_ll_p, sizeof(lv_image_decoder_t));
62
63 /*Initialize the cache*/
64 lv_image_cache_init(image_cache_size);
65 lv_image_header_cache_init(image_header_count);
66 }
67
68 /**
69 * Deinitialize the image decoder module
70 */
lv_image_decoder_deinit(void)71 void lv_image_decoder_deinit(void)
72 {
73 lv_cache_destroy(img_cache_p, NULL);
74 lv_cache_destroy(img_header_cache_p, NULL);
75
76 lv_ll_clear(img_decoder_ll_p);
77 }
78
lv_image_decoder_get_info(const void * src,lv_image_header_t * header)79 lv_result_t lv_image_decoder_get_info(const void * src, lv_image_header_t * header)
80 {
81 lv_image_decoder_dsc_t dsc;
82 lv_memzero(&dsc, sizeof(lv_image_decoder_dsc_t));
83 dsc.src = src;
84 dsc.src_type = lv_image_src_get_type(src);
85
86 lv_image_decoder_t * decoder = image_decoder_get_info(&dsc, header);
87 if(decoder == NULL) return LV_RESULT_INVALID;
88
89 return LV_RESULT_OK;
90 }
91
lv_image_decoder_open(lv_image_decoder_dsc_t * dsc,const void * src,const lv_image_decoder_args_t * args)92 lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, const lv_image_decoder_args_t * args)
93 {
94 lv_memzero(dsc, sizeof(lv_image_decoder_dsc_t));
95
96 if(src == NULL) return LV_RESULT_INVALID;
97 dsc->src = src;
98 dsc->src_type = lv_image_src_get_type(src);
99
100 if(lv_image_cache_is_enabled()) {
101 dsc->cache = img_cache_p;
102 /*Try cache first, unless we are told to ignore cache.*/
103 if(!(args && args->no_cache)) {
104 /*
105 * Check the cache first
106 * If the image is found in the cache, just return it.*/
107 if(try_cache(dsc) == LV_RESULT_OK) return LV_RESULT_OK;
108 }
109 }
110
111 /*Find the decoder that can open the image source, and get the header info in the same time.*/
112 dsc->decoder = image_decoder_get_info(dsc, &dsc->header);
113 if(dsc->decoder == NULL) return LV_RESULT_INVALID;
114
115 /*Make a copy of args*/
116 dsc->args = args ? *args : (lv_image_decoder_args_t) {
117 .stride_align = LV_DRAW_BUF_STRIDE_ALIGN != 1,
118 .premultiply = false,
119 .no_cache = false,
120 .use_indexed = false,
121 .flush_cache = false,
122 };
123
124 /*
125 * We assume that if a decoder can get the info, it can open the image.
126 * If decoder open failed, free the source and return error.
127 * If decoder open succeed, add the image to cache if enabled.
128 * */
129 lv_result_t res = dsc->decoder->open_cb(dsc->decoder, dsc);
130
131 /* Flush the D-Cache if enabled and the image was successfully opened */
132 if(dsc->args.flush_cache && res == LV_RESULT_OK && dsc->decoded != NULL) {
133 lv_draw_buf_flush_cache(dsc->decoded, NULL);
134 LV_LOG_INFO("Flushed D-cache: src %p (%s) (W%d x H%d, data: %p cf: %d)",
135 src,
136 dsc->src_type == LV_IMAGE_SRC_FILE ? (const char *)src : "c-array",
137 dsc->decoded->header.w,
138 dsc->decoded->header.h,
139 (void *)dsc->decoded->data,
140 dsc->decoded->header.cf);
141 }
142
143 return res;
144 }
145
lv_image_decoder_get_area(lv_image_decoder_dsc_t * dsc,const lv_area_t * full_area,lv_area_t * decoded_area)146 lv_result_t lv_image_decoder_get_area(lv_image_decoder_dsc_t * dsc, const lv_area_t * full_area,
147 lv_area_t * decoded_area)
148 {
149 lv_result_t res = LV_RESULT_INVALID;
150 if(dsc->decoder->get_area_cb) res = dsc->decoder->get_area_cb(dsc->decoder, dsc, full_area, decoded_area);
151
152 return res;
153 }
154
lv_image_decoder_close(lv_image_decoder_dsc_t * dsc)155 void lv_image_decoder_close(lv_image_decoder_dsc_t * dsc)
156 {
157 if(dsc->decoder) {
158 if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc);
159
160 if(lv_image_cache_is_enabled() && dsc->cache && dsc->cache_entry) {
161 /*Decoded data is in cache, release it from cache's callback*/
162 lv_cache_release(dsc->cache, dsc->cache_entry, NULL);
163 }
164 }
165 }
166
167 /**
168 * Create a new image decoder
169 * @return pointer to the new image decoder
170 */
lv_image_decoder_create(void)171 lv_image_decoder_t * lv_image_decoder_create(void)
172 {
173 lv_image_decoder_t * decoder;
174 decoder = lv_ll_ins_head(img_decoder_ll_p);
175 LV_ASSERT_MALLOC(decoder);
176 if(decoder == NULL) return NULL;
177
178 lv_memzero(decoder, sizeof(lv_image_decoder_t));
179
180 return decoder;
181 }
182
lv_image_decoder_delete(lv_image_decoder_t * decoder)183 void lv_image_decoder_delete(lv_image_decoder_t * decoder)
184 {
185 lv_ll_remove(img_decoder_ll_p, decoder);
186 lv_free(decoder);
187 }
188
lv_image_decoder_get_next(lv_image_decoder_t * decoder)189 lv_image_decoder_t * lv_image_decoder_get_next(lv_image_decoder_t * decoder)
190 {
191 if(decoder == NULL)
192 return lv_ll_get_head(img_decoder_ll_p);
193 else
194 return lv_ll_get_next(img_decoder_ll_p, decoder);
195 }
196
lv_image_decoder_set_info_cb(lv_image_decoder_t * decoder,lv_image_decoder_info_f_t info_cb)197 void lv_image_decoder_set_info_cb(lv_image_decoder_t * decoder, lv_image_decoder_info_f_t info_cb)
198 {
199 decoder->info_cb = info_cb;
200 }
201
lv_image_decoder_set_open_cb(lv_image_decoder_t * decoder,lv_image_decoder_open_f_t open_cb)202 void lv_image_decoder_set_open_cb(lv_image_decoder_t * decoder, lv_image_decoder_open_f_t open_cb)
203 {
204 decoder->open_cb = open_cb;
205 }
206
lv_image_decoder_set_get_area_cb(lv_image_decoder_t * decoder,lv_image_decoder_get_area_cb_t get_area_cb)207 void lv_image_decoder_set_get_area_cb(lv_image_decoder_t * decoder, lv_image_decoder_get_area_cb_t get_area_cb)
208 {
209 decoder->get_area_cb = get_area_cb;
210 }
211
lv_image_decoder_set_close_cb(lv_image_decoder_t * decoder,lv_image_decoder_close_f_t close_cb)212 void lv_image_decoder_set_close_cb(lv_image_decoder_t * decoder, lv_image_decoder_close_f_t close_cb)
213 {
214 decoder->close_cb = close_cb;
215 }
216
lv_image_decoder_add_to_cache(lv_image_decoder_t * decoder,lv_image_cache_data_t * search_key,const lv_draw_buf_t * decoded,void * user_data)217 lv_cache_entry_t * lv_image_decoder_add_to_cache(lv_image_decoder_t * decoder,
218 lv_image_cache_data_t * search_key,
219 const lv_draw_buf_t * decoded, void * user_data)
220 {
221 lv_cache_entry_t * cache_entry = lv_cache_add(img_cache_p, search_key, NULL);
222 if(cache_entry == NULL) {
223 return NULL;
224 }
225
226 lv_image_cache_data_t * cached_data;
227 cached_data = lv_cache_entry_get_data(cache_entry);
228
229 /*Set the cache entry to decoder data*/
230 cached_data->decoded = decoded;
231 if(cached_data->src_type == LV_IMAGE_SRC_FILE) {
232 cached_data->src = lv_strdup(cached_data->src);
233 }
234 cached_data->user_data = user_data; /*Need to free data on cache invalidate instead of decoder_close*/
235 cached_data->decoder = decoder;
236
237 return cache_entry;
238 }
239
lv_image_decoder_post_process(lv_image_decoder_dsc_t * dsc,lv_draw_buf_t * decoded)240 lv_draw_buf_t * lv_image_decoder_post_process(lv_image_decoder_dsc_t * dsc, lv_draw_buf_t * decoded)
241 {
242 if(decoded == NULL) return NULL; /*No need to adjust*/
243
244 lv_image_decoder_args_t * args = &dsc->args;
245 if(args->stride_align && decoded->header.cf != LV_COLOR_FORMAT_RGB565A8) {
246 uint32_t stride_expect = lv_draw_buf_width_to_stride(decoded->header.w, decoded->header.cf);
247 if(decoded->header.stride != stride_expect) {
248 LV_LOG_TRACE("Stride mismatch");
249 lv_result_t res = lv_draw_buf_adjust_stride(decoded, stride_expect);
250 if(res != LV_RESULT_OK) {
251 lv_draw_buf_t * aligned = lv_draw_buf_create_ex(image_cache_draw_buf_handlers, decoded->header.w, decoded->header.h,
252 decoded->header.cf, stride_expect);
253 if(aligned == NULL) {
254 LV_LOG_ERROR("No memory for Stride adjust.");
255 return NULL;
256 }
257
258 lv_draw_buf_copy(aligned, NULL, decoded, NULL);
259 decoded = aligned;
260 }
261 }
262 }
263
264 /*Premultiply alpha channel*/
265 if(args->premultiply
266 && !LV_COLOR_FORMAT_IS_ALPHA_ONLY(decoded->header.cf)
267 && lv_color_format_has_alpha(decoded->header.cf)
268 && !lv_draw_buf_has_flag(decoded, LV_IMAGE_FLAGS_PREMULTIPLIED) /*Hasn't done yet*/
269 ) {
270 LV_LOG_TRACE("Alpha premultiply.");
271 if(lv_draw_buf_has_flag(decoded, LV_IMAGE_FLAGS_MODIFIABLE)) {
272 /*Do it directly*/
273 lv_draw_buf_premultiply(decoded);
274 }
275 else {
276 decoded = lv_draw_buf_dup_ex(image_cache_draw_buf_handlers, decoded);
277 if(decoded == NULL) {
278 LV_LOG_ERROR("No memory for premultiplying.");
279 return NULL;
280 }
281
282 lv_draw_buf_premultiply(decoded);
283 }
284 }
285
286 return decoded;
287 }
288
289 /**********************
290 * STATIC FUNCTIONS
291 **********************/
292
image_decoder_get_info(lv_image_decoder_dsc_t * dsc,lv_image_header_t * header)293 static lv_image_decoder_t * image_decoder_get_info(lv_image_decoder_dsc_t * dsc, lv_image_header_t * header)
294 {
295 lv_memzero(header, sizeof(lv_image_header_t));
296
297 const void * src = dsc->src;
298 lv_image_src_t src_type = dsc->src_type;
299
300 if(src_type == LV_IMAGE_SRC_VARIABLE) {
301 const lv_image_dsc_t * img_dsc = src;
302 if(img_dsc->data == NULL) return NULL;
303 }
304
305 if(src_type == LV_IMAGE_SRC_FILE) LV_LOG_TRACE("Try to find decoder for %s", (const char *)src);
306 else LV_LOG_TRACE("Try to find decoder for %p", src);
307
308 lv_image_decoder_t * decoder;
309 bool is_header_cache_enabled = lv_image_header_cache_is_enabled();
310
311 if(is_header_cache_enabled && src_type == LV_IMAGE_SRC_FILE) {
312 lv_image_header_cache_data_t search_key;
313 search_key.src_type = src_type;
314 search_key.src = src;
315
316 lv_cache_entry_t * entry = lv_cache_acquire(img_header_cache_p, &search_key, NULL);
317
318 if(entry) {
319 lv_image_header_cache_data_t * cached_data = lv_cache_entry_get_data(entry);
320 *header = cached_data->header;
321 decoder = cached_data->decoder;
322 lv_cache_release(img_header_cache_p, entry, NULL);
323
324 LV_LOG_TRACE("Found decoder %s in header cache", decoder->name);
325 return decoder;
326 }
327 }
328
329 if(src_type == LV_IMAGE_SRC_FILE) {
330 lv_fs_res_t fs_res = lv_fs_open(&dsc->file, src, LV_FS_MODE_RD);
331 if(fs_res != LV_FS_RES_OK) {
332 LV_LOG_ERROR("File open failed: %" LV_PRIu32, (uint32_t)fs_res);
333 return NULL;
334 }
335 }
336
337 /*Search the decoders*/
338 lv_image_decoder_t * decoder_prev = NULL;
339 LV_LL_READ(img_decoder_ll_p, decoder) {
340 /*Info and Open callbacks are required*/
341 if(decoder->info_cb && decoder->open_cb) {
342 lv_fs_seek(&dsc->file, 0, LV_FS_SEEK_SET);
343 lv_result_t res = decoder->info_cb(decoder, dsc, header);
344
345 if(decoder_prev) LV_LOG_TRACE("Can't open image with decoder %s. Trying next decoder.", decoder_prev->name);
346
347 if(res == LV_RESULT_OK) {
348 if(header->stride == 0) {
349 LV_LOG_INFO("Image decoder didn't set stride. Calculate it from width.");
350 header->stride = img_width_to_stride(header);
351 }
352 break;
353 }
354
355 decoder_prev = decoder;
356 }
357 }
358
359 if(decoder == NULL) LV_LOG_TRACE("No decoder found");
360 else LV_LOG_TRACE("Found decoder %s", decoder->name);
361
362 if(src_type == LV_IMAGE_SRC_FILE) {
363 lv_fs_close(&dsc->file);
364 }
365
366 if(is_header_cache_enabled && src_type == LV_IMAGE_SRC_FILE && decoder) {
367 lv_cache_entry_t * entry;
368 lv_image_header_cache_data_t search_key;
369 search_key.src_type = src_type;
370 search_key.src = lv_strdup(src);
371 search_key.decoder = decoder;
372 search_key.header = *header;
373 entry = lv_cache_add(img_header_cache_p, &search_key, NULL);
374
375 if(entry == NULL) {
376 if(src_type == LV_IMAGE_SRC_FILE) lv_free((void *)search_key.src);
377 return NULL;
378 }
379
380 lv_cache_release(img_header_cache_p, entry, NULL);
381 }
382
383 return decoder;
384 }
385
img_width_to_stride(lv_image_header_t * header)386 static uint32_t img_width_to_stride(lv_image_header_t * header)
387 {
388 if(header->cf == LV_COLOR_FORMAT_RGB565A8) {
389 return header->w * 2;
390 }
391 else {
392 return ((uint32_t)header->w * lv_color_format_get_bpp(header->cf) + 7) >> 3;
393 }
394 }
395
try_cache(lv_image_decoder_dsc_t * dsc)396 static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
397 {
398 lv_cache_t * cache = dsc->cache;
399
400 lv_image_cache_data_t search_key;
401 search_key.src_type = dsc->src_type;
402 search_key.src = dsc->src;
403
404 lv_cache_entry_t * entry = lv_cache_acquire(cache, &search_key, NULL);
405
406 if(entry) {
407 lv_image_cache_data_t * cached_data = lv_cache_entry_get_data(entry);
408 dsc->decoded = cached_data->decoded;
409 dsc->decoder = (lv_image_decoder_t *)cached_data->decoder;
410 dsc->cache_entry = entry; /*Save the cache to release it in decoder_close*/
411 return LV_RESULT_OK;
412 }
413
414 return LV_RESULT_INVALID;
415 }
416