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