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 /**************************************************************************/
30 /*                                                                        */
31 /*  FUNCTION                                               RELEASE        */
32 /*                                                                        */
33 /*    _gx_utility_4bpp_pixelmap_raw_resize                PORTABLE C      */
34 /*                                                           6.1.7        */
35 /*  AUTHOR                                                                */
36 /*                                                                        */
37 /*    Kenneth Maxwell, Microsoft Corporation                              */
38 /*                                                                        */
39 /*  DESCRIPTION                                                           */
40 /*                                                                        */
41 /*    4bpp pixelmap resize function that handles uncompress, with or      */
42 /*    transparent channel.                                                */
43 /*                                                                        */
44 /*  INPUT                                                                 */
45 /*                                                                        */
46 /*    src                                   The source pixelmap           */
47 /*    destination                           The resized pixelmap to be    */
48 /*                                            returned                    */
49 /*    width                                 New width                     */
50 /*    height                                New height                    */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    status                                Completion status             */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _gx_system_memory_allocator           Memory Allocation routine     */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    _gx_utility_4bpp_pixelmap_resize                                    */
63 /*                                                                        */
64 /*  RELEASE HISTORY                                                       */
65 /*                                                                        */
66 /*    DATE              NAME                      DESCRIPTION             */
67 /*                                                                        */
68 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
69 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
70 /*                                            resulting in version 6.1    */
71 /*  06-02-2021     Kenneth Maxwell          Modified comment(s),          */
72 /*                                            removed unused variable     */
73 /*                                            assignment,                 */
74 /*                                            resulting in version 6.1.7  */
75 /*                                                                        */
76 /**************************************************************************/
_gx_utility_4bpp_pixelmap_raw_resize(GX_PIXELMAP * src,GX_PIXELMAP * destination,INT width,INT height)77 static UINT _gx_utility_4bpp_pixelmap_raw_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
78 {
79 /* The pixelmap resize function is implemented from nearest neighbor
80    image scaling algorithm.  */
81 
82 GX_UBYTE *get;
83 GX_UBYTE *put;
84 GX_UBYTE *putrow;
85 GX_UBYTE  putmask;
86 INT       putstride;
87 INT       getstride;
88 GX_UBYTE  pixel;
89 INT       xradio;
90 INT       yradio;
91 INT       x;
92 INT       y;
93 INT       xx;
94 INT       yy;
95 
96     /* Calculate scale ratio and enlarge it by 256 times to keep precision.  */
97     xradio = ((src -> gx_pixelmap_width) << 8) / width;
98     yradio = ((src -> gx_pixelmap_height) << 8) / height;
99 
100     putstride = (width + 1) >> 1;
101     getstride = (src -> gx_pixelmap_width + 1) >> 1;
102 
103     /* Fill property values into destination pixelmap structure. */
104     destination -> gx_pixelmap_flags = src -> gx_pixelmap_flags;
105     destination -> gx_pixelmap_format = src -> gx_pixelmap_format;
106     destination -> gx_pixelmap_transparent_color = src -> gx_pixelmap_transparent_color;
107     destination -> gx_pixelmap_version_major = src -> gx_pixelmap_version_major;
108     destination -> gx_pixelmap_version_minor = src -> gx_pixelmap_version_minor;
109 
110     destination -> gx_pixelmap_height = (GX_VALUE)height;
111     destination -> gx_pixelmap_width = (GX_VALUE)width;
112 
113     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
114        overflow cannot occur. */
115     destination -> gx_pixelmap_data_size = (UINT)(height * putstride) * sizeof(GX_UBYTE);
116 
117     /* Allocate memory to load pixelmap data. */
118     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
119 
120     if (destination -> gx_pixelmap_data == GX_NULL)
121     {
122         return GX_SYSTEM_MEMORY_ERROR;
123     }
124 
125     putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
126 
127     /* Loop through destination's pixel and fill each pixel with the nearest neighbor.  */
128     for (y = 0; y < height; y++)
129     {
130         put = putrow;
131         putmask = 0xf0;
132         for (x = 0; x < width; x++)
133         {
134             xx = (xradio * x) >> 8;
135             yy = (yradio * y) >> 8;
136 
137             get = (GX_UBYTE *)src -> gx_pixelmap_data;
138             get += yy * getstride;
139             get += xx >> 1;
140             if (xx & 1)
141             {
142                 pixel = *get & 0x0f;
143             }
144             else
145             {
146                 pixel = *get >> 4;
147             }
148             pixel |= (GX_UBYTE)(pixel << 4);
149 
150             *put &= (GX_UBYTE)(~putmask);
151             *put |= putmask & pixel;
152 
153             putmask >>= 4;
154             if (putmask == 0)
155             {
156                 put++;
157                 putmask = 0xf0;
158             }
159         }
160         putrow += putstride;
161     }
162 
163     return GX_SUCCESS;
164 }
165 /**************************************************************************/
166 /*                                                                        */
167 /*  FUNCTION                                               RELEASE        */
168 /*                                                                        */
169 /*    _gx_utility_4bpp_pixelmap_transparent_resize        PORTABLE C      */
170 /*                                                           6.1          */
171 /*  AUTHOR                                                                */
172 /*                                                                        */
173 /*    Kenneth Maxwell, Microsoft Corporation                              */
174 /*                                                                        */
175 /*  DESCRIPTION                                                           */
176 /*                                                                        */
177 /*    4bpp pixelmap resize function that handles uncompress, with or      */
178 /*    transparent channel.                                                */
179 /*                                                                        */
180 /*  INPUT                                                                 */
181 /*                                                                        */
182 /*    src                                   The source pixelmap           */
183 /*    destination                           The resized pixelmap to be    */
184 /*                                            returned                    */
185 /*    width                                 New width                     */
186 /*    height                                New height                    */
187 /*                                                                        */
188 /*  OUTPUT                                                                */
189 /*                                                                        */
190 /*    status                                Completion status             */
191 /*                                                                        */
192 /*  CALLS                                                                 */
193 /*                                                                        */
194 /*    _gx_system_memory_allocator           Memory Allocation routine     */
195 /*                                                                        */
196 /*  CALLED BY                                                             */
197 /*                                                                        */
198 /*    GUIX Internal Code                                                  */
199 /*                                                                        */
200 /*  RELEASE HISTORY                                                       */
201 /*                                                                        */
202 /*    DATE              NAME                      DESCRIPTION             */
203 /*                                                                        */
204 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
205 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
206 /*                                            resulting in version 6.1    */
207 /*                                                                        */
208 /**************************************************************************/
_gx_utility_4bpp_pixelmap_transparent_resize(GX_PIXELMAP * src,GX_PIXELMAP * destination,INT width,INT height)209 static UINT _gx_utility_4bpp_pixelmap_transparent_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
210 {
211 /* The pixelmap resize function is implemented from nearest neighbor
212    image scaling algorithm.  */
213 GX_UBYTE *get;
214 GX_UBYTE *getaux;
215 GX_UBYTE *put;
216 GX_UBYTE *putrow;
217 GX_UBYTE *putaux;
218 GX_UBYTE *putauxrow;
219 GX_UBYTE  putmask;
220 INT       putstride;
221 INT       putauxstride;
222 INT       getstride;
223 INT       getauxstride;
224 GX_UBYTE  transmask;
225 GX_UBYTE  putauxmask;
226 GX_UBYTE  pixel;
227 INT       xradio;
228 INT       yradio;
229 INT       x;
230 INT       y;
231 INT       xx;
232 INT       yy;
233 
234     /* Calculate scale ratio and enlarge it by 256 times to keep precision.  */
235     xradio = ((src -> gx_pixelmap_width) << 8) / width;
236     yradio = ((src -> gx_pixelmap_height) << 8) / height;
237 
238     putstride = (width + 1) >> 1;
239     putauxstride = (width + 7) >> 3;
240     getstride = (src -> gx_pixelmap_width + 1) >> 1;
241     getauxstride = (src -> gx_pixelmap_width + 7) >> 3;
242 
243     /* Fill property values into destination pixelmap structure. */
244     destination -> gx_pixelmap_flags = src -> gx_pixelmap_flags;
245     destination -> gx_pixelmap_format = src -> gx_pixelmap_format;
246     destination -> gx_pixelmap_transparent_color = src -> gx_pixelmap_transparent_color;
247     destination -> gx_pixelmap_version_major = src -> gx_pixelmap_version_major;
248     destination -> gx_pixelmap_version_minor = src -> gx_pixelmap_version_minor;
249 
250     destination -> gx_pixelmap_height = (GX_VALUE)height;
251     destination -> gx_pixelmap_width = (GX_VALUE)width;
252 
253     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
254        overflow cannot occur. */
255     destination -> gx_pixelmap_data_size = (UINT)(height * putstride) * sizeof(GX_UBYTE);
256 
257     /* Allocate memory to load pixelmap data. */
258     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
259 
260     if (destination -> gx_pixelmap_data == GX_NULL)
261     {
262         return GX_SYSTEM_MEMORY_ERROR;
263     }
264 
265     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
266        overflow cannot occur. */
267     destination -> gx_pixelmap_aux_data_size = (UINT)(height * putauxstride) * sizeof(GX_UBYTE);
268     destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
269 
270     if (destination -> gx_pixelmap_aux_data == GX_NULL)
271     {
272         _gx_system_memory_free((void *)destination -> gx_pixelmap_data);
273         return GX_SYSTEM_MEMORY_ERROR;
274     }
275 
276     putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
277     putauxrow = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
278 
279     /* Loop through destination's pixel and fill each pixel with the nearest neighbor.  */
280     for (y = 0; y < height; y++)
281     {
282         put = putrow;
283         putaux = putauxrow;
284         putmask = 0xf0;
285         putauxmask = 0x80;
286         for (x = 0; x < width; x++)
287         {
288             xx = (xradio * x) >> 8;
289             yy = (yradio * y) >> 8;
290 
291             /* set bits first. */
292             *put &= (GX_UBYTE)(~putmask);
293             getaux = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
294             getaux += yy * getauxstride;
295             getaux += xx >> 3;
296 
297             transmask = (GX_UBYTE)(0x80 >> (xx & 0x07));
298             if (transmask & (*getaux))
299             {
300                 /* set tranparent aux bit first. */
301                 *putaux |= putauxmask;
302             }
303             else
304             {
305                 *putaux &= (GX_UBYTE)(~putauxmask);
306 
307                 /* get pixel data */
308                 get = (GX_UBYTE *)src -> gx_pixelmap_data;
309                 get += yy * getstride;
310                 get += xx >> 1;
311                 if (xx & 1)
312                 {
313                     pixel = *get & 0x0f;
314                 }
315                 else
316                 {
317                     pixel = *get >> 4;
318                 }
319                 pixel |= (GX_UBYTE)(pixel << 4);
320                 *put |= putmask & pixel;
321             }
322             putauxmask >>= 1;
323             if (putauxmask == 0)
324             {
325                 putauxmask = 0x80;
326                 putaux++;
327             }
328 
329             putmask >>= 4;
330             if (putmask == 0)
331             {
332                 put++;
333                 putmask = 0xf0;
334             }
335         }
336         putrow += putstride;
337         putauxrow += putauxstride;
338     }
339 
340     return GX_SUCCESS;
341 }
342 /**************************************************************************/
343 /*                                                                        */
344 /*  FUNCTION                                               RELEASE        */
345 /*                                                                        */
346 /*    _gx_utility_4bpp_pixelmap_resize                    PORTABLE C      */
347 /*                                                           6.1          */
348 /*  AUTHOR                                                                */
349 /*                                                                        */
350 /*    Kenneth Maxwell, Microsoft Corporation                              */
351 /*                                                                        */
352 /*  DESCRIPTION                                                           */
353 /*                                                                        */
354 /*    4bpp pixelmap resize function that handles uncompress, with or      */
355 /*    without transparent channel.                                        */
356 /*                                                                        */
357 /*  INPUT                                                                 */
358 /*                                                                        */
359 /*    src                                   The source pixelmap           */
360 /*    destination                           The resized pixelmap to be    */
361 /*                                            returned                    */
362 /*    width                                 New width                     */
363 /*    height                                New height                    */
364 /*                                                                        */
365 /*  OUTPUT                                                                */
366 /*                                                                        */
367 /*    status                                Completion status             */
368 /*                                                                        */
369 /*  CALLS                                                                 */
370 /*                                                                        */
371 /*    _gx_utility_4bpp_pixelmap_transparent_resize                        */
372 /*                                          Real pixelmap resize routine  */
373 /*    _gx_utility_4bpp_pixelmap_raw_resize  Real pixelmap resize routine  */
374 /*                                                                        */
375 /*  CALLED BY                                                             */
376 /*                                                                        */
377 /*    GUIX Internal Code                                                  */
378 /*                                                                        */
379 /*  RELEASE HISTORY                                                       */
380 /*                                                                        */
381 /*    DATE              NAME                      DESCRIPTION             */
382 /*                                                                        */
383 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
384 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
385 /*                                            resulting in version 6.1    */
386 /*                                                                        */
387 /**************************************************************************/
_gx_utility_4bpp_pixelmap_resize(GX_PIXELMAP * src,GX_PIXELMAP * destination,INT width,INT height)388 UINT _gx_utility_4bpp_pixelmap_resize(GX_PIXELMAP *src, GX_PIXELMAP *destination, INT width, INT height)
389 {
390 UINT status;
391 
392     if (src -> gx_pixelmap_flags & GX_PIXELMAP_TRANSPARENT)
393     {
394         /* transparent, no compression */
395         status = _gx_utility_4bpp_pixelmap_transparent_resize(src, destination, width, height);
396     }
397     else
398     {
399         /* no compression or alpha */
400         status = _gx_utility_4bpp_pixelmap_raw_resize(src, destination, width, height);
401     }
402 
403     return status;
404 }
405 
406