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 
22 
23 /**************************************************************************/
24 /*                                                                        */
25 /*  COMPONENT DEFINITION                                   RELEASE        */
26 /*                                                                        */
27 /*    gx_image_reader.h                                   PORTABLE C      */
28 /*                                                           6.3.0        */
29 /*  AUTHOR                                                                */
30 /*                                                                        */
31 /*    Kenneth Maxwell, Microsoft Corporation                              */
32 /*                                                                        */
33 /*  DESCRIPTION                                                           */
34 /*                                                                        */
35 /*    This file defines the GUIX image reader management component,       */
36 /*    including all data types and external references.  It is assumed    */
37 /*    that gx_api.h and gx_port.h have already been included.             */
38 /*                                                                        */
39 /*  RELEASE HISTORY                                                       */
40 /*                                                                        */
41 /*    DATE              NAME                      DESCRIPTION             */
42 /*                                                                        */
43 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
44 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
45 /*                                            resulting in version 6.1    */
46 /*  06-02-2021     Ting Zhu                 Modified comment(s), and      */
47 /*                                            improved png decoding       */
48 /*                                            performance,                */
49 /*                                            resulting in version 6.1.7  */
50 /*  10-31-2022     Kenneth Maxwell          Modified comment(s),          */
51 /*                                            added definitions for fixed */
52 /*                                            size table dimensions,      */
53 /*                                            resulting in version 6.2.0  */
54 /*  10-31-2023     Ting Zhu                 Modified comment(s), added    */
55 /*                                            support for ARM Helium,     */
56 /*                                            added partial canvas buffer */
57 /*                                            support,                    */
58 /*                                            resulting in version 6.3.0  */
59 /*                                                                        */
60 /**************************************************************************/
61 #if defined(GX_SOFTWARE_DECODER_SUPPORT)
62 #ifndef GX_IMAGE_READER_H
63 #define GX_IMAGE_READER_H
64 
65 #if defined(GX_ENABLE_ARM_HELIUM)
66 #include <arm_mve.h>
67 #endif
68 
69 #define GX_IMAGE_FORMAT_1BPP                    0xf0
70 #define GX_IMAGE_FORMAT_2BPP                    0xf1
71 #define GX_IMAGE_FORMAT_4BPP                    0xf2
72 #define GX_IMAGE_FORMAT_8BPP                    0xf3
73 #define GX_IMAGE_FORMAT_16BPP_GRAY              0xf4 /* Internal format: 16bits for each gray value. */
74 #define GX_IMAGE_FORMAT_16BPP_GRAY_ALPHA        0xf5 /* Internal format: gray: alpha stream, 8 bits. */
75 #define GX_IMAGE_FORMAT_32BPP_GRAY_ALPHA        0xf6 /* Internal format: gray: alpha steam, 16bits. */
76 #define GX_IMAGE_FORMAT_24BPP                   0xf7 /* Internal format: r:g:b stream, 8bits for each channel. */
77 #define GX_IMAGE_FORMAT_32BPP                   0xf8 /* Internal format: r:g:b:a strem, 8bits for each channel. */
78 #define GX_IMAGE_FORMAT_48BPP                   0xf9 /* Internal format: r:g:b stream, 16bits for each channel. */
79 #define GX_IMAGE_FORMAT_64BPP                   0xfa /* Internal format: r:g:b:a stream, 16bits for each channel */
80 
81 #define GX_TRANSPARENT_COLOR                    0xff
82 
83 #define GX_PNG_CRC_TABLE_SIZE                   256
84 #define GX_PNG_HUFFMAN_LIT_TABLE_SIZE           286
85 #define GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE  288
86 #define GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE 32
87 #define GX_PNG_HUFFMAN_DIST_TABLE_SIZE          30
88 #define GX_PNG_PALETTE_TABLE_SIZE               256
89 #define GX_PNG_SCRATCH_BUFFER_SIZE              (GX_PNG_CRC_TABLE_SIZE +                   \
90                                                  GX_PNG_HUFFMAN_LIT_TABLE_SIZE +           \
91                                                  GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE +  \
92                                                  GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE + \
93                                                  GX_PNG_PALETTE_TABLE_SIZE)
94 #define JPG_MAX_COMPONENTS                      3
95 #define HUFF_TABLE_DIMENSION                    2
96 #define JPG_QUANT_TABLE_DIMENSION               4
97 
98 /* Control block used internally for jpeg reader.  */
99 typedef struct GX_HUFFCODE_INFO_STRUCT
100 {
101     USHORT   start;
102     USHORT   end;
103     USHORT   index;
104     GX_UBYTE bits;
105 } GX_HUFFCODE_INFO;
106 
107 typedef struct GX_JPEG_INFO_STRUCT
108 {
109     USHORT           gx_jpeg_width;
110     USHORT           gx_jpeg_height;
111     INT              gx_jpeg_num_of_components;
112     GX_UBYTE         gx_jpeg_sample_factor[JPG_MAX_COMPONENTS];
113     GX_UBYTE         gx_jpeg_component_id[JPG_MAX_COMPONENTS];
114     GX_UBYTE         gx_jpeg_qantization_table_index[JPG_MAX_COMPONENTS];
115     GX_UBYTE         gx_jpeg_dc_table_index[JPG_MAX_COMPONENTS];
116     GX_UBYTE         gx_jpeg_ac_table_index[JPG_MAX_COMPONENTS];
117     INT              gx_jpeg_quantization_table[JPG_QUANT_TABLE_DIMENSION][64];
118     GX_UBYTE        *gx_jpeg_huffman_table[HUFF_TABLE_DIMENSION][HUFF_TABLE_DIMENSION];
119     GX_HUFFCODE_INFO gx_jpeg_huffman_code_info[HUFF_TABLE_DIMENSION][HUFF_TABLE_DIMENSION][16];
120     INT              gx_jpeg_restart_interval;
121     GX_BYTE          gx_jpeg_Y_block[256];
122     GX_BYTE          gx_jpeg_Cr_block[64];
123     GX_BYTE          gx_jpeg_Cb_block[64];
124     INT              gx_jpeg_pre_dc[JPG_MAX_COMPONENTS];
125     INT              gx_jpeg_vecter[64];
126     GX_UBYTE        *gx_jpeg_data;
127     INT              gx_jpeg_data_size;
128     INT              gx_jpeg_data_index;
129     UINT             gx_jpeg_bit_buffer;
130     UINT             gx_jpeg_bit_count;
131 #if defined(GX_ENABLE_ARM_HELIUM)
132     VOID             (*gx_jpeg_pixel_write_helium)(struct GX_JPEG_INFO_STRUCT *jpeg_info, uint8x16_t vred, uint8x16_t vgreen, uint8x16_t vblue, INT size);
133 #else
134     VOID             (*gx_jpeg_pixel_write)(struct GX_JPEG_INFO_STRUCT *jpeg_info, GX_UBYTE red, GX_UBYTE green, GX_UBYTE blue);
135 #endif
136     GX_UBYTE        *gx_jpeg_output_buffer;
137 #if defined(GX_ENABLE_CANVAS_PARTIAL_FRAME_BUFFER)
138     GX_VALUE         gx_jpeg_output_buffer_offset_x;
139     GX_VALUE         gx_jpeg_output_buffer_offset_y;
140 #endif
141     USHORT           gx_jpeg_output_width;
142     USHORT           gx_jpeg_output_height;
143     INT              gx_jpeg_output_stride;
144     GX_RECTANGLE     gx_jpeg_output_clip;
145     INT              gx_jpeg_output_xpos;
146     INT              gx_jpeg_output_ypos;
147     GX_UBYTE         gx_jpeg_output_bpp;
148     GX_UBYTE         gx_jpeg_output_color_format;
149     USHORT           gx_jpeg_output_rotation_angle;
150     GX_UBYTE        *gx_jpeg_putdata;
151 } GX_JPEG_INFO;
152 
153 /* control block used internally for png reader */
154 typedef struct GX_PNG_STRUCT
155 {
156     GX_UBYTE *gx_png_data;
157     INT       gx_png_data_size;
158     INT       gx_png_data_index;
159     GX_UBYTE *gx_png_decoded_data;
160     INT       gx_png_decoded_data_len;
161     INT       gx_png_width;
162     INT       gx_png_height;
163     GX_UBYTE  gx_png_bit_depth;
164     INT       gx_png_color_type;
165     GX_UBYTE  gx_png_bpp; /* bits per pixel */
166     INT       gx_png_compression_method;
167     INT       gx_png_filter_method;
168     INT       gx_png_interlace_method;
169     UINT     *gx_png_crc_table;   /* 256 */
170     INT       gx_png_gamma;
171     INT       gx_png_huffman_clen_table[20];
172     INT       gx_png_huffman_clen_bits_count[17];
173     INT      *gx_png_huffman_lit_table;    /* 286 */
174     INT      *gx_png_huffman_lit_code_len; /* 286 */
175     INT       gx_png_huffman_lit_bits_count[17];
176     INT       gx_png_huffman_dist_table[GX_PNG_HUFFMAN_DIST_TABLE_SIZE];
177     INT      *gx_png_huffman_dist_code_len; /* 32 */
178     INT       gx_png_huffman_dist_bits_count[17];
179     GX_COLOR *gx_png_palette_table;         /* 256 */
180     INT       gx_png_palette_table_size;
181     GX_COLOR *gx_png_trans;
182     INT       gx_png_trans_num;
183     INT       gx_png_trunk_end_index;
184     UINT      gx_png_trunk_crc;
185 } GX_PNG;
186 
187 /* Define API functions for image reader.  */
188 UINT _gx_image_reader_start(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap);
189 UINT _gx_image_reader_colorspace_convert(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap);
190 
191 UINT _gx_image_reader_create(GX_IMAGE_READER *image_reader,
192                              GX_CONST GX_UBYTE *read_data,
193                              INT read_data_size,
194                              GX_UBYTE color_format,
195                              GX_UBYTE mode);
196 
197 /* Define internal function prototypes.  */
198 UINT _gx_image_reader_png_decode(GX_CONST GX_UBYTE *read_data, ULONG read_data_size, GX_PIXELMAP *outmap);
199 UINT _gx_image_reader_jpeg_decode(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap);
200 UINT _gx_image_reader_jpeg_mcu_decode(GX_CONST GX_UBYTE *read_data, ULONG data_size,
201                                       GX_DRAW_CONTEXT *context, INT xpos, INT ypos);
202 
203 UINT _gx_image_reader_pixel_read_callback_set(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap);
204 UINT _gx_image_reader_pixel_write_callback_set(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap);
205 UINT _gx_image_reader_image_decode(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap);
206 UINT _gx_image_reader_palette_set(GX_IMAGE_READER *image_reader, GX_COLOR *pal, UINT palsize);
207 UINT _gx_image_reader_nearest_palette_color_get(GX_IMAGE_READER *image_reader, GX_PIXEL *want_color, INT *index);
208 VOID _gx_image_reader_rgb2gray(GX_PIXEL *pixel, GX_UBYTE *gray);
209 UINT _gx_image_reader_rle_encode(GX_IMAGE_READER *image_reader, GX_PIXELMAP *pRLEmap);
210 UINT _gx_image_reader_rle_encode_size_get(GX_IMAGE_READER *image_reader, UINT *data_size, UINT *aux_size);
211 VOID _gx_image_reader_rgb2gray(GX_PIXEL *pixel, GX_UBYTE *gray);
212 
213 /* Define error checking shells for API services.  These are only referenced by the
214    application.  */
215 
216 UINT _gxe_image_reader_create(GX_IMAGE_READER *image_reader,
217                               GX_CONST GX_UBYTE  *read_data,
218                               INT read_data_size,
219                               GX_UBYTE color_format,
220                               GX_UBYTE mode);
221 
222 UINT _gxe_image_reader_palette_set(GX_IMAGE_READER *image_reader, GX_COLOR *pal, UINT palsize);
223 UINT _gxe_image_reader_start(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap);
224 
225 
226 #define GX_JPEG_DECODE_YCBCR2RGB(red, green, blue, y, cb, cr)                                                \
227     red = y + cr + (cr >> 2) + (cr >> 3) + 128;                                                              \
228     green = y - ((cb >> 2) + (cb >> 4) + (cb >> 5)) - ((cr >> 1) + (cr >> 3) + (cr >> 4) + (cr >> 5)) + 128; \
229     blue = y + cb + (cb >> 1) + (cb >> 2) + (cb >> 6) + 128;
230 
231 #if defined(GX_ENABLE_ARM_HELIUM)
232 
233 /* This offset table contains four offset vectors that used to gather load 16 cb/cr values to a 8x16 vector.
234    The table index represents the subsampling factor in horizontal. */
235 static uint8x16_t _gx_jpeg_cbcr_offset_table[7] = {
236     {0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}, /* h = 1 */
237     {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}, /* h = 2 */
238     {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7}, /* h = 2 */
239     {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3}, /* h = 4 */
240     {0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4}, /* h = 4 */
241     {0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4}, /* h = 4 */
242     {0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4}, /* h = 4 */
243 };
244 
245 static uint8x16_t _gx_jpeg_cbcr_offset_rotated_table_cw[3] = {
246     {0, 8, 16, 24, 32, 40, 48, 56,  0,  0,  0,  0,  0,  0,  0,  0}, /* cw, v = 1 */
247     {0, 0,  8,  8, 16, 16, 24, 24, 32, 32, 40, 40, 48, 48, 56, 56}, /* cw, v = 2 */
248     {0, 8,  8, 16, 16, 24, 24, 32, 32, 40, 40, 48, 48, 56, 56, 56} /* cw, v = 2 */
249 };
250 
251 static uint8x16_t _gx_jpeg_cbcr_offset_rotated_table_ccw[2] = {
252     {56, 48, 40, 32, 24, 16,  8,  0,  0,  0,  0,  0, 0, 0, 0, 0}, /* ccw, v = 1 */
253     {56, 56, 48, 48, 40, 40, 32, 32, 24, 24, 16, 16, 8, 8, 0, 0}, /* ccw, v = 2 */
254 };
255 
256 static uint8x16_t _gx_jpeg_y_offset_rotated_table_cw[3] = {
257     {0,  8, 16, 24,  32,  40,  48,  56,  64,  72,  80,  88,  96, 104, 112, 120}, /* cw, h = 1, v = 1 */
258     {0, 16, 32, 48,  64,  80,  96, 112, 128, 144, 160, 176, 192, 208, 224, 240}, /* cw, h = 2, v = 1 or v = 2 */
259     {0, 32, 64, 96, 128, 160, 192, 224, 224, 224, 224, 224, 224, 224, 224, 224} /* cw, h = 4, v = 1 */
260 };
261 
262 static uint8x16_t _gx_jpeg_y_offset_rotated_table_ccw[4] = {
263     {56,   48,  40,  32,  24,  16,   8,   0,   0,   0,   0,   0,   0,   0,   0, 0}, /* ccw, h = 1, v = 1 */
264     {112,  96,  80,  64,  48,  32,  16,   0,   0,   0,   0,   0,   0,   0,   0, 0}, /* ccw, h = 2, v = 1 */
265     {240, 224, 208, 192, 176, 160, 144, 128, 112,  96,  80,  64,  48,  32,  16, 0}, /* ccw, h = 2, v = 2 */
266     {224, 192, 160, 128,  96,  64,  32,   0,   0,   0,   0,   0,   0,   0,   0, 0} /* ccw, h = 4, v = 1 */
267 };
268 
269 
270 #define GX_JPEG_DECODE_YCBCR2RGB_HELIUM(vred, vgreen, vblue, y, cb, cr) \
271     {                                                                   \
272         int8x16_t vt;                                                   \
273         vred = (uint8x16_t)vqaddq_s8(y, cr);                            \
274         vt = vshrq_n_s8(cr, 2);                                         \
275         vred = (uint8x16_t)vqaddq_s8((int8x16_t)vred, vt);              \
276         vt = vshrq_n_s8(cr, 3);                                         \
277         vred = (uint8x16_t)vqaddq_s8((int8x16_t)vred, vt);              \
278         vred = vaddq_n_u8(vred, 128);                                   \
279                                                                         \
280         vt = vshrq_n_s8(cb, 2);                                         \
281         vgreen = (uint8x16_t)vshrq_n_s8(cb, 4);                         \
282         vgreen = (uint8x16_t)vqaddq_s8((int8x16_t)vgreen, vt);          \
283         vt = vshrq_n_s8(cb, 5);                                         \
284         vgreen = (uint8x16_t)vqaddq_s8((int8x16_t)vgreen, vt);          \
285         vt = vshrq_n_s8(cr, 1);                                         \
286         vgreen = (uint8x16_t)vqaddq_s8((int8x16_t)vgreen, vt);          \
287         vt = vshrq_n_s8(cr, 3);                                         \
288         vgreen = (uint8x16_t)vqaddq_s8((int8x16_t)vgreen, vt);          \
289         vt = vshrq_n_s8(cr, 4);                                         \
290         vgreen = (uint8x16_t)vqaddq_s8((int8x16_t)vgreen, vt);          \
291         vt = vshrq_n_s8(cr, 5);                                         \
292         vgreen = (uint8x16_t)vqaddq_s8((int8x16_t)vgreen, vt);          \
293         vgreen = (uint8x16_t)vqsubq_s8(y, (int8x16_t)vgreen);           \
294         vgreen = vaddq_n_u8(vgreen, 128);                               \
295                                                                         \
296         vblue = (uint8x16_t)vqaddq_s8(y, cb);                           \
297         vt = vshrq_n_s8(cb, 1);                                         \
298         vblue = (uint8x16_t)vqaddq_s8((int8x16_t)vblue, vt);            \
299         vt = vshrq_n_s8(cb, 2);                                         \
300         vblue = (uint8x16_t)vqaddq_s8((int8x16_t)vblue, vt);            \
301         vt = vshrq_n_s8(cb, 6);                                         \
302         vblue = (uint8x16_t)vqaddq_s8((int8x16_t)vblue, vt);            \
303         vblue = vaddq_n_u8(vblue, 128);                                 \
304     }
305 
306 
307 #endif /* GX_ENABLE_ARM_HELIUM */
308 
309 #endif /* GX_IMAGE_READER_H */
310 
311 #endif /* GX_SOFTWARE_DECODER_SUPPORT */
312 
313