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