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