1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** GUIX Component */
17 /** */
18 /** Utility (Utility) */
19 /** */
20 /**************************************************************************/
21
22 #define REDVAL(_c) (GX_UBYTE)(((_c) >> 10) & 0x1f)
23 #define GREENVAL(_c) (GX_UBYTE)(((_c) >> 5) & 0x1f)
24 #define BLUEVAL(_c) (GX_UBYTE)(((_c)) & 0x1f)
25
26 #define ASSEMBLECOLOR(_r, _g, _b) \
27 (USHORT)((((_r) & 0x1f) << 10) | \
28 (((_g) & 0x1f) << 5) | \
29 ((_b) & 0x1f))
30
31 #define BYTE_RANGE(_c) _c > 255 ? 255 : _c
32
33 #define GX_SOURCE_CODE
34
35
36 /* Include necessary system files. */
37
38 #include "gx_api.h"
39 #include "gx_utility.h"
40 #include "gx_system.h"
41
42 /**************************************************************************/
43 /* */
44 /* FUNCTION RELEASE */
45 /* */
46 /* _gx_utility_1555xrgb_pixelmap_raw_resize PORTABLE C */
47 /* 6.1.7 */
48 /* AUTHOR */
49 /* */
50 /* Kenneth Maxwell, Microsoft Corporation */
51 /* */
52 /* DESCRIPTION */
53 /* */
54 /* Internal helper function that resize an 1555xrgb format pixelmap */
55 /* without alpha. */
56 /* */
57 /* INPUT */
58 /* */
59 /* src The source pixelmap */
60 /* destination The resized pixelmap to be */
61 /* returned */
62 /* width New width */
63 /* height New height */
64 /* */
65 /* OUTPUT */
66 /* */
67 /* status Completion status */
68 /* */
69 /* CALLS */
70 /* */
71 /* _gx_system_memory_allocator */
72 /* */
73 /* CALLED BY */
74 /* */
75 /* GUIX Internal Code */
76 /* */
77 /* RELEASE HISTORY */
78 /* */
79 /* DATE NAME DESCRIPTION */
80 /* */
81 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
82 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
83 /* resulting in version 6.1 */
84 /* 06-02-2021 Kenneth Maxwell Modified comment(s), */
85 /* removed unused variable */
86 /* assignment, */
87 /* resulting in version 6.1.7 */
88 /* */
89 /**************************************************************************/
_gx_utility_1555xrgb_pixelmap_raw_resize(GX_PIXELMAP * src,GX_PIXELMAP * destination,INT width,INT height)90 static UINT _gx_utility_1555xrgb_pixelmap_raw_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
91 {
92 /* The pixelmap resize function is implemented from bilinear interpolation
93 image scaling algorithm. */
94
95 USHORT *get;
96 USHORT *put;
97 INT xdiff;
98 INT ydiff;
99 INT xradio;
100 INT yradio;
101 INT x;
102 INT y;
103 INT xx;
104 INT yy;
105 USHORT neighbor_pixels[2][2];
106 GX_COLOR red;
107 GX_COLOR green;
108 GX_COLOR blue;
109
110 /* Calculate scale ratio and enlarge it by 256 times to keep precision. */
111 xradio = ((src -> gx_pixelmap_width) << 8) / width;
112 yradio = ((src -> gx_pixelmap_height) << 8) / height;
113
114 /* Fill property values into destination pixelmap structure. */
115 destination -> gx_pixelmap_flags = src -> gx_pixelmap_flags;
116 destination -> gx_pixelmap_format = src -> gx_pixelmap_format;
117
118 destination -> gx_pixelmap_height = (GX_VALUE)height;
119 destination -> gx_pixelmap_width = (GX_VALUE)width;
120
121 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
122 overflow cannot occur. */
123 destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
124
125 /* Allocate memory for destination pixelmap. */
126 destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
127 destination -> gx_pixelmap_aux_data = GX_NULL;
128
129 if (destination -> gx_pixelmap_data == GX_NULL)
130 {
131 return GX_SYSTEM_MEMORY_ERROR;
132 }
133
134 put = (USHORT *)destination -> gx_pixelmap_data;
135
136 /* Loop through destination's pixel and fill each pixel with
137 the interpolation of 4 nearest neighboring pixels.*/
138 for (y = 0; y < height; y++)
139 {
140 for (x = 0; x < width; x++)
141 {
142 /* Find the original source pixel that the destination pixel conrespond to. */
143 xx = (xradio * x) >> 8;
144 yy = (yradio * y) >> 8;
145
146 /* The coordinates of the original source pixel are truncate value,
147 calucate their distance between the mathematical coordinates. */
148 xdiff = (xradio * x) & 0xff;
149 ydiff = (yradio * y) & 0xff;
150
151 get = (USHORT *)src -> gx_pixelmap_data;
152 get += yy * src -> gx_pixelmap_width;
153 get += xx;
154
155 /* Calculate 4 nearest neighboring pixels around the mathematical point of original pixel. */
156 neighbor_pixels[0][0] = *get;
157
158 if ((xx < src -> gx_pixelmap_width - 1) && (yy < src -> gx_pixelmap_height - 1))
159 {
160 neighbor_pixels[0][1] = *(get + 1);
161 neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
162 neighbor_pixels[1][1] = *(get + src -> gx_pixelmap_width + 1);
163 }
164 else
165 {
166
167 if ((xx == src -> gx_pixelmap_width - 1) &&
168 (yy == src -> gx_pixelmap_height - 1))
169 {
170 /* Handle pixels in right bottom corner. */
171 neighbor_pixels[0][1] = neighbor_pixels[0][0];
172 neighbor_pixels[1][0] = neighbor_pixels[0][0];
173 neighbor_pixels[1][1] = neighbor_pixels[0][0];
174 }
175 else if (xx == src -> gx_pixelmap_width - 1)
176 {
177 /* Handle pixels in right edge. */
178 neighbor_pixels[0][1] = neighbor_pixels[0][0];
179 neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
180 neighbor_pixels[1][1] = neighbor_pixels[1][0];
181 }
182 else
183 {
184 /* Handle pixels in bottom edge. */
185 neighbor_pixels[0][1] = *(get + 1);
186 neighbor_pixels[1][0] = neighbor_pixels[0][0];
187 neighbor_pixels[1][1] = neighbor_pixels[0][1];
188 }
189 }
190
191
192 /* Calulate pixel values by interpolating 4 neighboring pixels. */
193 red = (REDVAL(neighbor_pixels[0][0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
194 REDVAL(neighbor_pixels[0][1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) + \
195 REDVAL(neighbor_pixels[1][0]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) + \
196 REDVAL(neighbor_pixels[1][1]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
197
198 green = (GREENVAL(neighbor_pixels[0][0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
199 GREENVAL(neighbor_pixels[0][1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) + \
200 GREENVAL(neighbor_pixels[1][0]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) + \
201 GREENVAL(neighbor_pixels[1][1]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
202
203 blue = (BLUEVAL(neighbor_pixels[0][0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
204 BLUEVAL(neighbor_pixels[0][1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) + \
205 BLUEVAL(neighbor_pixels[1][0]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) + \
206 BLUEVAL(neighbor_pixels[1][1]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
207
208 red = BYTE_RANGE(red);
209 green = BYTE_RANGE(green);
210 blue = BYTE_RANGE(blue);
211
212 *put++ = ASSEMBLECOLOR(red, green, blue);
213 }
214 }
215
216 return GX_SUCCESS;
217 }
218
219 /**************************************************************************/
220 /* */
221 /* FUNCTION RELEASE */
222 /* */
223 /* _gx_utility_1555xrgb_pixelmap_alpha_resize PORTABLE C */
224 /* 6.1.7 */
225 /* AUTHOR */
226 /* */
227 /* Kenneth Maxwell, Microsoft Corporation */
228 /* */
229 /* DESCRIPTION */
230 /* */
231 /* Internal helper function that resize an 1555xrgb format pixelmap */
232 /* with alpha. */
233 /* */
234 /* INPUT */
235 /* */
236 /* src The source pixelmap */
237 /* destination The resized pixelmap to be */
238 /* returned */
239 /* width New width */
240 /* height New height */
241 /* */
242 /* OUTPUT */
243 /* */
244 /* status Completion status */
245 /* */
246 /* CALLS */
247 /* */
248 /* _gx_system_memory_allocator */
249 /* */
250 /* CALLED BY */
251 /* */
252 /* GUIX Internal Code */
253 /* */
254 /* RELEASE HISTORY */
255 /* */
256 /* DATE NAME DESCRIPTION */
257 /* */
258 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
259 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
260 /* resulting in version 6.1 */
261 /* 06-02-2021 Kenneth Maxwell Modified comment(s), */
262 /* removed unused variable */
263 /* assignment, */
264 /* resulting in version 6.1.7 */
265 /* */
266 /**************************************************************************/
_gx_utility_1555xrgb_pixelmap_alpha_resize(GX_PIXELMAP * src,GX_PIXELMAP * destination,INT width,INT height)267 static UINT _gx_utility_1555xrgb_pixelmap_alpha_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
268 {
269 /* The pixelmap resize function is implemented from bilinear interpolation
270 image scaling algorithm. */
271
272 USHORT *get;
273 USHORT *put;
274 GX_UBYTE *getalpha;
275 GX_UBYTE *putalpha;
276 INT xdiff;
277 INT ydiff;
278 INT xradio;
279 INT yradio;
280 INT x;
281 INT y;
282 INT xx;
283 INT yy;
284 USHORT neighbor_pixels[2][2];
285 GX_COLOR alpha[4];
286 GX_COLOR red;
287 GX_COLOR green;
288 GX_COLOR blue;
289
290 /* Calculate scale ratio and enlarge it by 256 times to keep precision. */
291 xradio = ((src -> gx_pixelmap_width) << 8) / width;
292 yradio = ((src -> gx_pixelmap_height) << 8) / height;
293
294 /* Fill property values into destination pixelmap structure. */
295 destination -> gx_pixelmap_flags = src -> gx_pixelmap_flags;
296 destination -> gx_pixelmap_format = src -> gx_pixelmap_format;
297
298 destination -> gx_pixelmap_height = (GX_VALUE)height;
299 destination -> gx_pixelmap_width = (GX_VALUE)width;
300
301 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
302 overflow cannot occur. */
303 destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
304 destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
305
306 /* Allocate memory to load pixelmap data. */
307 destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
308
309 if (destination -> gx_pixelmap_data == GX_NULL)
310 {
311 return GX_SYSTEM_MEMORY_ERROR;
312 }
313
314 destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
315
316 if (destination -> gx_pixelmap_aux_data == GX_NULL)
317 {
318 _gx_system_memory_free((void *)destination -> gx_pixelmap_data);
319 return GX_SYSTEM_MEMORY_ERROR;
320 }
321
322 put = (USHORT *)destination -> gx_pixelmap_data;
323 putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
324
325 /* Loop through destination's pixel and fill each pixel with
326 the interpolation of 4 nearest neighboring pixels.*/
327 for (y = 0; y < height; y++)
328 {
329 for (x = 0; x < width; x++)
330 {
331 /* Find the original source pixel that the destination pixel conrespond to. */
332 xx = (xradio * x) >> 8;
333 yy = (yradio * y) >> 8;
334
335 /* The coordinates of the original source pixel are truncate value,
336 calucate their distance between the mathematical coordinates. */
337 xdiff = (xradio * x) & 0xff;
338 ydiff = (yradio * y) & 0xff;
339
340 get = (USHORT *)src -> gx_pixelmap_data;
341 get += yy * src -> gx_pixelmap_width;
342 get += xx;
343
344 getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
345 getalpha += yy * src -> gx_pixelmap_width;
346 getalpha += xx;
347
348
349 /* Calculate 4 nearest neighboring pixels around the mathematical point of original pixel. */
350 neighbor_pixels[0][0] = *get;
351 alpha[0] = *getalpha;
352
353 if ((xx < src -> gx_pixelmap_width - 1) && (yy < src -> gx_pixelmap_height - 1))
354 {
355 neighbor_pixels[0][1] = *(get + 1);
356 neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
357 neighbor_pixels[1][1] = *(get + src -> gx_pixelmap_width + 1);
358
359 alpha[1] = *(getalpha + 1);
360 alpha[2] = *(getalpha + src -> gx_pixelmap_width);
361 alpha[3] = *(getalpha + src -> gx_pixelmap_width + 1);
362 }
363 else
364 {
365
366 if ((xx == src -> gx_pixelmap_width - 1) &&
367 (yy == src -> gx_pixelmap_height - 1))
368 {
369 /* Handle right bottom corder pixel. */
370 neighbor_pixels[0][1] = neighbor_pixels[0][0];
371 neighbor_pixels[1][0] = neighbor_pixels[0][0];
372 neighbor_pixels[1][1] = neighbor_pixels[0][0];
373
374 alpha[1] = alpha[0];
375 alpha[2] = alpha[0];
376 alpha[3] = alpha[0];
377 }
378 else if (xx == src -> gx_pixelmap_width - 1)
379 {
380 /* Handle pixels in right edge. */
381 neighbor_pixels[0][1] = neighbor_pixels[0][0];
382 neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
383 neighbor_pixels[1][1] = neighbor_pixels[1][0];
384
385 alpha[1] = alpha[0];
386 alpha[2] = *(getalpha + src -> gx_pixelmap_width);
387 alpha[3] = alpha[2];
388 }
389 else
390 {
391 /* Handle pixels in bottom edge. */
392 neighbor_pixels[0][1] = *(get + 1);
393 neighbor_pixels[1][0] = neighbor_pixels[0][0];
394 neighbor_pixels[1][1] = neighbor_pixels[0][1];
395
396 alpha[1] = *(getalpha + 1);
397 alpha[2] = alpha[0];
398 alpha[3] = alpha[1];
399 }
400 }
401
402 /* Calulate pixel values by interpolating 4 neighboring pixels. */
403 red = (REDVAL(neighbor_pixels[0][0]) * (alpha[0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
404 REDVAL(neighbor_pixels[0][1]) * (alpha[1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) + \
405 REDVAL(neighbor_pixels[1][0]) * (alpha[2]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) + \
406 REDVAL(neighbor_pixels[1][1]) * (alpha[3]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
407
408 green = (GREENVAL(neighbor_pixels[0][0]) * (alpha[0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
409 GREENVAL(neighbor_pixels[0][1]) * (alpha[1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) + \
410 GREENVAL(neighbor_pixels[1][0]) * (alpha[2]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) + \
411 GREENVAL(neighbor_pixels[1][1]) * (alpha[3]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
412
413 blue = (BLUEVAL(neighbor_pixels[0][0]) * (alpha[0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
414 BLUEVAL(neighbor_pixels[0][1]) * (alpha[1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) + \
415 BLUEVAL(neighbor_pixels[1][0]) * (alpha[2]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) + \
416 BLUEVAL(neighbor_pixels[1][1]) * (alpha[3]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
417
418 alpha[0] = ((alpha[0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
419 (alpha[1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) + \
420 (alpha[2]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) + \
421 (alpha[3]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
422
423 if (alpha[0])
424 {
425 red /= alpha[0];
426 green /= alpha[0];
427 blue /= alpha[0];
428 }
429
430 alpha[0] = BYTE_RANGE(alpha[0]);
431 red = BYTE_RANGE(red);
432 green = BYTE_RANGE(green);
433 blue = BYTE_RANGE(blue);
434
435 *put++ = ASSEMBLECOLOR(red, green, blue);
436 *putalpha++ = (GX_UBYTE)alpha[0];
437 }
438 }
439
440 return GX_SUCCESS;
441 }
442
443 /**************************************************************************/
444 /* */
445 /* FUNCTION RELEASE */
446 /* */
447 /* _gx_utility_1555xrgb_pixelmap_resize PORTABLE C */
448 /* 6.1 */
449 /* AUTHOR */
450 /* */
451 /* Kenneth Maxwell, Microsoft Corporation */
452 /* */
453 /* DESCRIPTION */
454 /* */
455 /* This function resize an 1555xrgb format pixelmap with or without */
456 /* alpha channel. */
457 /* */
458 /* INPUT */
459 /* */
460 /* src The source pixelmap */
461 /* destination The resized pixelmap to be */
462 /* returned */
463 /* width New width */
464 /* height New height */
465 /* */
466 /* OUTPUT */
467 /* */
468 /* status Completion status */
469 /* */
470 /* CALLS */
471 /* */
472 /* _gx_utility_1555xrgb_pixelmap_alpha_resize */
473 /* Resize 1555xrgb format */
474 /* pixelmap with alpha */
475 /* _gx_utility_1555xrgb_pixelmap_raw_resize */
476 /* Resize 1555xrgb format */
477 /* pixelmap without alpha */
478 /* */
479 /* CALLED BY */
480 /* */
481 /* GUIX Internal Code */
482 /* */
483 /* RELEASE HISTORY */
484 /* */
485 /* DATE NAME DESCRIPTION */
486 /* */
487 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
488 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
489 /* resulting in version 6.1 */
490 /* */
491 /**************************************************************************/
_gx_utility_1555xrgb_pixelmap_resize(GX_PIXELMAP * src,GX_PIXELMAP * destination,INT width,INT height)492 UINT _gx_utility_1555xrgb_pixelmap_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
493 {
494 UINT status;
495
496 if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
497 {
498 /* alpha, no compression */
499
500 status = _gx_utility_1555xrgb_pixelmap_alpha_resize(src, destination, width, height);
501 }
502 else
503 {
504 /* no alpha, no compression */
505
506 status = _gx_utility_1555xrgb_pixelmap_raw_resize(src, destination, width, height);
507 }
508
509 return status;
510 }
511