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