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