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