GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_utility_1555xrgb_pixelmap_resize.c Lines: 148 148 100.0 %
Date: 2026-03-06 19:21:09 Branches: 38 38 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
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
/**************************************************************************/
78
103
static UINT _gx_utility_1555xrgb_pixelmap_raw_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
79
{
80
/* The pixelmap resize function is implemented from bilinear interpolation
81
   image scaling algorithm.  */
82
83
USHORT  *get;
84
USHORT  *put;
85
INT      xdiff;
86
INT      ydiff;
87
INT      xradio;
88
INT      yradio;
89
INT      x;
90
INT      y;
91
INT      xx;
92
INT      yy;
93
USHORT   neighbor_pixels[2][2];
94
GX_COLOR red;
95
GX_COLOR green;
96
GX_COLOR blue;
97
98
    /* Calculate scale ratio and enlarge it by 256 times to keep precision.  */
99
103
    xradio = ((src -> gx_pixelmap_width) << 8) / width;
100
103
    yradio = ((src -> gx_pixelmap_height) << 8) / height;
101
102
    /* Fill property values into destination pixelmap structure. */
103
103
    destination -> gx_pixelmap_flags = src -> gx_pixelmap_flags;
104
103
    destination -> gx_pixelmap_format = src -> gx_pixelmap_format;
105
106
103
    destination -> gx_pixelmap_height = (GX_VALUE)height;
107
103
    destination -> gx_pixelmap_width = (GX_VALUE)width;
108
109
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
110
       overflow cannot occur. */
111
103
    destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
112
113
    /* Allocate memory for destination pixelmap.  */
114
103
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
115
103
    destination -> gx_pixelmap_aux_data = GX_NULL;
116
117
103
    if (destination -> gx_pixelmap_data == GX_NULL)
118
    {
119
2
        return GX_SYSTEM_MEMORY_ERROR;
120
    }
121
122
101
    put = (USHORT *)destination -> gx_pixelmap_data;
123
124
    /* Loop through destination's pixel and fill each pixel with
125
       the interpolation of 4 nearest neighboring pixels.*/
126
12220
    for (y = 0; y < height; y++)
127
    {
128
2800199
        for (x = 0; x < width; x++)
129
        {
130
            /* Find the original source pixel that the destination pixel conrespond to. */
131
2788080
            xx = (xradio * x) >> 8;
132
2788080
            yy = (yradio * y) >> 8;
133
134
            /* The coordinates of the original source pixel are truncate value,
135
               calucate their distance between the mathematical coordinates. */
136
2788080
            xdiff = (xradio * x) & 0xff;
137
2788080
            ydiff = (yradio * y) & 0xff;
138
139
2788080
            get = (USHORT *)src -> gx_pixelmap_data;
140
2788080
            get += yy * src -> gx_pixelmap_width;
141
2788080
            get += xx;
142
143
            /* Calculate 4 nearest neighboring pixels around the mathematical point of original pixel. */
144
2788080
            neighbor_pixels[0][0] = *get;
145
146

2788080
            if ((xx < src -> gx_pixelmap_width - 1) && (yy < src -> gx_pixelmap_height - 1))
147
            {
148
2782329
                neighbor_pixels[0][1] = *(get + 1);
149
2782329
                neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
150
2782329
                neighbor_pixels[1][1] = *(get + src -> gx_pixelmap_width + 1);
151
            }
152
            else
153
            {
154
155
5751
                if ((xx == src -> gx_pixelmap_width - 1) &&
156
1193
                    (yy == src -> gx_pixelmap_height - 1))
157
                {
158
                    /* Handle pixels in right bottom corner.  */
159
2
                    neighbor_pixels[0][1] = neighbor_pixels[0][0];
160
2
                    neighbor_pixels[1][0] = neighbor_pixels[0][0];
161
2
                    neighbor_pixels[1][1] = neighbor_pixels[0][0];
162
                }
163
5749
                else if (xx == src -> gx_pixelmap_width - 1)
164
                {
165
                    /* Handle pixels in right edge.  */
166
1191
                    neighbor_pixels[0][1] = neighbor_pixels[0][0];
167
1191
                    neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
168
1191
                    neighbor_pixels[1][1] = neighbor_pixels[1][0];
169
                }
170
                else
171
                {
172
                    /* Handle pixels in bottom edge.  */
173
4558
                    neighbor_pixels[0][1] = *(get + 1);
174
4558
                    neighbor_pixels[1][0] = neighbor_pixels[0][0];
175
4558
                    neighbor_pixels[1][1] = neighbor_pixels[0][1];
176
                }
177
            }
178
179
180
            /* Calulate pixel values by interpolating 4 neighboring pixels. */
181
2788080
            red = (REDVAL(neighbor_pixels[0][0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
182
2788080
                   REDVAL(neighbor_pixels[0][1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) +         \
183
2788080
                   REDVAL(neighbor_pixels[1][0]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) +         \
184
2788080
                   REDVAL(neighbor_pixels[1][1]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
185
186
2788080
            green = (GREENVAL(neighbor_pixels[0][0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
187
2788080
                     GREENVAL(neighbor_pixels[0][1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) +         \
188
2788080
                     GREENVAL(neighbor_pixels[1][0]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) +         \
189
2788080
                     GREENVAL(neighbor_pixels[1][1]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
190
191
2788080
            blue = (BLUEVAL(neighbor_pixels[0][0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
192
2788080
                    BLUEVAL(neighbor_pixels[0][1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) +         \
193
2788080
                    BLUEVAL(neighbor_pixels[1][0]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) +         \
194
2788080
                    BLUEVAL(neighbor_pixels[1][1]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
195
196
2788080
            red = BYTE_RANGE(red);
197
2788080
            green = BYTE_RANGE(green);
198
2788080
            blue = BYTE_RANGE(blue);
199
200
2788080
            *put++ = ASSEMBLECOLOR(red, green, blue);
201
        }
202
    }
203
204
101
    return GX_SUCCESS;
205
}
206
207
/**************************************************************************/
208
/*                                                                        */
209
/*  FUNCTION                                               RELEASE        */
210
/*                                                                        */
211
/*    _gx_utility_1555xrgb_pixelmap_alpha_resize          PORTABLE C      */
212
/*                                                           6.1.7        */
213
/*  AUTHOR                                                                */
214
/*                                                                        */
215
/*    Kenneth Maxwell, Microsoft Corporation                              */
216
/*                                                                        */
217
/*  DESCRIPTION                                                           */
218
/*                                                                        */
219
/*    Internal helper function that resize an 1555xrgb format pixelmap    */
220
/*    with alpha.                                                         */
221
/*                                                                        */
222
/*  INPUT                                                                 */
223
/*                                                                        */
224
/*    src                                   The source pixelmap           */
225
/*    destination                           The resized pixelmap to be    */
226
/*                                            returned                    */
227
/*    width                                 New width                     */
228
/*    height                                New height                    */
229
/*                                                                        */
230
/*  OUTPUT                                                                */
231
/*                                                                        */
232
/*    status                                Completion status             */
233
/*                                                                        */
234
/*  CALLS                                                                 */
235
/*                                                                        */
236
/*    _gx_system_memory_allocator                                         */
237
/*                                                                        */
238
/*  CALLED BY                                                             */
239
/*                                                                        */
240
/*    GUIX Internal Code                                                  */
241
/*                                                                        */
242
/**************************************************************************/
243
103
static UINT _gx_utility_1555xrgb_pixelmap_alpha_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
244
{
245
/* The pixelmap resize function is implemented from bilinear interpolation
246
   image scaling algorithm.  */
247
248
USHORT   *get;
249
USHORT   *put;
250
GX_UBYTE *getalpha;
251
GX_UBYTE *putalpha;
252
INT       xdiff;
253
INT       ydiff;
254
INT       xradio;
255
INT       yradio;
256
INT       x;
257
INT       y;
258
INT       xx;
259
INT       yy;
260
USHORT    neighbor_pixels[2][2];
261
GX_COLOR  alpha[4];
262
GX_COLOR  red;
263
GX_COLOR  green;
264
GX_COLOR  blue;
265
266
    /* Calculate scale ratio and enlarge it by 256 times to keep precision.  */
267
103
    xradio = ((src -> gx_pixelmap_width) << 8) / width;
268
103
    yradio = ((src -> gx_pixelmap_height) << 8) / height;
269
270
    /* Fill property values into destination pixelmap structure. */
271
103
    destination -> gx_pixelmap_flags = src -> gx_pixelmap_flags;
272
103
    destination -> gx_pixelmap_format = src -> gx_pixelmap_format;
273
274
103
    destination -> gx_pixelmap_height = (GX_VALUE)height;
275
103
    destination -> gx_pixelmap_width = (GX_VALUE)width;
276
277
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
278
       overflow cannot occur. */
279
103
    destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
280
103
    destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
281
282
    /* Allocate memory to load pixelmap data. */
283
103
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
284
285
103
    if (destination -> gx_pixelmap_data == GX_NULL)
286
    {
287
1
        return GX_SYSTEM_MEMORY_ERROR;
288
    }
289
290
102
    destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
291
292
102
    if (destination -> gx_pixelmap_aux_data == GX_NULL)
293
    {
294
1
        _gx_system_memory_free((void *)destination -> gx_pixelmap_data);
295
1
        return GX_SYSTEM_MEMORY_ERROR;
296
    }
297
298
101
    put = (USHORT *)destination -> gx_pixelmap_data;
299
101
    putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
300
301
    /* Loop through destination's pixel and fill each pixel with
302
       the interpolation of 4 nearest neighboring pixels.*/
303
14434
    for (y = 0; y < height; y++)
304
    {
305
2487353
        for (x = 0; x < width; x++)
306
        {
307
            /* Find the original source pixel that the destination pixel conrespond to. */
308
2473020
            xx = (xradio * x) >> 8;
309
2473020
            yy = (yradio * y) >> 8;
310
311
            /* The coordinates of the original source pixel are truncate value,
312
               calucate their distance between the mathematical coordinates. */
313
2473020
            xdiff = (xradio * x) & 0xff;
314
2473020
            ydiff = (yradio * y) & 0xff;
315
316
2473020
            get = (USHORT *)src -> gx_pixelmap_data;
317
2473020
            get += yy * src -> gx_pixelmap_width;
318
2473020
            get += xx;
319
320
2473020
            getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
321
2473020
            getalpha += yy * src -> gx_pixelmap_width;
322
2473020
            getalpha += xx;
323
324
325
            /* Calculate 4 nearest neighboring pixels around the mathematical point of original pixel. */
326
2473020
            neighbor_pixels[0][0] = *get;
327
2473020
            alpha[0] = *getalpha;
328
329

2473020
            if ((xx < src -> gx_pixelmap_width - 1) && (yy < src -> gx_pixelmap_height - 1))
330
            {
331
2467921
                neighbor_pixels[0][1] = *(get + 1);
332
2467921
                neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
333
2467921
                neighbor_pixels[1][1] = *(get + src -> gx_pixelmap_width + 1);
334
335
2467921
                alpha[1] = *(getalpha + 1);
336
2467921
                alpha[2] = *(getalpha + src -> gx_pixelmap_width);
337
2467921
                alpha[3] = *(getalpha + src -> gx_pixelmap_width + 1);
338
            }
339
            else
340
            {
341
342
5099
                if ((xx == src -> gx_pixelmap_width - 1) &&
343
1411
                    (yy == src -> gx_pixelmap_height - 1))
344
                {
345
                    /* Handle right bottom corder pixel.  */
346
2
                    neighbor_pixels[0][1] = neighbor_pixels[0][0];
347
2
                    neighbor_pixels[1][0] = neighbor_pixels[0][0];
348
2
                    neighbor_pixels[1][1] = neighbor_pixels[0][0];
349
350
2
                    alpha[1] = alpha[0];
351
2
                    alpha[2] = alpha[0];
352
2
                    alpha[3] = alpha[0];
353
                }
354
5097
                else if (xx == src -> gx_pixelmap_width - 1)
355
                {
356
                    /* Handle pixels in right edge.  */
357
1409
                    neighbor_pixels[0][1] = neighbor_pixels[0][0];
358
1409
                    neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
359
1409
                    neighbor_pixels[1][1] = neighbor_pixels[1][0];
360
361
1409
                    alpha[1] = alpha[0];
362
1409
                    alpha[2] = *(getalpha + src -> gx_pixelmap_width);
363
1409
                    alpha[3] = alpha[2];
364
                }
365
                else
366
                {
367
                    /* Handle pixels in bottom edge.  */
368
3688
                    neighbor_pixels[0][1] = *(get + 1);
369
3688
                    neighbor_pixels[1][0] = neighbor_pixels[0][0];
370
3688
                    neighbor_pixels[1][1] = neighbor_pixels[0][1];
371
372
3688
                    alpha[1] = *(getalpha + 1);
373
3688
                    alpha[2] = alpha[0];
374
3688
                    alpha[3] = alpha[1];
375
                }
376
            }
377
378
            /* Calulate pixel values by interpolating 4 neighboring pixels. */
379
2473020
            red = (REDVAL(neighbor_pixels[0][0]) * (alpha[0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
380
2473020
                   REDVAL(neighbor_pixels[0][1]) * (alpha[1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) +         \
381
2473020
                   REDVAL(neighbor_pixels[1][0]) * (alpha[2]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) +         \
382
2473020
                   REDVAL(neighbor_pixels[1][1]) * (alpha[3]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
383
384
2473020
            green = (GREENVAL(neighbor_pixels[0][0]) * (alpha[0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
385
2473020
                     GREENVAL(neighbor_pixels[0][1]) * (alpha[1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) +         \
386
2473020
                     GREENVAL(neighbor_pixels[1][0]) * (alpha[2]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) +         \
387
2473020
                     GREENVAL(neighbor_pixels[1][1]) * (alpha[3]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
388
389
2473020
            blue = (BLUEVAL(neighbor_pixels[0][0]) * (alpha[0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
390
2473020
                    BLUEVAL(neighbor_pixels[0][1]) * (alpha[1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) +         \
391
2473020
                    BLUEVAL(neighbor_pixels[1][0]) * (alpha[2]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) +         \
392
2473020
                    BLUEVAL(neighbor_pixels[1][1]) * (alpha[3]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
393
394
2473020
            alpha[0] = ((alpha[0]) * (256 - (GX_COLOR)xdiff) * (256 - (GX_COLOR)ydiff) + \
395
2473020
                        (alpha[1]) * (GX_COLOR)xdiff * (256 - (GX_COLOR)ydiff) +         \
396
2473020
                        (alpha[2]) * (GX_COLOR)ydiff * (256 - (GX_COLOR)xdiff) +         \
397
2473020
                        (alpha[3]) * (GX_COLOR)xdiff * (GX_COLOR)ydiff) >> 16;
398
399
2473020
            if (alpha[0])
400
            {
401
1060788
                red /= alpha[0];
402
1060788
                green /= alpha[0];
403
1060788
                blue /= alpha[0];
404
            }
405
406
2473020
            alpha[0] = BYTE_RANGE(alpha[0]);
407
2473020
            red = BYTE_RANGE(red);
408
2473020
            green = BYTE_RANGE(green);
409
2473020
            blue = BYTE_RANGE(blue);
410
411
2473020
            *put++ = ASSEMBLECOLOR(red, green, blue);
412
2473020
            *putalpha++ = (GX_UBYTE)alpha[0];
413
        }
414
    }
415
416
101
    return GX_SUCCESS;
417
}
418
419
/**************************************************************************/
420
/*                                                                        */
421
/*  FUNCTION                                               RELEASE        */
422
/*                                                                        */
423
/*    _gx_utility_1555xrgb_pixelmap_resize                PORTABLE C      */
424
/*                                                           6.1          */
425
/*  AUTHOR                                                                */
426
/*                                                                        */
427
/*    Kenneth Maxwell, Microsoft Corporation                              */
428
/*                                                                        */
429
/*  DESCRIPTION                                                           */
430
/*                                                                        */
431
/*    This function resize an 1555xrgb format pixelmap with or without    */
432
/*    alpha channel.                                                      */
433
/*                                                                        */
434
/*  INPUT                                                                 */
435
/*                                                                        */
436
/*    src                                   The source pixelmap           */
437
/*    destination                           The resized pixelmap to be    */
438
/*                                            returned                    */
439
/*    width                                 New width                     */
440
/*    height                                New height                    */
441
/*                                                                        */
442
/*  OUTPUT                                                                */
443
/*                                                                        */
444
/*    status                                Completion status             */
445
/*                                                                        */
446
/*  CALLS                                                                 */
447
/*                                                                        */
448
/*     _gx_utility_1555xrgb_pixelmap_alpha_resize                         */
449
/*                                          Resize 1555xrgb format        */
450
/*                                            pixelmap with alpha         */
451
/*     _gx_utility_1555xrgb_pixelmap_raw_resize                           */
452
/*                                          Resize 1555xrgb format        */
453
/*                                            pixelmap without alpha      */
454
/*                                                                        */
455
/*  CALLED BY                                                             */
456
/*                                                                        */
457
/*    GUIX Internal Code                                                  */
458
/*                                                                        */
459
/**************************************************************************/
460
206
UINT _gx_utility_1555xrgb_pixelmap_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
461
{
462
UINT status;
463
464
206
    if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
465
    {
466
        /* alpha, no compression */
467
468
103
        status = _gx_utility_1555xrgb_pixelmap_alpha_resize(src, destination, width, height);
469
    }
470
    else
471
    {
472
        /* no alpha, no compression */
473
474
103
        status = _gx_utility_1555xrgb_pixelmap_raw_resize(src, destination, width, height);
475
    }
476
477
206
    return status;
478
}