1 /**
2  * @file lv_img_buf.h
3  *
4  */
5 
6 #ifndef LV_IMG_BUF_H
7 #define LV_IMG_BUF_H
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 /*********************
14  *      INCLUDES
15  *********************/
16 #include <stdbool.h>
17 #include "../lv_misc/lv_color.h"
18 #include "../lv_misc/lv_area.h"
19 
20 
21 /*********************
22  *      DEFINES
23  *********************/
24 /*If image pixels contains alpha we need to know how much byte is a pixel*/
25 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8
26 #define LV_IMG_PX_SIZE_ALPHA_BYTE 2
27 #elif LV_COLOR_DEPTH == 16
28 #define LV_IMG_PX_SIZE_ALPHA_BYTE 3
29 #elif LV_COLOR_DEPTH == 32
30 #define LV_IMG_PX_SIZE_ALPHA_BYTE 4
31 #endif
32 
33 #define LV_IMG_BUF_SIZE_TRUE_COLOR(w, h) ((LV_COLOR_SIZE / 8) * w * h)
34 #define LV_IMG_BUF_SIZE_TRUE_COLOR_CHROMA_KEYED(w, h) ((LV_COLOR_SIZE / 8) * w * h)
35 #define LV_IMG_BUF_SIZE_TRUE_COLOR_ALPHA(w, h) (LV_IMG_PX_SIZE_ALPHA_BYTE * w * h)
36 
37 /*+ 1: to be sure no fractional row*/
38 #define LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) ((((w / 8) + 1) * h))
39 #define LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) ((((w / 4) + 1) * h))
40 #define LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) ((((w / 2) + 1) * h))
41 #define LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) ((w * h))
42 
43 /*4 * X: for palette*/
44 #define LV_IMG_BUF_SIZE_INDEXED_1BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_1BIT(w, h) + 4 * 2)
45 #define LV_IMG_BUF_SIZE_INDEXED_2BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_2BIT(w, h) + 4 * 4)
46 #define LV_IMG_BUF_SIZE_INDEXED_4BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_4BIT(w, h) + 4 * 16)
47 #define LV_IMG_BUF_SIZE_INDEXED_8BIT(w, h) (LV_IMG_BUF_SIZE_ALPHA_8BIT(w, h) + 4 * 256)
48 
49 #define LV_IMG_ZOOM_NONE   256
50 
51 #define _LV_TRANSFORM_TRIGO_SHIFT 10
52 #define _LV_ZOOM_INV_UPSCALE 5
53 
54 /**********************
55  *      TYPEDEFS
56  **********************/
57 
58 /*Image color format*/
59 enum {
60     LV_IMG_CF_UNKNOWN = 0,
61 
62     LV_IMG_CF_RAW,              /**< Contains the file as it is. Needs custom decoder function*/
63     LV_IMG_CF_RAW_ALPHA,        /**< Contains the file as it is. The image has alpha. Needs custom decoder
64                                    function*/
65     LV_IMG_CF_RAW_CHROMA_KEYED, /**< Contains the file as it is. The image is chroma keyed. Needs
66                                    custom decoder function*/
67 
68     LV_IMG_CF_TRUE_COLOR,              /**< Color format and depth should match with LV_COLOR settings*/
69     LV_IMG_CF_TRUE_COLOR_ALPHA,        /**< Same as `LV_IMG_CF_TRUE_COLOR` but every pixel has an alpha byte*/
70     LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED, /**< Same as `LV_IMG_CF_TRUE_COLOR` but LV_COLOR_TRANSP pixels
71                                           will be transparent*/
72 
73     LV_IMG_CF_INDEXED_1BIT, /**< Can have 2 different colors in a palette (always chroma keyed)*/
74     LV_IMG_CF_INDEXED_2BIT, /**< Can have 4 different colors in a palette (always chroma keyed)*/
75     LV_IMG_CF_INDEXED_4BIT, /**< Can have 16 different colors in a palette (always chroma keyed)*/
76     LV_IMG_CF_INDEXED_8BIT, /**< Can have 256 different colors in a palette (always chroma keyed)*/
77 
78     LV_IMG_CF_ALPHA_1BIT, /**< Can have one color and it can be drawn or not*/
79     LV_IMG_CF_ALPHA_2BIT, /**< Can have one color but 4 different alpha value*/
80     LV_IMG_CF_ALPHA_4BIT, /**< Can have one color but 16 different alpha value*/
81     LV_IMG_CF_ALPHA_8BIT, /**< Can have one color but 256 different alpha value*/
82 
83     LV_IMG_CF_RESERVED_15,              /**< Reserved for further use. */
84     LV_IMG_CF_RESERVED_16,              /**< Reserved for further use. */
85     LV_IMG_CF_RESERVED_17,              /**< Reserved for further use. */
86     LV_IMG_CF_RESERVED_18,              /**< Reserved for further use. */
87     LV_IMG_CF_RESERVED_19,              /**< Reserved for further use. */
88     LV_IMG_CF_RESERVED_20,              /**< Reserved for further use. */
89     LV_IMG_CF_RESERVED_21,              /**< Reserved for further use. */
90     LV_IMG_CF_RESERVED_22,              /**< Reserved for further use. */
91     LV_IMG_CF_RESERVED_23,              /**< Reserved for further use. */
92 
93     LV_IMG_CF_USER_ENCODED_0,          /**< User holder encoding format. */
94     LV_IMG_CF_USER_ENCODED_1,          /**< User holder encoding format. */
95     LV_IMG_CF_USER_ENCODED_2,          /**< User holder encoding format. */
96     LV_IMG_CF_USER_ENCODED_3,          /**< User holder encoding format. */
97     LV_IMG_CF_USER_ENCODED_4,          /**< User holder encoding format. */
98     LV_IMG_CF_USER_ENCODED_5,          /**< User holder encoding format. */
99     LV_IMG_CF_USER_ENCODED_6,          /**< User holder encoding format. */
100     LV_IMG_CF_USER_ENCODED_7,          /**< User holder encoding format. */
101 };
102 typedef uint8_t lv_img_cf_t;
103 
104 
105 /**
106  * LVGL image header
107  */
108 /* The first 8 bit is very important to distinguish the different source types.
109  * For more info see `lv_img_get_src_type()` in lv_img.c
110  * On big endian systems the order is reversed so cf and always_zero must be at
111  * the end of the struct.
112  * */
113 #if LV_BIG_ENDIAN_SYSTEM
114 typedef struct {
115 
116     uint32_t h : 11; /*Height of     the image map*/
117     uint32_t w : 11; /*Width of the image map*/
118     uint32_t reserved : 2; /*Reserved to be used later*/
119     uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
120                                  non-printable character*/
121     uint32_t cf : 5;          /* Color format: See `lv_img_color_format_t`*/
122 
123 
124 } lv_img_header_t;
125 #else
126 typedef struct {
127 
128     uint32_t cf : 5;          /* Color format: See `lv_img_color_format_t`*/
129     uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a
130                                  non-printable character*/
131 
132     uint32_t reserved : 2; /*Reserved to be used later*/
133 
134     uint32_t w : 11; /*Width of the image map*/
135     uint32_t h : 11; /*Height of     the image map*/
136 } lv_img_header_t;
137 #endif
138 
139 /** Image header it is compatible with
140  * the result from image converter utility*/
141 typedef struct {
142     lv_img_header_t header;
143     uint32_t data_size;
144     const uint8_t * data;
145 } lv_img_dsc_t;
146 
147 typedef struct {
148     struct {
149         const void * src;           /*image source (array of pixels)*/
150         lv_coord_t src_w;           /*width of the image source*/
151         lv_coord_t src_h;           /*height of the image source*/
152         lv_coord_t pivot_x;         /*pivot x*/
153         lv_coord_t pivot_y;         /* pivot y*/
154         int16_t angle;              /*angle to rotate*/
155         uint16_t zoom;              /*256 no zoom, 128 half size, 512 double size*/
156         lv_color_t color;           /*a color used for `LV_IMG_CF_INDEXED_1/2/4/8BIT` color formats*/
157         lv_img_cf_t cf;             /*color format of the image to rotate*/
158         bool antialias;
159     } cfg;
160 
161     struct {
162         lv_color_t color;
163         lv_opa_t opa;
164     } res;
165 
166 
167     struct {
168         lv_img_dsc_t img_dsc;
169         int32_t pivot_x_256;
170         int32_t pivot_y_256;
171         int32_t sinma;
172         int32_t cosma;
173 
174         uint8_t chroma_keyed : 1;
175         uint8_t has_alpha : 1;
176         uint8_t native_color : 1;
177 
178         uint32_t zoom_inv;
179 
180         /*Runtime data*/
181         lv_coord_t xs;
182         lv_coord_t ys;
183         lv_coord_t xs_int;
184         lv_coord_t ys_int;
185         uint32_t pxi;
186         uint8_t px_size;
187     } tmp;
188 } lv_img_transform_dsc_t;
189 
190 /**********************
191  * GLOBAL PROTOTYPES
192  **********************/
193 
194 /**
195  * Allocate an image buffer in RAM
196  * @param w width of image
197  * @param h height of image
198  * @param cf a color format (`LV_IMG_CF_...`)
199  * @return an allocated image, or NULL on failure
200  */
201 lv_img_dsc_t * lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
202 
203 /**
204  * Get the color of an image's pixel
205  * @param dsc an image descriptor
206  * @param x x coordinate of the point to get
207  * @param y x coordinate of the point to get
208  * @param color the color of the image. In case of `LV_IMG_CF_ALPHA_1/2/4/8` this color is used.
209  * Not used in other cases.
210  * @param safe true: check out of bounds
211  * @return color of the point
212  */
213 lv_color_t lv_img_buf_get_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t color);
214 
215 /**
216  * Get the alpha value of an image's pixel
217  * @param dsc pointer to an image descriptor
218  * @param x x coordinate of the point to set
219  * @param y x coordinate of the point to set
220  * @param safe true: check out of bounds
221  * @return alpha value of the point
222  */
223 lv_opa_t lv_img_buf_get_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y);
224 
225 /**
226  * Set the color of a pixel of an image. The alpha channel won't be affected.
227  * @param dsc pointer to an image descriptor
228  * @param x x coordinate of the point to set
229  * @param y x coordinate of the point to set
230  * @param c color of the point
231  * @param safe true: check out of bounds
232  */
233 void lv_img_buf_set_px_color(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_color_t c);
234 
235 /**
236  * Set the alpha value of a pixel of an image. The color won't be affected
237  * @param dsc pointer to an image descriptor
238  * @param x x coordinate of the point to set
239  * @param y x coordinate of the point to set
240  * @param opa the desired opacity
241  * @param safe true: check out of bounds
242  */
243 void lv_img_buf_set_px_alpha(lv_img_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa);
244 
245 /**
246  * Set the palette color of an indexed image. Valid only for `LV_IMG_CF_INDEXED1/2/4/8`
247  * @param dsc pointer to an image descriptor
248  * @param id the palette color to set:
249  *   - for `LV_IMG_CF_INDEXED1`: 0..1
250  *   - for `LV_IMG_CF_INDEXED2`: 0..3
251  *   - for `LV_IMG_CF_INDEXED4`: 0..15
252  *   - for `LV_IMG_CF_INDEXED8`: 0..255
253  * @param c the color to set
254  */
255 void lv_img_buf_set_palette(lv_img_dsc_t * dsc, uint8_t id, lv_color_t c);
256 
257 /**
258  * Free an allocated image buffer
259  * @param dsc image buffer to free
260  */
261 void lv_img_buf_free(lv_img_dsc_t * dsc);
262 
263 /**
264  * Get the memory consumption of a raw bitmap, given color format and dimensions.
265  * @param w width
266  * @param h height
267  * @param cf color format
268  * @return size in bytes
269  */
270 uint32_t lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
271 
272 
273 #if LV_USE_IMG_TRANSFORM
274 /**
275  * Initialize a descriptor to rotate an image
276  * @param dsc pointer to an `lv_img_transform_dsc_t` variable whose `cfg` field is initialized
277  */
278 void _lv_img_buf_transform_init(lv_img_transform_dsc_t * dsc);
279 
280 /**
281  * Continue transformation by taking the neighbors into account
282  * @param dsc pointer to the transformation descriptor
283  */
284 bool _lv_img_buf_transform_anti_alias(lv_img_transform_dsc_t * dsc);
285 
286 
287 /**
288  * Get which color and opa would come to a pixel if it were rotated
289  * @param dsc a descriptor initialized by `lv_img_buf_rotate_init`
290  * @param x the coordinate which color and opa should be get
291  * @param y the coordinate which color and opa should be get
292  * @return true: there is valid pixel on these x/y coordinates; false: the rotated pixel was out of the image
293  * @note the result is written back to `dsc->res_color` and `dsc->res_opa`
294  */
_lv_img_buf_transform(lv_img_transform_dsc_t * dsc,lv_coord_t x,lv_coord_t y)295 static inline bool _lv_img_buf_transform(lv_img_transform_dsc_t * dsc, lv_coord_t x, lv_coord_t y)
296 {
297     const uint8_t * src_u8 = (const uint8_t *)dsc->cfg.src;
298 
299     /*Get the target point relative coordinates to the pivot*/
300     int32_t xt = x - dsc->cfg.pivot_x;
301     int32_t yt = y - dsc->cfg.pivot_y;
302 
303     int32_t xs;
304     int32_t ys;
305     if(dsc->cfg.zoom == LV_IMG_ZOOM_NONE) {
306         /*Get the source pixel from the upscaled image*/
307         xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_x_256;
308         ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT - 8)) + dsc->tmp.pivot_y_256;
309     }
310     else if(dsc->cfg.angle == 0) {
311         xt = (int32_t)((int32_t)xt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
312         yt = (int32_t)((int32_t)yt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
313         xs = xt + dsc->tmp.pivot_x_256;
314         ys = yt + dsc->tmp.pivot_y_256;
315     }
316     else {
317         xt = (int32_t)((int32_t)xt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
318         yt = (int32_t)((int32_t)yt * dsc->tmp.zoom_inv) >> _LV_ZOOM_INV_UPSCALE;
319         xs = ((dsc->tmp.cosma * xt - dsc->tmp.sinma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_x_256;
320         ys = ((dsc->tmp.sinma * xt + dsc->tmp.cosma * yt) >> (_LV_TRANSFORM_TRIGO_SHIFT)) + dsc->tmp.pivot_y_256;
321     }
322 
323     /*Get the integer part of the source pixel*/
324     int32_t xs_int = xs >> 8;
325     int32_t ys_int = ys >> 8;
326 
327     if(xs_int >= dsc->cfg.src_w) return false;
328     else if(xs_int < 0) return false;
329 
330     if(ys_int >= dsc->cfg.src_h) return false;
331     else if(ys_int < 0) return false;
332 
333     uint8_t px_size;
334     uint32_t pxi;
335     if(dsc->tmp.native_color) {
336         if(dsc->tmp.has_alpha == 0) {
337             px_size = LV_COLOR_SIZE >> 3;
338 
339             pxi     = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size;
340             _lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size);
341         }
342         else {
343             px_size = LV_IMG_PX_SIZE_ALPHA_BYTE;
344             pxi     = dsc->cfg.src_w * ys_int * px_size + xs_int * px_size;
345             _lv_memcpy_small(&dsc->res.color, &src_u8[pxi], px_size - 1);
346             dsc->res.opa = src_u8[pxi + px_size - 1];
347         }
348     }
349     else {
350         pxi = 0; /*unused*/
351         px_size = 0;    /*unused*/
352         dsc->res.color = lv_img_buf_get_px_color(&dsc->tmp.img_dsc, xs_int, ys_int, dsc->cfg.color);
353         dsc->res.opa = lv_img_buf_get_px_alpha(&dsc->tmp.img_dsc, xs_int, ys_int);
354     }
355 
356     if(dsc->tmp.chroma_keyed) {
357         lv_color_t ct = LV_COLOR_TRANSP;
358         if(dsc->res.color.full == ct.full) return false;
359     }
360 
361     if(dsc->cfg.antialias == false) return true;
362 
363     dsc->tmp.xs = xs;
364     dsc->tmp.ys = ys;
365     dsc->tmp.xs_int = xs_int;
366     dsc->tmp.ys_int = ys_int;
367     dsc->tmp.pxi = pxi;
368     dsc->tmp.px_size = px_size;
369 
370     bool ret;
371     ret = _lv_img_buf_transform_anti_alias(dsc);
372 
373     return ret;
374 }
375 #endif
376 /**
377  * Get the area of a rectangle if its rotated and scaled
378  * @param res store the coordinates here
379  * @param w width of the rectangle to transform
380  * @param h height of the rectangle to transform
381  * @param angle angle of rotation
382  * @param zoom zoom, (256 no zoom)
383  * @param pivot x,y pivot coordinates of rotation
384  */
385 void _lv_img_buf_get_transformed_area(lv_area_t * res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom,
386                                       const lv_point_t * pivot);
387 
388 /**********************
389  *      MACROS
390  **********************/
391 
392 #ifdef __cplusplus
393 } /* extern "C" */
394 #endif
395 
396 #endif /*LV_IMG_BUF_H*/
397