GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_utility_32argb_pixelmap_resize.c Lines: 125 125 100.0 %
Date: 2026-03-06 19:21:09 Branches: 36 36 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) >> 16)
23
#define GREENVAL(_c)   (GX_UBYTE)((_c) >> 8)
24
#define BLUEVAL(_c)    (GX_UBYTE)(_c)
25
26
#define ASSEMBLECOLOR(_r, _g, _b) \
27
    ((GX_COLOR)(((_r) << 16) |    \
28
                ((_g) << 8)) |    \
29
                (_b))
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_32argb_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 uncompressed 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
326
static UINT _gx_utility_32argb_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
GX_COLOR *get;
84
GX_COLOR *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
GX_COLOR  neighbor_pixels[2][2];
94
INT       red;
95
INT       green;
96
INT       blue;
97
98
99
    /* Calculate scale ratio and enlarge it by 256 times to keep precision.  */
100
326
    xradio = ((src -> gx_pixelmap_width) << 8) / width;
101
326
    yradio = ((src -> gx_pixelmap_height) << 8) / height;
102
103
    /* Fill property values into destination pixelmap structure. */
104
326
    destination -> gx_pixelmap_flags = src -> gx_pixelmap_flags;
105
326
    destination -> gx_pixelmap_format = src -> gx_pixelmap_format;
106
107
326
    destination -> gx_pixelmap_height = (GX_VALUE)height;
108
326
    destination -> gx_pixelmap_width = (GX_VALUE)width;
109
110
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
111
       overflow cannot occur. */
112
326
    destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(GX_COLOR);
113
114
    /* Allocate memory for destination pixelmap.  */
115
326
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
116
117
326
    if (destination -> gx_pixelmap_data == GX_NULL)
118
    {
119
2
        return GX_SYSTEM_MEMORY_ERROR;
120
    }
121
122
324
    put = (GX_COLOR *)destination -> gx_pixelmap_data;
123
124
    /* Loop throught destination's pixels and fill each pixel with the interpolation of
125
       4 neighboring pixels. */
126
72176
    for (y = 0; y < height; y++)
127
    {
128
9175974
        for (x = 0; x < width; x++)
129
        {
130
            /* Find the original source pixel that the destination pixel conrespond to. */
131
9104122
            xx = (xradio * x) >> 8;
132
9104122
            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
9104122
            xdiff = (xradio * x) & 0xff;
137
9104122
            ydiff = (yradio * y) & 0xff;
138
139
9104122
            get = (GX_COLOR *)src -> gx_pixelmap_data;
140
9104122
            get += yy * src -> gx_pixelmap_width;
141
9104122
            get += xx;
142
143
            /* Calculate 4 nearest neighboring pixels around the mathematical point of original pixel. */
144
9104122
            neighbor_pixels[0][0] = *get;
145
146

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

11084689
            if ((xx < src -> gx_pixelmap_width - 1) && (yy < src -> gx_pixelmap_height - 1))
310
            {
311
11067159
                neighbor_pixels[0][1] = *(get + 1);
312
11067159
                neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
313
11067159
                neighbor_pixels[1][1] = *(get + src -> gx_pixelmap_width + 1);
314
            }
315
            else
316
            {
317
318
17530
                if ((xx == src -> gx_pixelmap_width - 1) &&
319
12022
                    (yy == src -> gx_pixelmap_height - 1))
320
                {
321
                    /* Hanle pixels in right bottom corner. */
322
12
                    neighbor_pixels[0][1] = neighbor_pixels[0][0];
323
12
                    neighbor_pixels[1][0] = neighbor_pixels[0][0];
324
12
                    neighbor_pixels[1][1] = neighbor_pixels[0][0];
325
                }
326
17518
                else if (xx == src -> gx_pixelmap_width - 1)
327
                {
328
                    /* Handle pixels in right edge. */
329
12010
                    neighbor_pixels[0][1] = neighbor_pixels[0][0];
330
12010
                    neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
331
12010
                    neighbor_pixels[1][1] = neighbor_pixels[1][0];
332
                }
333
                else
334
                {
335
                    /* Handle pixels in bottom edge.  */
336
5508
                    neighbor_pixels[0][1] = *(get + 1);
337
5508
                    neighbor_pixels[1][0] = neighbor_pixels[0][0];
338
5508
                    neighbor_pixels[1][1] = neighbor_pixels[0][1];
339
                }
340
            }
341
342
            /* Calulate pixel values by interpolating 4 neighboring pixels. */
343
11084689
            red = (INT)((REDVAL(neighbor_pixels[0][0]) * (neighbor_pixels[0][0] >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
344
11084689
                         REDVAL(neighbor_pixels[0][1]) * (neighbor_pixels[0][1] >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
345
11084689
                         REDVAL(neighbor_pixels[1][0]) * (neighbor_pixels[1][0] >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
346
11084689
                         REDVAL(neighbor_pixels[1][1]) * (neighbor_pixels[1][1] >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
347
348
11084689
            green = (INT)((GREENVAL(neighbor_pixels[0][0]) * (neighbor_pixels[0][0] >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
349
11084689
                           GREENVAL(neighbor_pixels[0][1]) * (neighbor_pixels[0][1] >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
350
11084689
                           GREENVAL(neighbor_pixels[1][0]) * (neighbor_pixels[1][0] >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
351
11084689
                           GREENVAL(neighbor_pixels[1][1]) * (neighbor_pixels[1][1] >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
352
353
11084689
            blue = (INT)((BLUEVAL(neighbor_pixels[0][0]) * (neighbor_pixels[0][0] >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
354
11084689
                          BLUEVAL(neighbor_pixels[0][1]) * (neighbor_pixels[0][1] >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
355
11084689
                          BLUEVAL(neighbor_pixels[1][0]) * (neighbor_pixels[1][0] >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
356
11084689
                          BLUEVAL(neighbor_pixels[1][1]) * (neighbor_pixels[1][1] >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
357
358
11084689
            alpha = (INT)(((neighbor_pixels[0][0] >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
359
11084689
                           (neighbor_pixels[0][1] >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
360
11084689
                           (neighbor_pixels[1][0] >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
361
11084689
                           (neighbor_pixels[1][1] >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
362
363
11084689
            if (alpha)
364
            {
365
5869656
                red /= alpha;
366
5869656
                green /= alpha;
367
5869656
                blue /= alpha;
368
            }
369
370
11084689
            alpha = BYTE_RANGE(alpha);
371
11084689
            red = BYTE_RANGE(red);
372
11084689
            green = BYTE_RANGE(green);
373
11084689
            blue = BYTE_RANGE(blue);
374
375
11084689
            *put++ = ASSEMBLECOLOR((ULONG)red, (ULONG)green, (ULONG)blue) + ((ULONG)alpha << 24);
376
        }
377
    }
378
379
370
    return GX_SUCCESS;
380
}
381
382
/**************************************************************************/
383
/*                                                                        */
384
/*  FUNCTION                                               RELEASE        */
385
/*                                                                        */
386
/*    _gx_utility_32argb_pixelmap_resize                  PORTABLE C      */
387
/*                                                           6.1          */
388
/*  AUTHOR                                                                */
389
/*                                                                        */
390
/*    Kenneth Maxwell, Microsoft Corporation                              */
391
/*                                                                        */
392
/*  DESCRIPTION                                                           */
393
/*                                                                        */
394
/*    32argb pixelmap resize function that handles uncompress, with or    */
395
/*    alpha channel.                                                      */
396
/*                                                                        */
397
/*  INPUT                                                                 */
398
/*                                                                        */
399
/*    src                                   The source pixelmap           */
400
/*    destination                           The resized pixelmap to be    */
401
/*                                            returned                    */
402
/*    width                                 New width                     */
403
/*    height                                New height                    */
404
/*                                                                        */
405
/*  OUTPUT                                                                */
406
/*                                                                        */
407
/*    status                                Completion status             */
408
/*                                                                        */
409
/*  CALLS                                                                 */
410
/*                                                                        */
411
/*     _gx_utility_32argb_pixelmap_alpha_resize                           */
412
/*     _gx_utility_32argb_pixelmap_raw_resize                             */
413
/*                                                                        */
414
/*  CALLED BY                                                             */
415
/*                                                                        */
416
/*    GUIX Internal Code                                                  */
417
/*                                                                        */
418
/**************************************************************************/
419
697
UINT _gx_utility_32argb_pixelmap_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
420
{
421
UINT status;
422
423
697
    if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
424
    {
425
        /* alpha, no compression */
426
427
371
        status = _gx_utility_32argb_pixelmap_alpha_resize(src, destination, width, height);
428
    }
429
    else
430
    {
431
        /* no compression or alpha */
432
433
326
        status = _gx_utility_32argb_pixelmap_raw_resize(src, destination, width, height);
434
    }
435
436
697
    return status;
437
}
438