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