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 /** Image Reader Management(Image Reader) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_image_reader.h"
28 #include "gx_system.h"
29
30 #if defined(GX_SOFTWARE_DECODER_SUPPORT)
31
32 #define PIXEL_CMP(_p1, _p2) \
33 (_p1.gx_pixel_alpha == _p2.gx_pixel_alpha) && \
34 (_p1.gx_pixel_red == _p2.gx_pixel_red) && \
35 (_p1.gx_pixel_green == _p2.gx_pixel_green) && \
36 (_p1.gx_pixel_blue == _p2.gx_pixel_blue)
37
38 /**************************************************************************/
39 /* */
40 /* FUNCTION RELEASE */
41 /* */
42 /* _gx_image_reader_rle_count_location_get PORTABLE C */
43 /* 6.1 */
44 /* AUTHOR */
45 /* */
46 /* Kenneth Maxwell, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function retrieves the count put position. */
51 /* */
52 /* INPUT */
53 /* */
54 /* image_reader Image reader control block. */
55 /* put_count Retrieved count put position. */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* status Completion status */
60 /* */
61 /* CALLS */
62 /* */
63 /* None */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* _gx_image_reader_rle_one_row_encode */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
74 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
75 /* resulting in version 6.1 */
76 /* */
77 /**************************************************************************/
_gx_image_reader_rle_count_location_get(GX_IMAGE_READER * image_reader,GX_UBYTE ** put_count)78 static UINT _gx_image_reader_rle_count_location_get(GX_IMAGE_READER *image_reader, GX_UBYTE **put_count)
79 {
80 switch (image_reader -> gx_image_reader_color_format)
81 {
82 case GX_COLOR_FORMAT_32ARGB:
83 case GX_COLOR_FORMAT_24XRGB:
84 (*put_count) = image_reader -> gx_image_reader_putauxdata++;
85 break;
86
87 case GX_COLOR_FORMAT_565RGB:
88 case GX_COLOR_FORMAT_1555XRGB:
89 if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_ALPHA)
90 {
91 (*put_count) = image_reader -> gx_image_reader_putdata;
92 }
93 else
94 {
95 (*put_count) = image_reader -> gx_image_reader_putdata;
96 image_reader -> gx_image_reader_putdata += 2;
97 }
98 break;
99
100 case GX_COLOR_FORMAT_4444ARGB:
101 (*put_count) = image_reader -> gx_image_reader_putdata;
102 image_reader -> gx_image_reader_putdata += 2;
103 break;
104
105 case GX_COLOR_FORMAT_8BIT_GRAY:
106 case GX_COLOR_FORMAT_8BIT_ALPHAMAP:
107 case GX_COLOR_FORMAT_8BIT_PALETTE:
108 (*put_count) = image_reader -> gx_image_reader_putdata++;
109 break;
110
111 case GX_COLOR_FORMAT_4BIT_GRAY:
112 (*put_count) = image_reader -> gx_image_reader_putauxdata++;
113 break;
114
115 case GX_COLOR_FORMAT_MONOCHROME:
116 (*put_count) = image_reader -> gx_image_reader_putdata;
117 break;
118
119 default:
120 return GX_NOT_SUPPORTED;
121 }
122
123 return GX_SUCCESS;
124 }
125
126
127 /**************************************************************************/
128 /* */
129 /* FUNCTION RELEASE */
130 /* */
131 /* _gx_image_reader_rle_count_write PORTABLE C */
132 /* 6.1 */
133 /* AUTHOR */
134 /* */
135 /* Kenneth Maxwell, Microsoft Corporation */
136 /* */
137 /* DESCRIPTION */
138 /* */
139 /* This function writes repeat count to output pixelmap data structure.*/
140 /* */
141 /* INPUT */
142 /* */
143 /* image_reader Image reader control block. */
144 /* count The number of pixels that */
145 /* follows. */
146 /* put_count The position to put "count". */
147 /* repeat Wheather the following pixels */
148 /* are repeated or not. */
149 /* */
150 /* OUTPUT */
151 /* */
152 /* status Completion status */
153 /* */
154 /* CALLS */
155 /* */
156 /* None */
157 /* */
158 /* CALLED BY */
159 /* */
160 /* _gx_image_reader_rle_one_row_encode */
161 /* */
162 /* RELEASE HISTORY */
163 /* */
164 /* DATE NAME DESCRIPTION */
165 /* */
166 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
167 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
168 /* resulting in version 6.1 */
169 /* */
170 /**************************************************************************/
_gx_image_reader_rle_count_write(GX_IMAGE_READER * image_reader,INT * count,GX_UBYTE * put_count,GX_BOOL repeat)171 static UINT _gx_image_reader_rle_count_write(GX_IMAGE_READER *image_reader, INT *count,
172 GX_UBYTE *put_count, GX_BOOL repeat)
173 {
174 INT write_count;
175
176 write_count = (*count) - 1;
177
178 switch (image_reader -> gx_image_reader_color_format)
179 {
180 case GX_COLOR_FORMAT_565RGB:
181 case GX_COLOR_FORMAT_1555XRGB:
182 if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_ALPHA)
183 {
184 if (write_count > 127)
185 {
186 write_count = 127;
187 }
188
189 if (repeat)
190 {
191 write_count |= 0x80;
192 }
193
194 if (!image_reader -> gx_image_reader_size_testing)
195 {
196 *put_count = (GX_UBYTE)write_count;
197 }
198
199 (*count) = (write_count & 0x7f) + 1;
200 }
201 else
202 {
203 if (repeat)
204 {
205 write_count |= 0x8000;
206 }
207
208 if (!image_reader -> gx_image_reader_size_testing)
209 {
210 *((USHORT *)put_count) = (USHORT)write_count;
211 }
212
213 (*count) = (write_count & 0x7fff) + 1;
214 }
215 break;
216
217 case GX_COLOR_FORMAT_4444ARGB:
218 if (repeat)
219 {
220 write_count |= 0x8000;
221 }
222
223 if (!image_reader -> gx_image_reader_size_testing)
224 {
225 *((USHORT *)put_count) = (USHORT)write_count;
226 }
227
228 *count = (write_count & 0x7fff) + 1;
229 break;
230
231 case GX_COLOR_FORMAT_MONOCHROME:
232 if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_ALPHA)
233 {
234 if (write_count > 0x1f)
235 {
236 write_count = 0x1f;
237 }
238 if (repeat)
239 {
240 write_count |= 0x20;
241 }
242 if (!image_reader -> gx_image_reader_size_testing)
243 {
244 *put_count |= (GX_UBYTE)(write_count << 2);
245 }
246
247 (*count) = (write_count & 0x1f) + 1;
248 }
249 else
250 {
251 if (write_count > 0x3f)
252 {
253 write_count = 0x3f;
254 }
255 if (repeat)
256 {
257 write_count |= 0x40;
258 }
259 if (!image_reader -> gx_image_reader_size_testing)
260 {
261 (*put_count) |= (GX_UBYTE)(write_count << 1);
262 }
263
264 (*count) = (write_count & 0x3f) + 1;
265 }
266 break;
267
268 case GX_COLOR_FORMAT_4BIT_GRAY:
269 default:
270 if (write_count > 127)
271 {
272 write_count = 127;
273 }
274
275 if (repeat)
276 {
277 write_count |= 0x80;
278 }
279
280 if (!image_reader -> gx_image_reader_size_testing)
281 {
282 (*put_count) = (GX_UBYTE)write_count;
283 }
284
285 (*count) = (write_count & 0x7f) + 1;
286 break;
287 }
288
289 return GX_SUCCESS;
290 }
291
292 /**************************************************************************/
293 /* */
294 /* FUNCTION RELEASE */
295 /* */
296 /* _gx_image_reader_rle_duplicates_count PORTABLE C */
297 /* 6.1 */
298 /* AUTHOR */
299 /* */
300 /* Kenneth Maxwell, Microsoft Corporation */
301 /* */
302 /* DESCRIPTION */
303 /* */
304 /* This function calculates the number of duplicate pixels. */
305 /* */
306 /* INPUT */
307 /* */
308 /* image_reader Image reader control block. */
309 /* index Position of the pixel to */
310 /* calcualte from. */
311 /* repeat_counts The number of duplicate pixels.*/
312 /* */
313 /* OUTPUT */
314 /* */
315 /* Completion status */
316 /* */
317 /* CALLS */
318 /* */
319 /* None */
320 /* */
321 /* CALLED BY */
322 /* */
323 /* _gx_image_reader_rle_one_row_encode */
324 /* */
325 /* RELEASE HISTORY */
326 /* */
327 /* DATE NAME DESCRIPTION */
328 /* */
329 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
330 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
331 /* resulting in version 6.1 */
332 /* */
333 /**************************************************************************/
_gx_image_reader_rle_duplicates_count(GX_IMAGE_READER * image_reader,INT index,INT * repeat_counts)334 static UINT _gx_image_reader_rle_duplicates_count(GX_IMAGE_READER *image_reader, INT index, INT *repeat_counts)
335 {
336 UINT width;
337 INT duplicates = 1;
338 GX_PIXEL pre_pixel;
339 GX_PIXEL cur_pixel;
340
341
342 image_reader -> gx_image_reader_pixel_read(image_reader, index++, &pre_pixel);
343
344 width = image_reader -> gx_image_reader_image_width;
345
346 while ((UINT)index < width)
347 {
348 image_reader -> gx_image_reader_pixel_read(image_reader, index, &cur_pixel);
349
350 if (PIXEL_CMP(pre_pixel, cur_pixel))
351 {
352 duplicates++;
353 }
354 else
355 {
356 break;
357 }
358 index++;
359 }
360
361 (*repeat_counts) = duplicates;
362
363 return GX_SUCCESS;
364 }
365
366 /**************************************************************************/
367 /* */
368 /* FUNCTION RELEASE */
369 /* */
370 /* _gx_image_reader_rle_one_row_encode PORTABLE C */
371 /* 6.1 */
372 /* AUTHOR */
373 /* */
374 /* Kenneth Maxwell, Microsoft Corporation */
375 /* */
376 /* DESCRIPTION */
377 /* */
378 /* This funcitons encodes one row of the input pixelmap. */
379 /* */
380 /* INPUT */
381 /* */
382 /* image_reader Image reader control block. */
383 /* */
384 /* OUTPUT */
385 /* */
386 /* status Completion status */
387 /* */
388 /* CALLS */
389 /* */
390 /* _gx_image_reader_rle_duplicates_count Calculate the number of */
391 /* duplicate pixels */
392 /* _gx_image_reader_rle_count_write Write out duplicated pixel */
393 /* count */
394 /* _gx_image_reader_rle_count_location_get */
395 /* Retrieve the address to put */
396 /* duplicated pixel count */
397 /* */
398 /* */
399 /* CALLED BY */
400 /* */
401 /* _gx_image_reader_rle_encode */
402 /* */
403 /* RELEASE HISTORY */
404 /* */
405 /* DATE NAME DESCRIPTION */
406 /* */
407 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
408 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
409 /* resulting in version 6.1 */
410 /* */
411 /**************************************************************************/
_gx_image_reader_rle_one_row_encode(GX_IMAGE_READER * image_reader)412 static UINT _gx_image_reader_rle_one_row_encode(GX_IMAGE_READER *image_reader)
413 {
414 UINT status = GX_SUCCESS;
415 UINT col = 0;
416 INT raw_count = 0;
417 INT count = 0;
418 GX_UBYTE *putCount = GX_NULL;
419 UINT width;
420 GX_PIXEL pixel;
421
422 width = image_reader -> gx_image_reader_image_width;
423
424 while (col < width)
425 {
426 /* Calculate the number of duplicate pixels. */
427 _gx_image_reader_rle_duplicates_count(image_reader, (INT)col, &count);
428
429 if (count >= 3)
430 {
431 if (raw_count)
432 {
433 _gx_image_reader_rle_count_write(image_reader, &raw_count, putCount, GX_FALSE);
434 }
435
436 /* Retrieve the count put position. */
437 status = _gx_image_reader_rle_count_location_get(image_reader, &putCount);
438
439 if (status != GX_SUCCESS)
440 {
441 return status;
442 }
443
444 /* Write count. */
445 _gx_image_reader_rle_count_write(image_reader, &count, putCount, GX_TRUE);
446
447 image_reader -> gx_image_reader_pixel_read(image_reader, (INT)col, &pixel);
448
449 /* Write pixel value. */
450 image_reader -> gx_image_reader_pixel_write(image_reader, &pixel);
451
452 col += (UINT)count;
453 raw_count = 0;
454 }
455 else
456 {
457
458 if (!raw_count)
459 {
460 status = _gx_image_reader_rle_count_location_get(image_reader, &putCount);
461
462 if (status != GX_SUCCESS)
463 {
464 return status;
465 }
466 }
467
468 raw_count++;
469
470 image_reader -> gx_image_reader_pixel_read(image_reader, (INT)col, &pixel);
471
472 /* Write pixel value. */
473 image_reader -> gx_image_reader_pixel_write(image_reader, &pixel);
474
475 col++;
476
477 if (raw_count == 128 || col == width)
478 {
479 _gx_image_reader_rle_count_write(image_reader, &raw_count, putCount, GX_FALSE);
480
481 raw_count = 0;
482 }
483 }
484 }
485
486 return status;
487 }
488
489 /**************************************************************************/
490 /* */
491 /* FUNCTION RELEASE */
492 /* */
493 /* _gx_image_reader_rle_encode_size_get PORTABLE C */
494 /* 6.1 */
495 /* AUTHOR */
496 /* */
497 /* Kenneth Maxwell, Microsoft Corporation */
498 /* */
499 /* DESCRIPTION */
500 /* */
501 /* This function gets the size of encoded pixelmap. */
502 /* */
503 /* INPUT */
504 /* */
505 /* image_reader Image reader control block. */
506 /* datasize Retrieved data size. */
507 /* auxsize Retrieved aux data size. */
508 /* */
509 /* OUTPUT */
510 /* */
511 /* Completion status */
512 /* */
513 /* CALLS */
514 /* */
515 /* _gx_image_reader_rle_one_row_encode Process one row encoding */
516 /* */
517 /* CALLED BY */
518 /* */
519 /* _gx_image_reader_rle_colorspace_convert */
520 /* */
521 /* RELEASE HISTORY */
522 /* */
523 /* DATE NAME DESCRIPTION */
524 /* */
525 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
526 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
527 /* resulting in version 6.1 */
528 /* */
529 /**************************************************************************/
_gx_image_reader_rle_encode_size_get(GX_IMAGE_READER * image_reader,UINT * data_size,UINT * aux_size)530 UINT _gx_image_reader_rle_encode_size_get(GX_IMAGE_READER *image_reader, UINT *data_size, UINT *aux_size)
531 {
532 UINT status = GX_SUCCESS;
533 UINT row;
534 UINT height;
535 UINT width;
536 UINT aux_stride;
537
538
539 height = image_reader -> gx_image_reader_image_height;
540 width = image_reader -> gx_image_reader_image_width;
541 aux_stride = width;
542
543 /* Process rle encode logic, but not output compressed data. */
544 image_reader -> gx_image_reader_size_testing = GX_TRUE;
545 image_reader -> gx_image_reader_putdata = GX_NULL;
546 image_reader -> gx_image_reader_putauxdata = GX_NULL;
547
548 switch (image_reader -> gx_image_reader_color_format)
549 {
550 case GX_COLOR_FORMAT_4BIT_GRAY:
551 if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_ALPHA)
552 {
553 aux_stride = (aux_stride + 7) >> 3;
554 }
555 break;
556 }
557
558 /* Test size of compressed data to see if it is smaller. */
559 for (row = 0; row < height; row++)
560 {
561 status = _gx_image_reader_rle_one_row_encode(image_reader);
562
563 if (status != GX_SUCCESS)
564 {
565 return status;
566 }
567
568 image_reader -> gx_image_reader_getdata += image_reader -> gx_image_reader_input_stride;
569 image_reader -> gx_image_reader_getauxdata += aux_stride;
570 }
571
572 if (image_reader -> gx_image_reader_color_format == GX_COLOR_FORMAT_4BIT_GRAY)
573 {
574 if (!(image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_ALPHA) &&
575 image_reader -> gx_image_reader_putdata_mask == 0x0f)
576 {
577 image_reader -> gx_image_reader_putdata++;
578 }
579 }
580
581 (*data_size) = (UINT)image_reader -> gx_image_reader_putdata;
582 (*aux_size) = (UINT)image_reader -> gx_image_reader_putauxdata;
583
584 return status;
585 }
586
587 /**************************************************************************/
588 /* */
589 /* FUNCTION RELEASE */
590 /* */
591 /* _gx_image_reader_rle_encode PORTABLE C */
592 /* 6.1 */
593 /* AUTHOR */
594 /* */
595 /* Kenneth Maxwell, Microsoft Corporation */
596 /* */
597 /* DESCRIPTION */
598 /* */
599 /* This function converts a raw map into a compressed map. */
600 /* */
601 /* INPUT */
602 /* */
603 /* image_reader Image reader control block. */
604 /* outmap Encoded pixelmap. */
605 /* */
606 /* OUTPUT */
607 /* */
608 /* Completion status */
609 /* */
610 /* CALLS */
611 /* */
612 /* _gx_image_reader_rle_one_row_encode Process one row encoding */
613 /* */
614 /* CALLED BY */
615 /* */
616 /* _gx_image_reader_rle_colorspace_convert */
617 /* */
618 /* RELEASE HISTORY */
619 /* */
620 /* DATE NAME DESCRIPTION */
621 /* */
622 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
623 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
624 /* resulting in version 6.1 */
625 /* */
626 /**************************************************************************/
_gx_image_reader_rle_encode(GX_IMAGE_READER * image_reader,GX_PIXELMAP * outmap)627 UINT _gx_image_reader_rle_encode(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap)
628 {
629 UINT status = GX_SUCCESS;
630 GX_VALUE height;
631 GX_VALUE width;
632 INT row;
633 GX_VALUE aux_stride;
634
635 height = outmap -> gx_pixelmap_height;
636 width = outmap -> gx_pixelmap_width;
637 aux_stride = width;
638
639 /* If size testing is TRUE, process rle encode logic but not output compressed data.
640 If size testing is FALSE, process rle encode logic, and output compressed data. */
641 image_reader -> gx_image_reader_size_testing = GX_FALSE;
642
643 switch (image_reader -> gx_image_reader_color_format)
644 {
645 case GX_COLOR_FORMAT_4BIT_GRAY:
646 if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_ALPHA)
647 {
648 aux_stride = (GX_VALUE)((aux_stride + 7) >> 3);
649 }
650 break;
651 }
652
653 /* Process RLE encode. */
654 for (row = 0; row < height; row++)
655 {
656 /* Encode one row data. */
657 status = _gx_image_reader_rle_one_row_encode(image_reader);
658
659 if (status != GX_SUCCESS)
660 {
661 return status;
662 }
663
664 image_reader -> gx_image_reader_getdata += image_reader -> gx_image_reader_input_stride;
665 image_reader -> gx_image_reader_getauxdata += aux_stride;
666 }
667
668 return status;
669 }
670 #endif
671
672