GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_utility_32argb_pixelmap_resize.c Lines: 125 125 100.0 %
Date: 2024-12-05 08:52:37 Branches: 36 36 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** GUIX Component                                                        */
16
/**                                                                       */
17
/**   Utility (Utility)                                                   */
18
/**                                                                       */
19
/**************************************************************************/
20
21
#define REDVAL(_c)     (GX_UBYTE)((_c) >> 16)
22
#define GREENVAL(_c)   (GX_UBYTE)((_c) >> 8)
23
#define BLUEVAL(_c)    (GX_UBYTE)(_c)
24
25
#define ASSEMBLECOLOR(_r, _g, _b) \
26
    ((GX_COLOR)(((_r) << 16) |    \
27
                ((_g) << 8)) |    \
28
                (_b))
29
30
#define BYTE_RANGE(_c) _c > 255 ? 255 : _c
31
32
#define GX_SOURCE_CODE
33
34
35
/* Include necessary system files.  */
36
37
#include "gx_api.h"
38
#include "gx_utility.h"
39
#include "gx_system.h"
40
41
/**************************************************************************/
42
/*                                                                        */
43
/*  FUNCTION                                               RELEASE        */
44
/*                                                                        */
45
/*    _gx_utility_32argb_pixelmap_raw_resize              PORTABLE C      */
46
/*                                                           6.1.7        */
47
/*  AUTHOR                                                                */
48
/*                                                                        */
49
/*    Kenneth Maxwell, Microsoft Corporation                              */
50
/*                                                                        */
51
/*  DESCRIPTION                                                           */
52
/*                                                                        */
53
/*    Internal helper function that resize an uncompressed pixelmap       */
54
/*      without alpha.                                                    */
55
/*                                                                        */
56
/*  INPUT                                                                 */
57
/*                                                                        */
58
/*    src                                   The source pixelmap           */
59
/*    destination                           The resized pixelmap to be    */
60
/*                                            returned                    */
61
/*    width                                 New width                     */
62
/*    height                                New height                    */
63
/*                                                                        */
64
/*  OUTPUT                                                                */
65
/*                                                                        */
66
/*    status                                Completion status             */
67
/*                                                                        */
68
/*  CALLS                                                                 */
69
/*                                                                        */
70
/*    _gx_system_memory_allocator                                         */
71
/*                                                                        */
72
/*  CALLED BY                                                             */
73
/*                                                                        */
74
/*    GUIX Internal Code                                                  */
75
/*                                                                        */
76
/*  RELEASE HISTORY                                                       */
77
/*                                                                        */
78
/*    DATE              NAME                      DESCRIPTION             */
79
/*                                                                        */
80
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
81
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
82
/*                                            resulting in version 6.1    */
83
/*  06-02-2021     Kenneth Maxwell          Modified comment(s),          */
84
/*                                            removed unused variable     */
85
/*                                            assignment,                 */
86
/*                                            resulting in version 6.1.7  */
87
/*                                                                        */
88
/**************************************************************************/
89
326
static UINT _gx_utility_32argb_pixelmap_raw_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
90
{
91
/* The pixelmap resize function is implemented from bilinear interpolation
92
   image scaling algorithm.  */
93
94
GX_COLOR *get;
95
GX_COLOR *put;
96
INT       xdiff;
97
INT       ydiff;
98
INT       xradio;
99
INT       yradio;
100
INT       x;
101
INT       y;
102
INT       xx;
103
INT       yy;
104
GX_COLOR  neighbor_pixels[2][2];
105
INT       red;
106
INT       green;
107
INT       blue;
108
109
110
    /* Calculate scale ratio and enlarge it by 256 times to keep precision.  */
111
326
    xradio = ((src -> gx_pixelmap_width) << 8) / width;
112
326
    yradio = ((src -> gx_pixelmap_height) << 8) / height;
113
114
    /* Fill property values into destination pixelmap structure. */
115
326
    destination -> gx_pixelmap_flags = src -> gx_pixelmap_flags;
116
326
    destination -> gx_pixelmap_format = src -> gx_pixelmap_format;
117
118
326
    destination -> gx_pixelmap_height = (GX_VALUE)height;
119
326
    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
326
    destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(GX_COLOR);
124
125
    /* Allocate memory for destination pixelmap.  */
126
326
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
127
128
326
    if (destination -> gx_pixelmap_data == GX_NULL)
129
    {
130
2
        return GX_SYSTEM_MEMORY_ERROR;
131
    }
132
133
324
    put = (GX_COLOR *)destination -> gx_pixelmap_data;
134
135
    /* Loop throught destination's pixels and fill each pixel with the interpolation of
136
       4 neighboring pixels. */
137
72176
    for (y = 0; y < height; y++)
138
    {
139
9175974
        for (x = 0; x < width; x++)
140
        {
141
            /* Find the original source pixel that the destination pixel conrespond to. */
142
9104122
            xx = (xradio * x) >> 8;
143
9104122
            yy = (yradio * y) >> 8;
144
145
            /* The coordinates of the original source pixel are truncate value,
146
               calucate their distance between the mathematical coordinates. */
147
9104122
            xdiff = (xradio * x) & 0xff;
148
9104122
            ydiff = (yradio * y) & 0xff;
149
150
9104122
            get = (GX_COLOR *)src -> gx_pixelmap_data;
151
9104122
            get += yy * src -> gx_pixelmap_width;
152
9104122
            get += xx;
153
154
            /* Calculate 4 nearest neighboring pixels around the mathematical point of original pixel. */
155
9104122
            neighbor_pixels[0][0] = *get;
156
157

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

10930459
            if ((xx < src -> gx_pixelmap_width - 1) && (yy < src -> gx_pixelmap_height - 1))
333
            {
334
10912929
                neighbor_pixels[0][1] = *(get + 1);
335
10912929
                neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
336
10912929
                neighbor_pixels[1][1] = *(get + src -> gx_pixelmap_width + 1);
337
            }
338
            else
339
            {
340
341
17530
                if ((xx == src -> gx_pixelmap_width - 1) &&
342
12022
                    (yy == src -> gx_pixelmap_height - 1))
343
                {
344
                    /* Hanle pixels in right bottom corner. */
345
12
                    neighbor_pixels[0][1] = neighbor_pixels[0][0];
346
12
                    neighbor_pixels[1][0] = neighbor_pixels[0][0];
347
12
                    neighbor_pixels[1][1] = neighbor_pixels[0][0];
348
                }
349
17518
                else if (xx == src -> gx_pixelmap_width - 1)
350
                {
351
                    /* Handle pixels in right edge. */
352
12010
                    neighbor_pixels[0][1] = neighbor_pixels[0][0];
353
12010
                    neighbor_pixels[1][0] = *(get + src -> gx_pixelmap_width);
354
12010
                    neighbor_pixels[1][1] = neighbor_pixels[1][0];
355
                }
356
                else
357
                {
358
                    /* Handle pixels in bottom edge.  */
359
5508
                    neighbor_pixels[0][1] = *(get + 1);
360
5508
                    neighbor_pixels[1][0] = neighbor_pixels[0][0];
361
5508
                    neighbor_pixels[1][1] = neighbor_pixels[0][1];
362
                }
363
            }
364
365
            /* Calulate pixel values by interpolating 4 neighboring pixels. */
366
10930459
            red = (INT)((REDVAL(neighbor_pixels[0][0]) * (neighbor_pixels[0][0] >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
367
10930459
                         REDVAL(neighbor_pixels[0][1]) * (neighbor_pixels[0][1] >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
368
10930459
                         REDVAL(neighbor_pixels[1][0]) * (neighbor_pixels[1][0] >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
369
10930459
                         REDVAL(neighbor_pixels[1][1]) * (neighbor_pixels[1][1] >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
370
371
10930459
            green = (INT)((GREENVAL(neighbor_pixels[0][0]) * (neighbor_pixels[0][0] >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
372
10930459
                           GREENVAL(neighbor_pixels[0][1]) * (neighbor_pixels[0][1] >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
373
10930459
                           GREENVAL(neighbor_pixels[1][0]) * (neighbor_pixels[1][0] >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
374
10930459
                           GREENVAL(neighbor_pixels[1][1]) * (neighbor_pixels[1][1] >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
375
376
10930459
            blue = (INT)((BLUEVAL(neighbor_pixels[0][0]) * (neighbor_pixels[0][0] >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
377
10930459
                          BLUEVAL(neighbor_pixels[0][1]) * (neighbor_pixels[0][1] >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
378
10930459
                          BLUEVAL(neighbor_pixels[1][0]) * (neighbor_pixels[1][0] >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
379
10930459
                          BLUEVAL(neighbor_pixels[1][1]) * (neighbor_pixels[1][1] >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
380
381
10930459
            alpha = (INT)(((neighbor_pixels[0][0] >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
382
10930459
                           (neighbor_pixels[0][1] >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
383
10930459
                           (neighbor_pixels[1][0] >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
384
10930459
                           (neighbor_pixels[1][1] >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
385
386
10930459
            if (alpha)
387
            {
388
5758659
                red /= alpha;
389
5758659
                green /= alpha;
390
5758659
                blue /= alpha;
391
            }
392
393
10930459
            alpha = BYTE_RANGE(alpha);
394
10930459
            red = BYTE_RANGE(red);
395
10930459
            green = BYTE_RANGE(green);
396
10930459
            blue = BYTE_RANGE(blue);
397
398
10930459
            *put++ = ASSEMBLECOLOR((ULONG)red, (ULONG)green, (ULONG)blue) + ((ULONG)alpha << 24);
399
        }
400
    }
401
402
367
    return GX_SUCCESS;
403
}
404
405
/**************************************************************************/
406
/*                                                                        */
407
/*  FUNCTION                                               RELEASE        */
408
/*                                                                        */
409
/*    _gx_utility_32argb_pixelmap_resize                  PORTABLE C      */
410
/*                                                           6.1          */
411
/*  AUTHOR                                                                */
412
/*                                                                        */
413
/*    Kenneth Maxwell, Microsoft Corporation                              */
414
/*                                                                        */
415
/*  DESCRIPTION                                                           */
416
/*                                                                        */
417
/*    32argb pixelmap resize function that handles uncompress, with or    */
418
/*    alpha channel.                                                      */
419
/*                                                                        */
420
/*  INPUT                                                                 */
421
/*                                                                        */
422
/*    src                                   The source pixelmap           */
423
/*    destination                           The resized pixelmap to be    */
424
/*                                            returned                    */
425
/*    width                                 New width                     */
426
/*    height                                New height                    */
427
/*                                                                        */
428
/*  OUTPUT                                                                */
429
/*                                                                        */
430
/*    status                                Completion status             */
431
/*                                                                        */
432
/*  CALLS                                                                 */
433
/*                                                                        */
434
/*     _gx_utility_32argb_pixelmap_alpha_resize                           */
435
/*     _gx_utility_32argb_pixelmap_raw_resize                             */
436
/*                                                                        */
437
/*  CALLED BY                                                             */
438
/*                                                                        */
439
/*    GUIX Internal Code                                                  */
440
/*                                                                        */
441
/*  RELEASE HISTORY                                                       */
442
/*                                                                        */
443
/*    DATE              NAME                      DESCRIPTION             */
444
/*                                                                        */
445
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
446
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
447
/*                                            resulting in version 6.1    */
448
/*                                                                        */
449
/**************************************************************************/
450
694
UINT _gx_utility_32argb_pixelmap_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
451
{
452
UINT status;
453
454
694
    if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
455
    {
456
        /* alpha, no compression */
457
458
368
        status = _gx_utility_32argb_pixelmap_alpha_resize(src, destination, width, height);
459
    }
460
    else
461
    {
462
        /* no compression or alpha */
463
464
326
        status = _gx_utility_32argb_pixelmap_raw_resize(src, destination, width, height);
465
    }
466
467
694
    return status;
468
}
469