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 Management (Utility) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23 /* Include necessary system files. */
24
25 #include "gx_api.h"
26 #include "gx_context.h"
27 #include "gx_system.h"
28 #include "gx_utility.h"
29 #include "gx_image_reader.h"
30
31 #if defined(GX_SOFTWARE_DECODER_SUPPORT)
32
33 #define GX_SATURATE_TO_UBYTE(result, i) \
34 { \
35 if ((i) < 0) \
36 { \
37 (result) = 0; \
38 } \
39 else if ((i) > 255) \
40 { \
41 (result) = 255; \
42 } \
43 else \
44 { \
45 (result) = (GX_UBYTE)(i); \
46 } \
47 }
48
49 #define GX_SATURATE_TO_BYTE(result, i) \
50 { \
51 if ((i) < -128) \
52 { \
53 (result) = -128; \
54 } \
55 else if ((i) > 127) \
56 { \
57 (result) = 127; \
58 } \
59 else \
60 { \
61 (result) = (GX_BYTE)(i); \
62 } \
63 }
64
65 #define GX_JPEG_BITS_GET(jpeg_info, num_of_bits) \
66 while (jpeg_info -> gx_jpeg_bit_count <= num_of_bits) \
67 { \
68 if ((jpeg_info -> gx_jpeg_data_index < jpeg_info -> gx_jpeg_data_size) && (jpeg_info -> gx_jpeg_bit_count <= 24)) \
69 { \
70 jpeg_info -> gx_jpeg_bit_buffer |= ((UINT)(jpeg_info -> gx_jpeg_data[jpeg_info -> gx_jpeg_data_index]) << (UINT)(24 - jpeg_info -> gx_jpeg_bit_count)); \
71 \
72 /* 2 byte 'FF00' sequence should be considered as just a byte 0xFF. */ \
73 if ((jpeg_info -> gx_jpeg_data[jpeg_info -> gx_jpeg_data_index] == 0xff) && \
74 (jpeg_info -> gx_jpeg_data_index + 1 < jpeg_info -> gx_jpeg_data_size) && \
75 (jpeg_info -> gx_jpeg_data[jpeg_info -> gx_jpeg_data_index + 1] == 0x00)) \
76 { \
77 jpeg_info -> gx_jpeg_data_index += 2; \
78 } \
79 else \
80 { \
81 jpeg_info -> gx_jpeg_data_index += 1; \
82 } \
83 } \
84 \
85 jpeg_info -> gx_jpeg_bit_count += 8; \
86 }
87
88 #define GX_JPEG_BITS_SKIP(jpeg_info, skip_bits) \
89 (jpeg_info) -> gx_jpeg_bit_buffer <<= (skip_bits); \
90 (jpeg_info) -> gx_jpeg_bit_count -= (skip_bits);
91
92 /**************************************************************************/
93 /* */
94 /* FUNCTION RELEASE */
95 /* */
96 /* _gx_dislay_driver_jpeg_quantization_table_set PORTABLE C */
97 /* 6.2.0 */
98 /* AUTHOR */
99 /* */
100 /* Kenneth Maxwell, Microsoft Corporation */
101 /* */
102 /* DESCRIPTION */
103 /* */
104 /* Sets the JPEG quantization table. */
105 /* */
106 /* INPUT */
107 /* */
108 /* jpeg_info JPEG data control block */
109 /* segment_len Initial length of the segment */
110 /* */
111 /* OUTPUT */
112 /* */
113 /* None */
114 /* */
115 /* CALLS */
116 /* */
117 /* None */
118 /* */
119 /* CALLED BY */
120 /* */
121 /* _gx_image_reader_jpeg_decode */
122 /* */
123 /* RELEASE HISTORY */
124 /* */
125 /* DATE NAME DESCRIPTION */
126 /* */
127 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
128 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
129 /* resulting in version 6.1 */
130 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
131 /* prevented underflow from */
132 /* bad input data, */
133 /* resulting in version 6.2.0 */
134 /* */
135 /**************************************************************************/
_gx_image_reader_jpeg_quantization_table_set(GX_JPEG_INFO * jpeg_info,UINT segment_len)136 static UINT _gx_image_reader_jpeg_quantization_table_set(GX_JPEG_INFO *jpeg_info, UINT segment_len)
137 {
138 GX_UBYTE table_index;
139 GX_UBYTE *jpeg_data = jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index;
140 INT index;
141
142 /* Minus two-byte length. */
143 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
144 segment_len -= 2;
145 jpeg_data += 2;
146
147 while (segment_len)
148 {
149 /* The upper 4 bits specify the element precision: 0 indicates 8-bit, 1 indecates 16-bit. */
150 if ((*jpeg_data) & 0xf0)
151 {
152 /* Baseline DCT-based jpeg only support 8-bit precision. */
153 return GX_NOT_SUPPORTED;
154 }
155
156 /* The lower 4 bits specify the table destination identifier, specify one of four possible destinations. */
157 table_index = (*jpeg_data++) & 0x03;
158
159 /* Read quantization table element. */
160 for (index = 0; index < 64; index++)
161 {
162 jpeg_info -> gx_jpeg_quantization_table[table_index][index] = *jpeg_data++;
163 }
164
165 if (segment_len < 65)
166 {
167 return GX_INVALID_FORMAT;
168 }
169 segment_len -= 65;
170 }
171
172 return GX_SUCCESS;
173 }
174
175 /**************************************************************************/
176 /* */
177 /* FUNCTION RELEASE */
178 /* */
179 /* _gx_image_reader_jpeg_huffcode_find PORTABLE C */
180 /* 6.3.0 */
181 /* AUTHOR */
182 /* */
183 /* Kenneth Maxwell, Microsoft Corporation */
184 /* */
185 /* DESCRIPTION */
186 /* */
187 /* Lookup the huffman code. */
188 /* */
189 /* INPUT */
190 /* */
191 /* jpeg_info JPEG data control block */
192 /* table_class Table class, 0 = DC table, */
193 /* 1 = AC table */
194 /* table_id Table index */
195 /* scan_buffer Buffer to search from */
196 /* bit_len Retrieved Huffman Code Length */
197 /* code_value Retrieved Huffman Code */
198 /* */
199 /* OUTPUT */
200 /* */
201 /* Status Code */
202 /* */
203 /* CALLS */
204 /* */
205 /* None */
206 /* */
207 /* CALLED BY */
208 /* */
209 /* _gx_image_reader_jpeg_dc_decode */
210 /* _gx_image_reader_jpeg_ac_decode */
211 /* */
212 /* RELEASE HISTORY */
213 /* */
214 /* DATE NAME DESCRIPTION */
215 /* */
216 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
217 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
218 /* resulting in version 6.1 */
219 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
220 /* changed bit_count to */
221 /* GX_VALUE data type, */
222 /* resulting in version 6.2.0 */
223 /* 10-31-2023 Ting Zhu Modified comment(s), */
224 /* improved logic, */
225 /* resulting in version 6.3.0 */
226 /* */
227 /**************************************************************************/
_gx_image_reader_jpeg_huffcode_find(GX_JPEG_INFO * jpeg_info,UINT table_class,UINT table_id,UINT * bit_len,GX_UBYTE * code_value)228 static UINT _gx_image_reader_jpeg_huffcode_find(GX_JPEG_INFO *jpeg_info,
229 UINT table_class,
230 UINT table_id,
231 UINT *bit_len,
232 GX_UBYTE *code_value)
233 {
234 GX_UBYTE index;
235 USHORT code;
236 USHORT code_index;
237 GX_HUFFCODE_INFO *code_info;
238
239 for (index = 0; index < 16; index++)
240 {
241 code_info = &jpeg_info -> gx_jpeg_huffman_code_info[table_class][table_id][index];
242 if (code_info -> bits)
243 {
244 code = (USHORT)((jpeg_info -> gx_jpeg_bit_buffer) >> (32 - code_info -> bits));
245
246 if (code <= code_info -> end)
247 {
248 code_index = (USHORT)(code_info -> index + code - code_info -> start);
249 *bit_len = code_info -> bits;
250 *code_value = jpeg_info -> gx_jpeg_huffman_table[table_class][table_id][code_index];
251 return GX_SUCCESS;
252 }
253 }
254 else
255 {
256 break;
257 }
258 }
259
260 return GX_FAILURE;
261 }
262
263 /**************************************************************************/
264 /* */
265 /* FUNCTION RELEASE */
266 /* */
267 /* _gx_image_reader_huffman_table_set PORTABLE C */
268 /* 6.3.0 */
269 /* AUTHOR */
270 /* */
271 /* Kenneth Maxwell, Microsoft Corporation */
272 /* */
273 /* DESCRIPTION */
274 /* */
275 /* Sets up the huffman table. */
276 /* */
277 /* INPUT */
278 /* */
279 /* jpeg_info JPEG data control block */
280 /* segment_len Initial length of the segment */
281 /* */
282 /* OUTPUT */
283 /* */
284 /* None */
285 /* */
286 /* CALLS */
287 /* */
288 /* None */
289 /* */
290 /* CALLED BY */
291 /* */
292 /* _gx_image_reader_jpeg_decode_blocks */
293 /* */
294 /* RELEASE HISTORY */
295 /* */
296 /* DATE NAME DESCRIPTION */
297 /* */
298 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
299 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
300 /* resulting in version 6.1 */
301 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
302 /* added range test to prevent */
303 /* underflow, */
304 /* resulting in version 6.2.0 */
305 /* 10-31-2023 Ting Zhu Modified comment(s), */
306 /* improved logic, */
307 /* resulting in version 6.3.0 */
308 /* */
309 /**************************************************************************/
_gx_image_reader_huffman_table_set(GX_JPEG_INFO * jpeg_info,UINT segment_len)310 static UINT _gx_image_reader_huffman_table_set(GX_JPEG_INFO *jpeg_info, UINT segment_len)
311 {
312 GX_UBYTE *jpeg_data = jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index;
313 GX_UBYTE table_class;
314 GX_UBYTE table_id;
315 GX_UBYTE bit_count;
316 UINT i_bits;
317 USHORT i_table_size;
318 GX_HUFFCODE_INFO *code_info;
319 INT index = 0;
320 USHORT code = 0;
321
322 /* must have at least one code for each of 16 huffman bit lengths */
323 if (segment_len < 19)
324 {
325 return GX_INVALID_FORMAT;
326 }
327
328 /* Minus two-byte length. */
329 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
330 segment_len -= 2;
331 jpeg_data += 2;
332
333 while (segment_len)
334 {
335 /* table_calss: 0 DC 1 AC */
336 table_class = ((*jpeg_data) >> 4) & 1;
337 table_id = (*jpeg_data++) & 0x01;
338
339 if (segment_len < 17)
340 {
341 return GX_INVALID_FORMAT;
342 }
343 segment_len -= 17;
344
345 i_table_size = 0;
346
347 index = 0;
348 code = 0;
349
350 /* Read the number of Huffman codes for each bit length, from 1 to 16. */
351 for (i_bits = 0; i_bits < 16; i_bits++)
352 {
353 bit_count = *jpeg_data++;
354
355 if (bit_count)
356 {
357 code_info = &jpeg_info -> gx_jpeg_huffman_code_info[table_class][table_id][index++];
358 code_info -> index = i_table_size;
359 code_info -> start = code;
360 code_info -> end = (USHORT)(code + bit_count - 1);
361 code_info -> bits = (GX_UBYTE)(i_bits + 1);
362 }
363 code = (USHORT)((code + bit_count) << 1);
364
365 i_table_size = (USHORT)(i_table_size + bit_count);
366 }
367
368 if (segment_len < i_table_size)
369 {
370 return GX_INVALID_FORMAT;
371 }
372
373 segment_len -= i_table_size;
374
375 /* Load the start address of the specified huffman table. */
376 jpeg_info -> gx_jpeg_huffman_table[table_class][table_id] = jpeg_data;
377 jpeg_data += i_table_size;
378 }
379
380 return GX_SUCCESS;
381 }
382
383 /**************************************************************************/
384 /* */
385 /* FUNCTION RELEASE */
386 /* */
387 /* _gx_display_driver_jpeg_frame_header_read PORTABLE C */
388 /* 6.1 */
389 /* AUTHOR */
390 /* */
391 /* Kenneth Maxwell, Microsoft Corporation */
392 /* */
393 /* DESCRIPTION */
394 /* */
395 /* Reads in the frame header infomration. */
396 /* */
397 /* INPUT */
398 /* */
399 /* jpeg_info JPEG data control block */
400 /* segment_len Initial length of the segment */
401 /* */
402 /* OUTPUT */
403 /* */
404 /* None */
405 /* */
406 /* CALLS */
407 /* */
408 /* None */
409 /* */
410 /* CALLED BY */
411 /* */
412 /* _gx_image_reader_jpeg_decode_blocks */
413 /* */
414 /* RELEASE HISTORY */
415 /* */
416 /* DATE NAME DESCRIPTION */
417 /* */
418 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
419 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
420 /* resulting in version 6.1 */
421 /* */
422 /**************************************************************************/
_gx_image_reader_jpeg_frame_header_read(GX_JPEG_INFO * jpeg_info,UINT segment_len)423 static UINT _gx_image_reader_jpeg_frame_header_read(GX_JPEG_INFO *jpeg_info, UINT segment_len)
424 {
425 GX_UBYTE *jpeg_data = jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index;
426 INT i_component;
427
428 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
429 jpeg_data += 2;
430
431 /* Skip precision field. */
432 jpeg_data++;
433
434 /* Read image width, WORD */
435 jpeg_info -> gx_jpeg_height = *jpeg_data++;
436 jpeg_info -> gx_jpeg_height = (USHORT)(jpeg_info -> gx_jpeg_height << 8);
437 jpeg_info -> gx_jpeg_height = (USHORT)(jpeg_info -> gx_jpeg_height | (*jpeg_data++));
438
439 /* Limit max jpeg height to 14 bits. */
440 if (jpeg_info -> gx_jpeg_height > GX_MAX_PIXELMAP_RESOLUTION)
441 {
442 return GX_INVALID_HEIGHT;
443 }
444
445 /* Read image height, WORD */
446 jpeg_info -> gx_jpeg_width = *jpeg_data++;
447 jpeg_info -> gx_jpeg_width = (USHORT)(jpeg_info -> gx_jpeg_width << 8);
448 jpeg_info -> gx_jpeg_width = (USHORT)(jpeg_info -> gx_jpeg_width | (*jpeg_data++));
449
450 /* Limit max jpeg width to 14 bits. */
451 if (jpeg_info -> gx_jpeg_width > GX_MAX_PIXELMAP_RESOLUTION)
452 {
453 return GX_INVALID_WIDTH;
454 }
455
456 /* Read image components. */
457 jpeg_info -> gx_jpeg_num_of_components = *jpeg_data++;
458
459 if (jpeg_info -> gx_jpeg_num_of_components > JPG_MAX_COMPONENTS)
460 {
461 return GX_FAILURE;
462 }
463
464 for (i_component = 0; i_component < jpeg_info -> gx_jpeg_num_of_components; i_component++)
465 {
466 /* Read component id */
467 jpeg_info -> gx_jpeg_component_id[i_component] = *jpeg_data++;
468
469 /* Read sample factor */
470 jpeg_info -> gx_jpeg_sample_factor[i_component] = *jpeg_data++;
471
472 /* Read quantization table index */
473 jpeg_info -> gx_jpeg_qantization_table_index[i_component] = *jpeg_data++;
474 }
475
476 return GX_SUCCESS;
477 }
478
479 /**************************************************************************/
480 /* */
481 /* FUNCTION RELEASE */
482 /* */
483 /* _gx_image_reader_jpeg_scan_header_read PORTABLE C */
484 /* 6.1 */
485 /* AUTHOR */
486 /* */
487 /* Kenneth Maxwell, Microsoft Corporation */
488 /* */
489 /* DESCRIPTION */
490 /* */
491 /* Reads in the scan header information. */
492 /* */
493 /* INPUT */
494 /* */
495 /* jpeg_info JPEG data control block */
496 /* segment_len Initial length of the segment */
497 /* */
498 /* OUTPUT */
499 /* */
500 /* None */
501 /* */
502 /* CALLS */
503 /* */
504 /* None */
505 /* */
506 /* CALLED BY */
507 /* */
508 /* _gx_image_reader_jpeg_decode_blocks */
509 /* */
510 /* RELEASE HISTORY */
511 /* */
512 /* DATE NAME DESCRIPTION */
513 /* */
514 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
515 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
516 /* resulting in version 6.1 */
517 /* */
518 /**************************************************************************/
_gx_image_reader_jpeg_scan_header_read(GX_JPEG_INFO * jpeg_info,UINT segment_len)519 static UINT _gx_image_reader_jpeg_scan_header_read(GX_JPEG_INFO *jpeg_info, UINT segment_len)
520 {
521 GX_UBYTE *jpeg_data = jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index;
522 INT index;
523
524 jpeg_data += 2;
525 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
526
527 /* Read the number of image components. */
528 jpeg_info -> gx_jpeg_num_of_components = *jpeg_data++;
529
530 if (jpeg_info -> gx_jpeg_num_of_components > JPG_MAX_COMPONENTS)
531 {
532 return GX_FAILURE;
533 }
534
535 for (index = 0; index < jpeg_info -> gx_jpeg_num_of_components; index++)
536 {
537 /* skip image component */
538 jpeg_data++;
539
540 /* high bits correspond to DC table index.
541 low bits correspond to AC table index
542 0: Y Huffman table
543 1: Chrominance Huffman table. */
544 jpeg_info -> gx_jpeg_dc_table_index[index] = ((*jpeg_data) & 0xf0) >> 4;
545 jpeg_info -> gx_jpeg_ac_table_index[index] = (*jpeg_data++) & 0x0f;
546 }
547
548 return GX_SUCCESS;
549 }
550
551 /**************************************************************************/
552 /* */
553 /* FUNCTION RELEASE */
554 /* */
555 /* _gx_image_reader_jpeg_dc_decode PORTABLE C */
556 /* 6.3.0 */
557 /* AUTHOR */
558 /* */
559 /* Kenneth Maxwell, Microsoft Corporation */
560 /* */
561 /* DESCRIPTION */
562 /* */
563 /* Decode the DC component. */
564 /* */
565 /* INPUT */
566 /* */
567 /* jpeg_info JPEG data control block */
568 /* i_component Component index */
569 /* */
570 /* OUTPUT */
571 /* */
572 /* Status */
573 /* */
574 /* CALLS */
575 /* */
576 /* GX_JPEG_BITS_GET Extract a specified number of*/
577 /* bits from JPEG data stream */
578 /* GX_JPEG_BITS_SKIP Skips bits from tempory JPEG */
579 /* data stream */
580 /* _gx_image_reader_jpeg_huffman_code_find */
581 /* Lookup the huffman code */
582 /* */
583 /* CALLED BY */
584 /* */
585 /* _gx_image_reader_jpeg_one_block_decode */
586 /* */
587 /* RELEASE HISTORY */
588 /* */
589 /* DATE NAME DESCRIPTION */
590 /* */
591 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
592 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
593 /* resulting in version 6.1 */
594 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
595 /* added range test, */
596 /* resulting in version 6.2.0 */
597 /* 10-31-2023 Ting Zhu Modified comment(s), */
598 /* improved logic, */
599 /* resulting in version 6.3.0 */
600 /* */
601 /**************************************************************************/
_gx_image_reader_jpeg_dc_decode(GX_JPEG_INFO * jpeg_info,UINT i_component)602 static UINT _gx_image_reader_jpeg_dc_decode(GX_JPEG_INFO *jpeg_info, UINT i_component)
603 {
604 UINT i_bits = 0;
605 GX_UBYTE code_value;
606 INT diff;
607 UINT table_index = jpeg_info -> gx_jpeg_dc_table_index[i_component];
608 GX_BOOL negative;
609
610 if (table_index >= HUFF_TABLE_DIMENSION)
611 {
612 return GX_FAILURE;
613 }
614
615 GX_JPEG_BITS_GET(jpeg_info, 16);
616
617 if (_gx_image_reader_jpeg_huffcode_find(jpeg_info, 0, table_index, &i_bits, &code_value) == 0)
618 {
619 GX_JPEG_BITS_SKIP(jpeg_info, i_bits);
620
621 if (code_value == 0)
622 {
623 jpeg_info -> gx_jpeg_vecter[0] = jpeg_info -> gx_jpeg_pre_dc[i_component];
624 }
625 else
626 {
627
628 GX_JPEG_BITS_GET(jpeg_info, code_value);
629 diff = (INT)(((UINT)jpeg_info -> gx_jpeg_bit_buffer) >> (32 - code_value));
630 GX_JPEG_BITS_SKIP(jpeg_info, code_value);
631
632 negative = !(diff >> (code_value - 1));
633
634 if (negative)
635 {
636 diff += 1 - (1 << code_value);
637 }
638
639 jpeg_info -> gx_jpeg_vecter[0] = diff + jpeg_info -> gx_jpeg_pre_dc[i_component];
640 jpeg_info -> gx_jpeg_pre_dc[i_component] = jpeg_info -> gx_jpeg_vecter[0];
641 }
642 }
643 else
644 {
645 return GX_FAILURE;
646 }
647
648 return GX_SUCCESS;
649 }
650
651 /**************************************************************************/
652 /* */
653 /* FUNCTION RELEASE */
654 /* */
655 /* _gx_image_reader_jpeg_ac_decode PORTABLE C */
656 /* 6.3.0 */
657 /* AUTHOR */
658 /* */
659 /* Kenneth Maxwell, Microsoft Corporation */
660 /* */
661 /* DESCRIPTION */
662 /* */
663 /* Decode the AC component. */
664 /* */
665 /* INPUT */
666 /* */
667 /* jpeg_info JPEG data control block */
668 /* i_component Component index */
669 /* */
670 /* OUTPUT */
671 /* */
672 /* Status Code */
673 /* */
674 /* CALLS */
675 /* */
676 /* GX_JPEG_BITS_GET Extract a specified number of*/
677 /* bits from JPEG data stream */
678 /* GX_JPEG_BITS_SKIP Skips bits from tempory JPEG */
679 /* data stream */
680 /* _gx_image_reader_jpeg_huffman_code_find */
681 /* Lookup the huffman code */
682 /* */
683 /* CALLED BY */
684 /* */
685 /* _gx_image_reader_jpeg_one_block_decode */
686 /* */
687 /* RELEASE HISTORY */
688 /* */
689 /* DATE NAME DESCRIPTION */
690 /* */
691 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
692 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
693 /* resulting in version 6.1 */
694 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
695 /* added range test, */
696 /* resulting in version 6.2.0 */
697 /* 10-31-2023 Ting Zhu Modified comment(s), */
698 /* improved logic, */
699 /* resulting in version 6.3.0 */
700 /* */
701 /**************************************************************************/
_gx_image_reader_jpeg_ac_decode(GX_JPEG_INFO * jpeg_info,UINT i_component)702 static UINT _gx_image_reader_jpeg_ac_decode(GX_JPEG_INFO *jpeg_info, UINT i_component)
703 {
704 UINT i_bits = 0;
705 GX_UBYTE code_value;
706 GX_UBYTE catogory;
707 GX_UBYTE runs_of_zero;
708 INT ac_coefficient;
709 UINT ac_counter = 1;
710 UINT table_index = jpeg_info -> gx_jpeg_ac_table_index[i_component];
711 INT negative;
712
713 if (table_index >= HUFF_TABLE_DIMENSION)
714 {
715 return GX_FAILURE;
716 }
717
718 while (ac_counter < 64)
719 {
720 i_bits = 0;
721 GX_JPEG_BITS_GET(jpeg_info, 16);
722
723 if (_gx_image_reader_jpeg_huffcode_find(jpeg_info, 1, table_index, &i_bits, &code_value) == 0)
724 {
725 GX_JPEG_BITS_SKIP(jpeg_info, i_bits);
726
727 runs_of_zero = (0xf0 & code_value) >> 4;
728 catogory = 0x0f & code_value;
729
730 if (catogory == 0)
731 {
732 /* EOB encountered. */
733 if (runs_of_zero == 0)
734 {
735 ac_counter = 64;
736 }
737 else if (runs_of_zero == 0x0f)
738 {
739 ac_counter += 16;
740 }
741 }
742 else
743 {
744 ac_counter += runs_of_zero;
745
746 GX_JPEG_BITS_GET(jpeg_info, catogory);
747 ac_coefficient = (INT)((jpeg_info -> gx_jpeg_bit_buffer) >> (32 - catogory));
748 GX_JPEG_BITS_SKIP(jpeg_info, catogory);
749
750 negative = !(ac_coefficient >> (catogory - 1));
751
752 if (negative)
753 {
754 ac_coefficient += 1 - (1 << catogory);
755 }
756
757 if (ac_counter < 64)
758 {
759 jpeg_info -> gx_jpeg_vecter[ac_counter++] = ac_coefficient;
760 }
761 }
762 }
763 else
764 {
765 return GX_FAILURE;
766 }
767 }
768
769 return GX_SUCCESS;
770 }
771
772 #if defined(GX_ENABLE_ARM_HELIUM)
773 /* Define the triple Bufferfly Addition operation */
774 #define VBUTTERFLY_ADDITION(a, b) \
775 vtemp = vaddq_s32(a, b); \
776 b = vsubq_s32(a, b); \
777 a = vtemp
778
779 /* Define the butterfly Multiplication */
780 #define VBUTTERFLY_MULTIPLICATION(a, b, cos, sin) \
781 vtempa = vmulq_n_s32(a, cos); \
782 vtempb = vmulq_n_s32(b, sin); \
783 vtemp = vaddq_s32(vtempa, vtempb); \
784 vtempa = vmulq_n_s32(a, sin); \
785 vtempb = vmulq_n_s32(b, cos); \
786 b = vsubq_s32(vtempb, vtempa); \
787 a = vtemp
788
789 #define VBUTTERFLY_MULTIPLICATION_SHR6(a, b, cos, sin) \
790 vtempa = vmulq_n_s32(a, cos); \
791 vtempb = vmulq_n_s32(b, sin); \
792 vtemp = vaddq_s32(vtempa, vtempb); \
793 vtempa = vmulq_n_s32(a, sin); \
794 vtempb = vmulq_n_s32(b, cos); \
795 b = vsubq_s32(vtempb, vtempa); \
796 b = vshrq_n_s32(b, 6); \
797 a = vshrq_n_s32(vtemp, 6)
798 #else
799
800 /* Define the triple Bufferfly Addition operation */
801 #define BUTTERFLY_ADDITION(a, b) \
802 t = a + b; \
803 b = a - b; \
804 a = t
805
806 /* Define the butterfly Multiplication */
807 #define BUTTERFLY_MULTIPLICATION(a, b, cos, sin) \
808 t = (a * cos + b * sin); \
809 b = (b * cos - a * sin); \
810 a = t
811
812 #define BUTTERFLY_MULTIPLICATION_SHR6(a, b, cos, sin) \
813 t = (a * cos + b * sin) >> 6; \
814 b = (b * cos - a * sin) >> 6; \
815 a = t
816
817 #endif
818
819 /* Define constants. */
820 #define R2_SHR7 181 /* = sqrt(2) << 7. */
821 #define C1_SHR8 251 /* = cos(pi/16) << 8. */
822 #define S1_SHR8 50 /* = sin(pi/16) << 8. */
823 #define C3_SHR8 213 /* = cos(3pi/16)*sqrt(2) << 8. */
824 #define S3_SHR8 142 /* = sin(3pi/16)*sqrt(2) << 8. */
825 #define C6R2_SHR9 277 /* = cos(pi/16)*sqrt(2) << 9. */
826 #define S6R2_SHR9 669 /* = sin(3pi/16)*sqrt(2) << 9. */
827 #define POSTSH1 9
828 #define POSTSH2 12
829
830 #if defined(GX_ENABLE_ARM_HELIUM)
831 /**************************************************************************/
832 /* */
833 /* FUNCTION RELEASE */
834 /* */
835 /* _gx_image_reader_jpeg_dequantize_idct PORTABLE C */
836 /* 6.3.0 */
837 /* AUTHOR */
838 /* */
839 /* Ting Zhu, Microsoft Corporation */
840 /* */
841 /* DESCRIPTION */
842 /* */
843 /* Dequatilizes decoded data and performs Inverse Discrete Consine */
844 /* Transformation using helium intrinsics. */
845 /* */
846 /* INPUT */
847 /* */
848 /* block Pointer to decoded data */
849 /* quant_table Pointer to quantization table */
850 /* out Buffer for output data */
851 /* stride Stride of output data */
852 /* */
853 /* OUTPUT */
854 /* */
855 /* None */
856 /* */
857 /* CALLS */
858 /* */
859 /* vldrwq_gather_shifted_offset_s32 Gather data from memory */
860 /* vmulq_s32 Multiply two vectors */
861 /* vmulq_n_s32 Multiply by scaler */
862 /* vqrshlq_n_s32 Shift each element of a */
863 /* vector register left by */
864 /* the immediate value */
865 /* vaddq_s32 Add two vectors */
866 /* vrshrq_n_s32 Shift each element of a */
867 /* vector register right by */
868 /* the immediate value */
869 /* vstrhq_scatter_offset_s32 Scatter store data to memory */
870 /* vldrhq_s32 Load vector register */
871 /* vqrshrnbq_n_s32 Shift right with saturation, */
872 /* and write the result to the */
873 /* bottom half of the result */
874 /* element */
875 /* vqmovntq_s16 Saturate to half width and */
876 /* write the result to the */
877 /* top of the result element */
878 /* vstrbq_scatter_offset_s8 Scatter store data to memory */
879 /* VBUTTERFLY_ADDITION Perform butterfly addition */
880 /* VBUTTERFLY_MULTIPLICATION Perform butterfly */
881 /* multiplication */
882 /* VBUTTERFLY_MULTIPLICATION_SHR6 Perform butterfly */
883 /* multiplication with shift */
884 /* */
885 /* CALLED BY */
886 /* */
887 /* _gx_image_reader_jpeg_one_block_decode */
888 /* */
889 /* RELEASE HISTORY */
890 /* */
891 /* DATE NAME DESCRIPTION */
892 /* */
893 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
894 /* */
895 /**************************************************************************/
_gx_image_reader_jpeg_dequantize_idct(INT * block,INT * quant_table,GX_BYTE * out,INT stride)896 static VOID _gx_image_reader_jpeg_dequantize_idct(INT *block, INT *quant_table, GX_BYTE *out, INT stride)
897 {
898 static uint32x4_t voffset[8][2] = {
899 {{0, 2, 3, 9}, {10, 20, 21, 35}},
900 {{1, 4, 8, 11}, {19, 22, 34, 36}},
901 {{5, 7, 12, 18}, {23, 33, 37, 48}},
902 {{6, 13, 17, 24}, {32, 38, 47, 49}},
903 {{14, 16, 25, 31}, {39, 46, 50, 57}},
904 {{15, 26, 30, 40}, {45, 51, 56, 58}},
905 {{27, 29, 41, 44}, {52, 55, 59, 62}},
906 {{28, 42, 43, 53}, {54, 60, 61, 63}}
907 };
908 static uint32x4_t vstroffset1= {0, 16, 32, 48};
909 INT index;
910 GX_VALUE temp_block[64];
911 GX_VALUE *output_data;
912 int32x4_t vrow0, vrow1, vrow2, vrow3, vrow4, vrow5, vrow6, vrow7, vtemp, vtempa, vtempb;
913 uint8x16_t vstroffset = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3};
914 int16x8_t vtemp16;
915 int8x16_t vtemp8;
916 int16_t const *base;
917
918 /* Perform 2-D DCT by applying first a 1-D DCT over the rows
919 followed by a 1-D DCT over the columns of the input-data matrix.*/
920 for (index = 0; index < 4; index++)
921 {
922 vstroffset[0 + index * 4] += (stride * 3);
923 vstroffset[1 + index * 4] += stride;
924 vstroffset[2 + index * 4] += (stride << 1);
925 }
926
927
928 for (index = 0; index < 2; index++)
929 {
930 output_data = temp_block + 32 * index;
931
932 /* Load data. */
933 vrow0 = vldrwq_gather_shifted_offset_s32(block, voffset[0][index]);
934 vtemp = vldrwq_gather_shifted_offset_s32(quant_table, voffset[0][index]);
935 vrow0 = vmulq_s32(vrow0, vtemp);
936
937 vrow1 = vldrwq_gather_shifted_offset_s32(block, voffset[1][index]);
938 vtemp = vldrwq_gather_shifted_offset_s32(quant_table, voffset[1][index]);
939 vrow1 = vmulq_s32(vrow1, vtemp);
940
941 vrow2 = vldrwq_gather_shifted_offset_s32(block, voffset[2][index]);
942 vtemp = vldrwq_gather_shifted_offset_s32(quant_table, voffset[2][index]);
943 vrow2 = vmulq_s32(vrow2, vtemp);
944
945 vrow3 = vldrwq_gather_shifted_offset_s32(block, voffset[3][index]);
946 vtemp = vldrwq_gather_shifted_offset_s32(quant_table, voffset[3][index]);
947 vrow3 = vmulq_s32(vrow3, vtemp);
948
949 vrow4 = vldrwq_gather_shifted_offset_s32(block, voffset[4][index]);
950 vtemp = vldrwq_gather_shifted_offset_s32(quant_table, voffset[4][index]);
951 vrow4 = vmulq_s32(vrow4, vtemp);
952
953 vrow5 = vldrwq_gather_shifted_offset_s32(block, voffset[5][index]);
954 vtemp = vldrwq_gather_shifted_offset_s32(quant_table, voffset[5][index]);
955 vrow5 = vmulq_s32(vrow5, vtemp);
956
957 vrow6 = vldrwq_gather_shifted_offset_s32(block, voffset[6][index]);
958 vtemp = vldrwq_gather_shifted_offset_s32(quant_table, voffset[6][index]);
959 vrow6 = vmulq_s32(vrow6, vtemp);
960
961 vrow7 = vldrwq_gather_shifted_offset_s32(block, voffset[7][index]);
962 vtemp = vldrwq_gather_shifted_offset_s32(quant_table, voffset[7][index]);
963 vrow7 = vmulq_s32(vrow7, vtemp);
964
965 /* Prescale. */
966 vrow0 = vqrshlq_n_s32(vrow0, 9);
967 vrow1 = vqrshlq_n_s32(vrow1, 7);
968 vrow4 = vqrshlq_n_s32(vrow4, 9);
969 vrow7 = vqrshlq_n_s32(vrow7, 7);
970
971 /* stage 1. */
972 VBUTTERFLY_ADDITION(vrow1, vrow7);
973
974 vrow3 = vmulq_n_s32(vrow3, R2_SHR7);
975 vrow5 = vmulq_n_s32(vrow5, R2_SHR7);
976
977 /* stage 2. */
978 VBUTTERFLY_ADDITION(vrow0, vrow4);
979 VBUTTERFLY_MULTIPLICATION(vrow6, vrow2, C6R2_SHR9, S6R2_SHR9);
980 VBUTTERFLY_ADDITION(vrow7, vrow5);
981 VBUTTERFLY_ADDITION(vrow1, vrow3);
982
983 /* stage 3. */
984 VBUTTERFLY_ADDITION(vrow0, vrow6);
985 VBUTTERFLY_ADDITION(vrow4, vrow2);
986 VBUTTERFLY_MULTIPLICATION_SHR6(vrow5, vrow3, C1_SHR8, S1_SHR8);
987 VBUTTERFLY_MULTIPLICATION_SHR6(vrow1, vrow7, C3_SHR8, S3_SHR8);
988
989 /* stage 4. */
990 vtemp = vaddq_s32(vrow0, vrow1);
991 vtemp = vrshrq_n_s32(vtemp, POSTSH1);
992 vstrhq_scatter_offset_s32(output_data, vstroffset1, vtemp);
993
994 vtemp = vaddq_s32(vrow4, vrow5);
995 vtemp = vrshrq_n_s32(vtemp, POSTSH1);
996 vstrhq_scatter_offset_s32(output_data + 1, vstroffset1, vtemp);
997
998 vtemp = vaddq_s32(vrow2, vrow3);
999 vtemp = vrshrq_n_s32(vtemp, POSTSH1);
1000 vstrhq_scatter_offset_s32(output_data + 2, vstroffset1, vtemp);
1001
1002 vtemp = vaddq_s32(vrow6, vrow7);
1003 vtemp = vrshrq_n_s32(vtemp, POSTSH1);
1004 vstrhq_scatter_offset_s32(output_data + 3, vstroffset1, vtemp);
1005
1006 vtemp = vsubq_s32(vrow6, vrow7);
1007 vtemp = vrshrq_n_s32(vtemp, POSTSH1);
1008 vstrhq_scatter_offset_s32(output_data + 4, vstroffset1, vtemp);
1009
1010 vtemp = vsubq_s32(vrow2, vrow3);
1011 vtemp = vrshrq_n_s32(vtemp, POSTSH1);
1012 vstrhq_scatter_offset_s32(output_data + 5, vstroffset1, vtemp);
1013
1014 vtemp = vsubq_s32(vrow4, vrow5);
1015 vtemp = vrshrq_n_s32(vtemp, POSTSH1);
1016 vstrhq_scatter_offset_s32(output_data + 6, vstroffset1, vtemp);
1017
1018 vtemp = vsubq_s32(vrow0, vrow1);
1019 vtemp = vrshrq_n_s32(vtemp, POSTSH1);
1020 vstrhq_scatter_offset_s32(output_data + 7, vstroffset1, vtemp);
1021 }
1022
1023 for (index = 0; index < 2; index++)
1024 {
1025 base = (int16_t const *)(temp_block + 4 * index);
1026
1027 /* Load data. */
1028 vrow0 = vldrhq_s32(base);
1029 vrow1 = vldrhq_s32(base + 8);
1030 vrow2 = vldrhq_s32(base + 16);
1031 vrow3 = vldrhq_s32(base + 24);
1032 vrow4 = vldrhq_s32(base + 32);
1033 vrow5 = vldrhq_s32(base + 40);
1034 vrow6 = vldrhq_s32(base + 48);
1035 vrow7 = vldrhq_s32(base + 56);
1036
1037 /* Prescale. */
1038 vrow0 = vqrshlq_n_s32(vrow0, 9);
1039 vrow1 = vqrshlq_n_s32(vrow1, 7);
1040 vrow4 = vqrshlq_n_s32(vrow4, 9);
1041 vrow7 = vqrshlq_n_s32(vrow7, 7);
1042
1043 /* stage 1. */
1044 VBUTTERFLY_ADDITION(vrow1, vrow7);
1045
1046 vrow3 = vmulq_n_s32(vrow3, R2_SHR7);
1047 vrow5 = vmulq_n_s32(vrow5, R2_SHR7);
1048
1049 /* stage 2. */
1050 VBUTTERFLY_ADDITION(vrow0, vrow4);
1051 VBUTTERFLY_MULTIPLICATION(vrow6, vrow2, C6R2_SHR9, S6R2_SHR9);
1052 VBUTTERFLY_ADDITION(vrow7, vrow5);
1053 VBUTTERFLY_ADDITION(vrow1, vrow3);
1054
1055 /* stage 3. */
1056 VBUTTERFLY_ADDITION(vrow0, vrow6);
1057 VBUTTERFLY_ADDITION(vrow4, vrow2);
1058 VBUTTERFLY_MULTIPLICATION_SHR6(vrow5, vrow3, C1_SHR8, S1_SHR8);
1059 VBUTTERFLY_MULTIPLICATION_SHR6(vrow1, vrow7, C3_SHR8, S3_SHR8);
1060
1061 /* stage 4. */
1062
1063 vtemp = vaddq_s32(vrow0, vrow1);
1064 vtemp16 = vqrshrntq_n_s32(vtemp16, vtemp, POSTSH2);
1065
1066 vtemp = vaddq_s32(vrow4, vrow5);
1067 vtemp16 = vqrshrnbq_n_s32(vtemp16, vtemp, POSTSH2);
1068 vtemp8 = vqmovntq_s16(vtemp8, vtemp16);
1069
1070 vtemp = vaddq_s32(vrow2, vrow3);
1071 vtemp16 = vqrshrntq_n_s32(vtemp16, vtemp, POSTSH2);
1072
1073 vtemp = vaddq_s32(vrow6, vrow7);
1074 vtemp16 = vqrshrnbq_n_s32(vtemp16, vtemp, POSTSH2);
1075 vtemp8 = vqmovnbq_s16(vtemp8, vtemp16);
1076 vstrbq_scatter_offset_s8(out + 4 * index, vstroffset, vtemp8);
1077
1078 vtemp = vsubq_s32(vrow6, vrow7);
1079 vtemp16 = vqrshrntq_n_s32(vtemp16, vtemp, POSTSH2);
1080
1081 vtemp = vsubq_s32(vrow2, vrow3);
1082 vtemp16 = vqrshrnbq_n_s32(vtemp16, vtemp, POSTSH2);
1083 vtemp8 = vqmovntq_s16(vtemp8, vtemp16);
1084
1085 vtemp = vsubq_s32(vrow4, vrow5);
1086 vtemp16 = vqrshrntq_n_s32(vtemp16, vtemp, POSTSH2);
1087
1088 vtemp = vsubq_s32(vrow0, vrow1);
1089 vtemp16 = vqrshrnbq_n_s32(vtemp16, vtemp, POSTSH2);
1090 vtemp8 = vqmovnbq_s16(vtemp8, vtemp16);
1091 vstrbq_scatter_offset_s8(out + (stride << 2) + 4 * index, vstroffset, vtemp8);
1092 }
1093 }
1094 #else
1095
1096 /**************************************************************************/
1097 /* */
1098 /* FUNCTION RELEASE */
1099 /* */
1100 /* _gx_image_reader_jpeg_1d_idct PORTABLE C */
1101 /* 6.3.0 */
1102 /* AUTHOR */
1103 /* */
1104 /* Kenneth Maxwell, Microsoft Corporation */
1105 /* */
1106 /* DESCRIPTION */
1107 /* */
1108 /* Performs 1D Inverse Discrete Consine Transformation. It is an */
1109 /* implementation of LLM (Loeffler, Lighenberg, Moschytz) algorithm. */
1110 /* */
1111 /* INPUT */
1112 /* */
1113 /* input_data Input data */
1114 /* output_data Buffer for output data */
1115 /* post_scale Post scale value */
1116 /* round Value to reduce round error */
1117 /* */
1118 /* OUTPUT */
1119 /* */
1120 /* None */
1121 /* */
1122 /* CALLS */
1123 /* */
1124 /* None */
1125 /* */
1126 /* CALLED BY */
1127 /* */
1128 /* _gx_image_reader_jpeg_2d_idct */
1129 /* */
1130 /* RELEASE HISTORY */
1131 /* */
1132 /* DATE NAME DESCRIPTION */
1133 /* */
1134 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1135 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1136 /* resulting in version 6.1 */
1137 /* 10-31-2023 Ting Zhu Modified comment(s), */
1138 /* improved logic, */
1139 /* resulting in version 6.3.0 */
1140 /* */
1141 /**************************************************************************/
_gx_image_reader_jpeg_1d_idct(INT * input_data,INT * output_data,INT post_scale,INT round)1142 static VOID _gx_image_reader_jpeg_1d_idct(INT *input_data, INT *output_data, INT post_scale, INT round)
1143 {
1144 INT t;
1145
1146 input_data[0] <<= 9;
1147 input_data[1] <<= 7;
1148 input_data[4] <<= 9;
1149 input_data[7] <<= 7;
1150
1151 /* iDCT computation .*/
1152
1153 /* stage 1. */
1154 BUTTERFLY_ADDITION(input_data[1], input_data[7]);
1155
1156 input_data[3] *= R2_SHR7;
1157 input_data[5] *= R2_SHR7;
1158
1159 /* stage 2. */
1160 BUTTERFLY_ADDITION(input_data[0], input_data[4]);
1161 BUTTERFLY_MULTIPLICATION(input_data[6], input_data[2], C6R2_SHR9, S6R2_SHR9);
1162 BUTTERFLY_ADDITION(input_data[7], input_data[5]);
1163 BUTTERFLY_ADDITION(input_data[1], input_data[3]);
1164
1165 /* staget 3. */
1166 BUTTERFLY_ADDITION(input_data[0], input_data[6]);
1167 BUTTERFLY_ADDITION(input_data[4], input_data[2]);
1168 BUTTERFLY_MULTIPLICATION_SHR6(input_data[5], input_data[3], C1_SHR8, S1_SHR8);
1169 BUTTERFLY_MULTIPLICATION_SHR6(input_data[1], input_data[7], C3_SHR8, S3_SHR8);
1170
1171 /* stage 4. */
1172 input_data[0] += round;
1173 input_data[4] += round;
1174 input_data[2] += round;
1175 input_data[6] += round;
1176
1177 output_data[0] = (input_data[0] + input_data[1]) >> post_scale;
1178 output_data[8] = (input_data[4] + input_data[5]) >> post_scale;
1179 output_data[16] = (input_data[2] + input_data[3]) >> post_scale;
1180 output_data[24] = (input_data[6] + input_data[7]) >> post_scale;
1181 output_data[32] = (input_data[6] - input_data[7]) >> post_scale;
1182 output_data[40] = (input_data[2] - input_data[3]) >> post_scale;
1183 output_data[48] = (input_data[4] - input_data[5]) >> post_scale;
1184 output_data[56] = (input_data[0] - input_data[1]) >> post_scale;
1185 }
1186
1187 /**************************************************************************/
1188 /* */
1189 /* FUNCTION RELEASE */
1190 /* */
1191 /* _gx_image_reader_jpeg_dequantize_idct PORTABLE C */
1192 /* 6.3.0 */
1193 /* AUTHOR */
1194 /* */
1195 /* Kenneth Maxwell, Microsoft Corporation */
1196 /* */
1197 /* DESCRIPTION */
1198 /* */
1199 /* Dequatilizes decoded data and performs Inverse Discrete Consine */
1200 /* Transformation. */
1201 /* */
1202 /* INPUT */
1203 /* */
1204 /* block Pointer to decoded data */
1205 /* quant_table Pointer to quantization table */
1206 /* out Buffer for output data */
1207 /* stride Stride of output data */
1208 /* */
1209 /* OUTPUT */
1210 /* */
1211 /* None */
1212 /* */
1213 /* CALLS */
1214 /* */
1215 /* _gx_image_reader_jpeg_1d_idct Perform 1D Inverse Discrete */
1216 /* Consine Transformation */
1217 /* GX_SATURATE_TO_BYTE Saturate to [-128, 127] */
1218 /* */
1219 /* CALLED BY */
1220 /* */
1221 /* _gx_image_reader_jpeg_one_block_decode */
1222 /* */
1223 /* RELEASE HISTORY */
1224 /* */
1225 /* DATE NAME DESCRIPTION */
1226 /* */
1227 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1228 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1229 /* resulting in version 6.1 */
1230 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
1231 /* added range check for */
1232 /* stride, changed return val, */
1233 /* added range check for */
1234 /* table_index, */
1235 /* resulting in version 6.2.0 */
1236 /* 10-31-2023 Ting Zhu Modified comment(s), */
1237 /* improved logic, */
1238 /* resulting in version 6.3.0 */
1239 /* */
1240 /**************************************************************************/
_gx_image_reader_jpeg_dequantize_idct(INT * block,INT * quant_table,GX_BYTE * out,INT stride)1241 static VOID _gx_image_reader_jpeg_dequantize_idct(INT *block, INT *quant_table, GX_BYTE *out, INT stride)
1242 {
1243 static GX_CONST GX_UBYTE reorder_index[] = {
1244 0, 1, 8, 16, 9, 2, 3, 10,
1245 17, 24, 32, 25, 18, 11, 4, 5,
1246 12, 19, 26, 33, 40, 48, 41, 34,
1247 27, 20, 13, 6, 7, 14, 21, 28,
1248 35, 42, 49, 56, 57, 50, 43, 36,
1249 29, 22, 15, 23, 30, 37, 44, 51,
1250 58, 59, 52, 45, 38, 31, 39, 46,
1251 53, 60, 61, 54, 47, 55, 62, 63
1252 };
1253 INT index;
1254 INT jpeg_block[64];
1255 INT temp_block[64];
1256 INT row;
1257
1258 for (index = 0; index < 64; index++)
1259 {
1260 block[index] *= quant_table[index];
1261
1262 /* Reorder from zig-zag order to 8*8 block */
1263 jpeg_block[reorder_index[index]] = block[index];
1264 }
1265
1266 for (index = 0; index < 8; index++)
1267 {
1268 _gx_image_reader_jpeg_1d_idct(jpeg_block + index * 8, temp_block + index, 9, 256); /* row */
1269 }
1270
1271 for (index = 0; index < 8; index++)
1272 {
1273 _gx_image_reader_jpeg_1d_idct(temp_block + index * 8, jpeg_block + index, 12, 2048); /* col */
1274 }
1275
1276 for (row = 0; row < 8; row++)
1277 {
1278 for (index = 0; index < 8; index++)
1279 {
1280 GX_SATURATE_TO_BYTE(out[index], jpeg_block[row * 8 + index]);
1281 }
1282
1283 out += stride;
1284 }
1285 }
1286 #endif
1287
1288 /**************************************************************************/
1289 /* */
1290 /* FUNCTION RELEASE */
1291 /* */
1292 /* _gx_image_reader_jpeg_one_block_decode PORTABLE C */
1293 /* 6.3.0 */
1294 /* AUTHOR */
1295 /* */
1296 /* Kenneth Maxwell, Microsoft Corporation */
1297 /* */
1298 /* DESCRIPTION */
1299 /* */
1300 /* Decode one block of JPEG data. */
1301 /* */
1302 /* INPUT */
1303 /* */
1304 /* jpeg_info JPEG data control block */
1305 /* icomponent Component index */
1306 /* block_data Pointer to decoded data */
1307 /* */
1308 /* OUTPUT */
1309 /* */
1310 /* Status Code */
1311 /* */
1312 /* CALLS */
1313 /* */
1314 /* memset */
1315 /* _gx_image_reader_jpeg_dc_decode Decode dc component */
1316 /* _gx_image_reader_jpeg_ac_decode Decode ac component */
1317 /* _gx_image_reader_jpeg_dequantize_idct Dequatilize decoded data */
1318 /* */
1319 /* CALLED BY */
1320 /* */
1321 /* _gx_image_reader_jpeg_decode */
1322 /* */
1323 /* RELEASE HISTORY */
1324 /* */
1325 /* DATE NAME DESCRIPTION */
1326 /* */
1327 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1328 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1329 /* resulting in version 6.1 */
1330 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
1331 /* returned result of */
1332 /* dequantize_idct, */
1333 /* resulting in version 6.2.0 */
1334 /* 10-31-2023 Ting Zhu Modified comment(s), */
1335 /* improved logic, */
1336 /* resulting in version 6.3.0 */
1337 /* */
1338 /**************************************************************************/
_gx_image_reader_jpeg_one_block_decode(GX_JPEG_INFO * jpeg_info,UINT i_component,GX_BYTE * block_data)1339 static UINT _gx_image_reader_jpeg_one_block_decode(GX_JPEG_INFO *jpeg_info, UINT i_component, GX_BYTE *block_data)
1340 {
1341 INT table_index;
1342 INT stride;
1343
1344 memset(jpeg_info -> gx_jpeg_vecter, 0, 64 * sizeof(UINT));
1345 _gx_image_reader_jpeg_dc_decode(jpeg_info, i_component);
1346 _gx_image_reader_jpeg_ac_decode(jpeg_info, i_component);
1347
1348 if (i_component >= JPG_MAX_COMPONENTS)
1349 {
1350 return GX_FAILURE;
1351 }
1352
1353 stride = ((jpeg_info -> gx_jpeg_sample_factor[i_component] & 0xf0) >> 1);
1354
1355 if (i_component == 0)
1356 {
1357 if (stride > 32)
1358 {
1359 return GX_FAILURE;
1360 }
1361 }
1362 else
1363 {
1364 if (stride > 8)
1365 {
1366 return GX_FAILURE;
1367 }
1368 }
1369
1370 table_index = jpeg_info -> gx_jpeg_qantization_table_index[i_component];
1371
1372 if (table_index >= JPG_QUANT_TABLE_DIMENSION)
1373 {
1374 return GX_FAILURE;
1375 }
1376
1377 _gx_image_reader_jpeg_dequantize_idct(jpeg_info -> gx_jpeg_vecter, jpeg_info -> gx_jpeg_quantization_table[table_index], block_data, stride);
1378 return GX_SUCCESS;
1379 }
1380
1381
1382 #if defined(GX_ENABLE_ARM_HELIUM)
1383 /**************************************************************************/
1384 /* */
1385 /* FUNCTION RELEASE */
1386 /* */
1387 /* _gx_image_reader_jpeg_24xrgb_pixel_write_helium PORTABLE C */
1388 /* 6.3.0 */
1389 /* AUTHOR */
1390 /* */
1391 /* Ting Zhu, Microsoft Corporation */
1392 /* */
1393 /* DESCRIPTION */
1394 /* */
1395 /* Write 24xrgb pixel to memory using Helium intrinsics. */
1396 /* */
1397 /* INPUT */
1398 /* */
1399 /* jpeg_info JPEG control block */
1400 /* vred Red value vector */
1401 /* vgreen Green value vector */
1402 /* vblue Blue value vector */
1403 /* size Number of pixels to write */
1404 /* */
1405 /* OUTPUT */
1406 /* */
1407 /* vstrbq_scatter_offset_u8 Scatter 8-bit values to */
1408 /* memory */
1409 /* vstrbq_scatter_offset_p_u8 Optionaly scatter 8-bit */
1410 /* values to memory */
1411 /* */
1412 /* CALLS */
1413 /* */
1414 /* None */
1415 /* */
1416 /* CALLED BY */
1417 /* */
1418 /* _gx_image_reader_jpeg_one_mcu_write */
1419 /* _gx_image_reader_jpeg_one_mcu_rotated_write */
1420 /* */
1421 /* RELEASE HISTORY */
1422 /* */
1423 /* DATE NAME DESCRIPTION */
1424 /* */
1425 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
1426 /* */
1427 /**************************************************************************/
_gx_image_reader_jpeg_24xrgb_pixel_write_helium(GX_JPEG_INFO * jpeg_info,uint8x16_t vred,uint8x16_t vgreen,uint8x16_t vblue,INT size)1428 static VOID _gx_image_reader_jpeg_24xrgb_pixel_write_helium(GX_JPEG_INFO *jpeg_info, uint8x16_t vred, uint8x16_t vgreen, uint8x16_t vblue, INT size)
1429 {
1430 INT index;
1431
1432 for(index = 0; index < size; index++)
1433 {
1434 *((GX_COLOR *)jpeg_info -> gx_jpeg_putdata) = 0xff000000 | ((ULONG)vred[index] << 16) | ((ULONG)vgreen[index] << 8) | (ULONG)vblue[index];
1435
1436 jpeg_info -> gx_jpeg_putdata += 4;
1437 }
1438 }
1439 #else
1440 /**************************************************************************/
1441 /* */
1442 /* FUNCTION RELEASE */
1443 /* */
1444 /* _gx_image_reader_jpeg_1555xrgb_pixel_write PORTABLE C */
1445 /* 6.3.0 */
1446 /* AUTHOR */
1447 /* */
1448 /* Ting Zhu, Microsoft Corporation */
1449 /* */
1450 /* DESCRIPTION */
1451 /* */
1452 /* Write 24xrgb pixel to memory. */
1453 /* */
1454 /* INPUT */
1455 /* */
1456 /* jpeg_info JPEG control block */
1457 /* red Red value */
1458 /* green Green value */
1459 /* blue Blue value */
1460 /* */
1461 /* OUTPUT */
1462 /* */
1463 /* None */
1464 /* */
1465 /* CALLS */
1466 /* */
1467 /* None */
1468 /* */
1469 /* CALLED BY */
1470 /* */
1471 /* _gx_image_reader_jpeg_one_mcu_write */
1472 /* _gx_image_reader_jpeg_one_mcu_rotated_write */
1473 /* */
1474 /* RELEASE HISTORY */
1475 /* */
1476 /* DATE NAME DESCRIPTION */
1477 /* */
1478 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
1479 /* */
1480 /**************************************************************************/
_gx_image_reader_jpeg_24xrgb_pixel_write(GX_JPEG_INFO * jpeg_info,GX_UBYTE red,GX_UBYTE green,GX_UBYTE blue)1481 static VOID _gx_image_reader_jpeg_24xrgb_pixel_write(GX_JPEG_INFO *jpeg_info, GX_UBYTE red, GX_UBYTE green, GX_UBYTE blue)
1482 {
1483 *((GX_COLOR *)jpeg_info -> gx_jpeg_putdata) = 0xff000000 | ((ULONG)red << 16) | ((ULONG)green << 8) | (ULONG)blue;
1484
1485 jpeg_info -> gx_jpeg_putdata += 4;
1486 }
1487 #endif
1488
1489 #if defined(GX_ENABLE_ARM_HELIUM)
1490 /**************************************************************************/
1491 /* */
1492 /* FUNCTION RELEASE */
1493 /* */
1494 /* _gx_image_reader_jpeg_24bpp_pixel_write_helium PORTABLE C */
1495 /* 6.3.0 */
1496 /* AUTHOR */
1497 /* */
1498 /* Ting Zhu, Microsoft Corporation */
1499 /* */
1500 /* DESCRIPTION */
1501 /* */
1502 /* Internal helper function to write 24xrgb pixel to memory using */
1503 /* Helium intrinsics. */
1504 /* */
1505 /* INPUT */
1506 /* */
1507 /* jpeg_info JPEG control block */
1508 /* vred Red value vector */
1509 /* vgreen Green value vector */
1510 /* vblue Blue value vector */
1511 /* size Number of pixels to write */
1512 /* */
1513 /* OUTPUT */
1514 /* */
1515 /* vstrbq_scatter_offset_u8 Scatter 8-bit values to */
1516 /* memory */
1517 /* vstrbq_scatter_offset_p_u8 Optionally scatter 8-bit */
1518 /* values to memory */
1519 /* */
1520 /* CALLS */
1521 /* */
1522 /* None */
1523 /* */
1524 /* CALLED BY */
1525 /* */
1526 /* _gx_image_reader_jpeg_one_mcu_write */
1527 /* _gx_image_reader_jpeg_one_mcu_rotated_write */
1528 /* */
1529 /* RELEASE HISTORY */
1530 /* */
1531 /* DATE NAME DESCRIPTION */
1532 /* */
1533 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
1534 /* */
1535 /**************************************************************************/
_gx_image_reader_jpeg_24bpp_pixel_write_helium(GX_JPEG_INFO * jpeg_info,uint8x16_t vred,uint8x16_t vgreen,uint8x16_t vblue,INT size)1536 static VOID _gx_image_reader_jpeg_24bpp_pixel_write_helium(GX_JPEG_INFO *jpeg_info, uint8x16_t vred, uint8x16_t vgreen, uint8x16_t vblue, INT size)
1537 {
1538 static uint8x16_t voffset = {0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45};
1539 mve_pred16_t p;
1540
1541 if (size == 16)
1542 {
1543 vstrbq_scatter_offset_u8(jpeg_info -> gx_jpeg_putdata++, voffset, vred);
1544 vstrbq_scatter_offset_u8(jpeg_info -> gx_jpeg_putdata++, voffset, vgreen);
1545 vstrbq_scatter_offset_u8(jpeg_info -> gx_jpeg_putdata++, voffset, vblue);
1546 jpeg_info -> gx_jpeg_putdata += 45;
1547 }
1548 else
1549 {
1550 /* Write the specified size of RGB values to memory. */
1551 p = 0xffff >> (16 - size);
1552 vstrbq_scatter_offset_p_u8(jpeg_info -> gx_jpeg_putdata++, voffset, vred, p);
1553 vstrbq_scatter_offset_p_u8(jpeg_info -> gx_jpeg_putdata++, voffset, vgreen, p);
1554 vstrbq_scatter_offset_p_u8(jpeg_info -> gx_jpeg_putdata++, voffset, vblue, p);
1555 jpeg_info -> gx_jpeg_putdata += (size - 1) * 3;
1556 }
1557 }
1558 #else
1559 /**************************************************************************/
1560 /* */
1561 /* FUNCTION RELEASE */
1562 /* */
1563 /* _gx_image_reader_jpeg_24bpp_pixel_write PORTABLE C */
1564 /* 6.3.0 */
1565 /* AUTHOR */
1566 /* */
1567 /* Ting Zhu, Microsoft Corporation */
1568 /* */
1569 /* DESCRIPTION */
1570 /* */
1571 /* Write 24bpp pixel to memory. */
1572 /* */
1573 /* INPUT */
1574 /* */
1575 /* jpeg_info JPEG control block */
1576 /* red Red value */
1577 /* green Green value */
1578 /* blue Blue value */
1579 /* */
1580 /* OUTPUT */
1581 /* */
1582 /* None */
1583 /* */
1584 /* CALLS */
1585 /* */
1586 /* None */
1587 /* */
1588 /* CALLED BY */
1589 /* */
1590 /* _gx_image_reader_jpeg_one_mcu_write */
1591 /* _gx_image_reader_jpeg_one_mcu_rotated_write */
1592 /* */
1593 /* RELEASE HISTORY */
1594 /* */
1595 /* DATE NAME DESCRIPTION */
1596 /* */
1597 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
1598 /* */
1599 /**************************************************************************/
_gx_image_reader_jpeg_24bpp_pixel_write(GX_JPEG_INFO * jpeg_info,GX_UBYTE red,GX_UBYTE green,GX_UBYTE blue)1600 static VOID _gx_image_reader_jpeg_24bpp_pixel_write(GX_JPEG_INFO *jpeg_info, GX_UBYTE red, GX_UBYTE green, GX_UBYTE blue)
1601 {
1602 *jpeg_info -> gx_jpeg_putdata++ = red;
1603 *jpeg_info -> gx_jpeg_putdata++ = green;
1604 *jpeg_info -> gx_jpeg_putdata++ = blue;
1605 }
1606 #endif
1607
1608 #if defined(GX_ENABLE_ARM_HELIUM)
1609 /**************************************************************************/
1610 /* */
1611 /* FUNCTION RELEASE */
1612 /* */
1613 /* _gx_image_reader_jpeg_565rgb_pixel_write_helium PORTABLE C */
1614 /* 6.3.0 */
1615 /* AUTHOR */
1616 /* */
1617 /* Ting Zhu, Microsoft Corporation */
1618 /* */
1619 /* DESCRIPTION */
1620 /* */
1621 /* Internal helper function to write 565rgb pixel to memory using */
1622 /* Helium intrinsics. */
1623 /* */
1624 /* INPUT */
1625 /* */
1626 /* jpeg_info JPEG control block */
1627 /* vred Red value vector */
1628 /* vgreen Green value vector */
1629 /* vblue Blue value vector */
1630 /* size Number of pixels to write */
1631 /* */
1632 /* OUTPUT */
1633 /* */
1634 /* vshrq_n_u8 Unsigned 8-bit shift right */
1635 /* vldrbq_u16 Load 8-bit value to a */
1636 /* destination register */
1637 /* vshlq_n_u16 Unsigned 16-bit shift left */
1638 /* vorrq_u16 Unsigned 16-bit OR */
1639 /* vstrhq_u16 Store 16-bit values from */
1640 /* register to memory */
1641 /* vstrhq_p_u16 Optionally store 16-bit */
1642 /* values from register to */
1643 /* memory */
1644 /* */
1645 /* CALLS */
1646 /* */
1647 /* None */
1648 /* */
1649 /* CALLED BY */
1650 /* */
1651 /* _gx_image_reader_jpeg_one_mcu_write */
1652 /* _gx_image_reader_jpeg_one_mcu_rotated_write */
1653 /* */
1654 /* RELEASE HISTORY */
1655 /* */
1656 /* DATE NAME DESCRIPTION */
1657 /* */
1658 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
1659 /* */
1660 /**************************************************************************/
_gx_image_reader_jpeg_565rgb_pixel_write_helium(GX_JPEG_INFO * jpeg_info,uint8x16_t vred,uint8x16_t vgreen,uint8x16_t vblue,INT size)1661 static VOID _gx_image_reader_jpeg_565rgb_pixel_write_helium(GX_JPEG_INFO *jpeg_info, uint8x16_t vred, uint8x16_t vgreen, uint8x16_t vblue, INT size)
1662 {
1663 uint16x8_t vresult;
1664 uint16x8_t vtemp;
1665 INT index;
1666 mve_pred16_t p;
1667 uint16_t *put = (uint16_t *)jpeg_info -> gx_jpeg_putdata;
1668 GX_UBYTE red[16];
1669 GX_UBYTE green[16];
1670 GX_UBYTE blue[16];
1671
1672 vred = vshrq_n_u8(vred, 3);
1673 vgreen = vshrq_n_u8(vgreen, 2);
1674 vblue = vshrq_n_u8(vblue, 3);
1675
1676 vstrbq(red, vred);
1677 vstrbq(green, vgreen);
1678 vstrbq(blue, vblue);
1679
1680 for (index = 0; index <= 8; index += 8)
1681 {
1682 vtemp = vldrbq_u16(&red[index]);
1683 vresult = vshlq_n_u16(vtemp, 11);
1684
1685 vtemp = vldrbq_u16(&green[index]);
1686 vtemp = vshlq_n_u16(vtemp, 5);
1687 vresult = vorrq_u16(vresult, vtemp);
1688
1689 vtemp = vldrbq_u16(&blue[index]);
1690 vresult = vorrq_u16(vresult, vtemp);
1691
1692 if (size >= 8)
1693 {
1694 vstrhq_u16(put, vresult);
1695 put += 8;
1696 size -= 8;
1697 }
1698 else
1699 {
1700 p = 0xffff >> (16 - (size << 1));
1701 vstrhq_p_u16(put, vresult, p);
1702 put += size;
1703 break;
1704 }
1705 }
1706
1707 jpeg_info -> gx_jpeg_putdata = (GX_UBYTE *)put;
1708 }
1709 #else
1710 /**************************************************************************/
1711 /* */
1712 /* FUNCTION RELEASE */
1713 /* */
1714 /* _gx_image_reader_jpeg_1555xrgb_pixel_write PORTABLE C */
1715 /* 6.3.0 */
1716 /* AUTHOR */
1717 /* */
1718 /* Ting Zhu, Microsoft Corporation */
1719 /* */
1720 /* DESCRIPTION */
1721 /* */
1722 /* Write 1555xrgb pixel to memory. */
1723 /* */
1724 /* INPUT */
1725 /* */
1726 /* jpeg_info JPEG control block */
1727 /* red Red value */
1728 /* green Green value */
1729 /* blue Blue value */
1730 /* */
1731 /* OUTPUT */
1732 /* */
1733 /* None */
1734 /* */
1735 /* CALLS */
1736 /* */
1737 /* GX_SATURATE_TO_5BIT Saturate the value to 5 bits */
1738 /* */
1739 /* CALLED BY */
1740 /* */
1741 /* _gx_image_reader_jpeg_one_mcu_write */
1742 /* _gx_image_reader_jpeg_one_mcu_rotated_write */
1743 /* */
1744 /* RELEASE HISTORY */
1745 /* */
1746 /* DATE NAME DESCRIPTION */
1747 /* */
1748 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
1749 /* */
1750 /**************************************************************************/
_gx_image_reader_jpeg_565rgb_pixel_write(GX_JPEG_INFO * jpeg_info,GX_UBYTE red,GX_UBYTE green,GX_UBYTE blue)1751 static VOID _gx_image_reader_jpeg_565rgb_pixel_write(GX_JPEG_INFO *jpeg_info, GX_UBYTE red, GX_UBYTE green, GX_UBYTE blue)
1752 {
1753 /* Make sure the range of the RGB values are within bound. */
1754 red >>= 3;
1755 green >>= 2;
1756 blue >>= 3;
1757
1758 *((USHORT *)jpeg_info -> gx_jpeg_putdata) = (USHORT)((red << 11) | (green << 5 | blue));
1759 jpeg_info -> gx_jpeg_putdata += 2;
1760 }
1761 #endif
1762
1763 #if defined(GX_ENABLE_ARM_HELIUM)
1764 /**************************************************************************/
1765 /* */
1766 /* FUNCTION RELEASE */
1767 /* */
1768 /* _gx_image_reader_jpeg_1555xrgb_pixel_write_helium PORTABLE C */
1769 /* 6.3.0 */
1770 /* AUTHOR */
1771 /* */
1772 /* Ting Zhu, Microsoft Corporation */
1773 /* */
1774 /* DESCRIPTION */
1775 /* */
1776 /* Internal helper function to write 1555xrgb pixel to memory using */
1777 /* Helium intrinsics. */
1778 /* */
1779 /* INPUT */
1780 /* */
1781 /* jpeg_info JPEG control block */
1782 /* vred Red value vector */
1783 /* vgreen Green value vector */
1784 /* vblue Blue value vector */
1785 /* size Number of pixels to write */
1786 /* */
1787 /* OUTPUT */
1788 /* */
1789 /* vshrq_n_u8 Unsigned 8-bit shift right */
1790 /* vldrbq_u16 Load 8-bit value to a */
1791 /* destination register */
1792 /* vshlq_n_u16 Unsigned 16-bit shift left */
1793 /* vorrq_u16 Unsigned 16-bit OR */
1794 /* vstrhq_u16 Store 16-bit values from */
1795 /* register to memory */
1796 /* vstrhq_p_u16 Optionally store 16-bit */
1797 /* values from register to */
1798 /* memory */
1799 /* */
1800 /* CALLS */
1801 /* */
1802 /* None */
1803 /* */
1804 /* CALLED BY */
1805 /* */
1806 /* _gx_image_reader_jpeg_one_mcu_write */
1807 /* _gx_image_reader_jpeg_one_mcu_rotated_write */
1808 /* */
1809 /* RELEASE HISTORY */
1810 /* */
1811 /* DATE NAME DESCRIPTION */
1812 /* */
1813 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
1814 /* */
1815 /**************************************************************************/
_gx_image_reader_jpeg_1555xrgb_pixel_write_helium(GX_JPEG_INFO * jpeg_info,uint8x16_t vred,uint8x16_t vgreen,uint8x16_t vblue,INT size)1816 static VOID _gx_image_reader_jpeg_1555xrgb_pixel_write_helium(GX_JPEG_INFO *jpeg_info, uint8x16_t vred, uint8x16_t vgreen, uint8x16_t vblue, INT size)
1817 {
1818 uint16x8_t vresult;
1819 uint16x8_t vtemp;
1820 INT index;
1821 uint16_t *put = (uint16_t *)jpeg_info -> gx_jpeg_putdata;
1822 mve_pred16_t p;
1823 GX_UBYTE red[16];
1824 GX_UBYTE green[16];
1825 GX_UBYTE blue[16];
1826
1827 vred = vshrq_n_u8(vred, 3);
1828 vgreen = vshrq_n_u8(vgreen, 3);
1829 vblue = vshrq_n_u8(vblue, 3);
1830
1831 vstrbq(red, vred);
1832 vstrbq(green, vgreen);
1833 vstrbq(blue, vblue);
1834
1835 for (index = 0; index <= 8; index += 8)
1836 {
1837 vtemp = vldrbq_u16(&red[index]);
1838 vresult = vshlq_n_u16(vtemp, 10);
1839
1840 vtemp = vldrbq_u16(&green[index]);
1841 vtemp = vshlq_n_u16(vtemp, 5);
1842 vresult = vorrq_u16(vresult, vtemp);
1843
1844 vtemp = vldrbq_u16(&blue[index]);
1845 vresult = vorrq_u16(vresult, vtemp);
1846
1847 if (size >= 8)
1848 {
1849 vstrhq_u16(put, vresult);
1850 put += 8;
1851 size -= 8;
1852 }
1853 else
1854 {
1855 p = 0xffff >> (16 - (size << 1));
1856 vstrhq_p_u16(put, vresult, p);
1857 put += size;
1858 break;
1859 }
1860 }
1861
1862 jpeg_info -> gx_jpeg_putdata = (GX_UBYTE *)put;
1863 }
1864 #else
1865 /**************************************************************************/
1866 /* */
1867 /* FUNCTION RELEASE */
1868 /* */
1869 /* _gx_image_reader_jpeg_1555xrgb_pixel_write PORTABLE C */
1870 /* 6.3.0 */
1871 /* AUTHOR */
1872 /* */
1873 /* Ting Zhu, Microsoft Corporation */
1874 /* */
1875 /* DESCRIPTION */
1876 /* */
1877 /* Write 1555xrgb pixel to memory. */
1878 /* */
1879 /* INPUT */
1880 /* */
1881 /* jpeg_info JPEG control block */
1882 /* red Red value */
1883 /* green Green value */
1884 /* blue Blue value */
1885 /* */
1886 /* OUTPUT */
1887 /* */
1888 /* None */
1889 /* */
1890 /* CALLS */
1891 /* */
1892 /* GX_SATURATE_TO_5BIT Saturate the value to 5 bits */
1893 /* */
1894 /* CALLED BY */
1895 /* */
1896 /* _gx_image_reader_jpeg_one_mcu_write */
1897 /* _gx_image_reader_jpeg_one_mcu_rotated_write */
1898 /* */
1899 /* RELEASE HISTORY */
1900 /* */
1901 /* DATE NAME DESCRIPTION */
1902 /* */
1903 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
1904 /* */
1905 /**************************************************************************/
_gx_image_reader_jpeg_1555xrgb_pixel_write(GX_JPEG_INFO * jpeg_info,GX_UBYTE red,GX_UBYTE green,GX_UBYTE blue)1906 static VOID _gx_image_reader_jpeg_1555xrgb_pixel_write(GX_JPEG_INFO *jpeg_info, GX_UBYTE red, GX_UBYTE green, GX_UBYTE blue)
1907 {
1908 /* Make sure the range of the RGB values are within bound. */
1909 red >>= 3;
1910 green >>= 3;
1911 blue >>= 3;
1912
1913 *((USHORT *)jpeg_info -> gx_jpeg_putdata) = (USHORT)((red << 10) | (green << 5 | blue));
1914 jpeg_info -> gx_jpeg_putdata += 2;
1915 }
1916 #endif
1917
1918 /**************************************************************************/
1919 /* */
1920 /* FUNCTION RELEASE */
1921 /* */
1922 /* _gx_image_reader_jpeg_pixel_write_info_set PORTABLE C */
1923 /* 6.3.0 */
1924 /* AUTHOR */
1925 /* */
1926 /* Ting Zhu, Microsoft Corporation */
1927 /* */
1928 /* DESCRIPTION */
1929 /* */
1930 /* Set information for writing pixel to memory. */
1931 /* */
1932 /* INPUT */
1933 /* */
1934 /* jpeg_info JPEG control block */
1935 /* */
1936 /* OUTPUT */
1937 /* */
1938 /* Status Code */
1939 /* */
1940 /* CALLS */
1941 /* */
1942 /* _gx_image_reader_jpeg_565rgb_pixel_write_helium */
1943 /* Write 565rgb pixel to memory */
1944 /* _gx_image_reader_jpeg_565rgb_pixel_write */
1945 /* Write 565rgb pixel to memory */
1946 /* _gx_image_reader_jpeg_1555xrgb_pixel_write_helium */
1947 /* Write 1555xrgb pixel to memory*/
1948 /* _gx_image_reader_jpeg_1555xrgb_pixel_write */
1949 /* Write 1555xrgb pixel to memory*/
1950 /* _gx_image_reader_jpeg_24xrgb_24bpp_pixel_write_helium */
1951 /* Write 24xrgb or 24rgb pixel */
1952 /* to memory */
1953 /* _gx_image_reader_jpeg_24xrgb_24bpp_pixel_write */
1954 /* Write 24xrgb or 24rgb pixel */
1955 /* to memory */
1956 /* */
1957 /* CALLED BY */
1958 /* */
1959 /* _gx_image_reader_jpeg_decompress */
1960 /* */
1961 /* RELEASE HISTORY */
1962 /* */
1963 /* DATE NAME DESCRIPTION */
1964 /* */
1965 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
1966 /* */
1967 /**************************************************************************/
_gx_image_reader_jpeg_pixel_write_info_set(GX_JPEG_INFO * jpeg_info)1968 static UINT _gx_image_reader_jpeg_pixel_write_info_set(GX_JPEG_INFO *jpeg_info)
1969 {
1970 if (!jpeg_info -> gx_jpeg_output_width)
1971 {
1972 jpeg_info -> gx_jpeg_output_width = jpeg_info -> gx_jpeg_width;
1973 jpeg_info -> gx_jpeg_output_height = jpeg_info -> gx_jpeg_height;
1974
1975 _gx_utility_rectangle_define(&jpeg_info -> gx_jpeg_output_clip, 0, 0, (GX_VALUE)(jpeg_info -> gx_jpeg_width - 1), (GX_VALUE)(jpeg_info -> gx_jpeg_height - 1));
1976 }
1977
1978 jpeg_info -> gx_jpeg_output_stride = jpeg_info -> gx_jpeg_output_rotation_angle == 0 ? jpeg_info -> gx_jpeg_output_width : jpeg_info -> gx_jpeg_output_height;
1979
1980 /* Set pixel write callback. */
1981 switch (jpeg_info -> gx_jpeg_output_color_format)
1982 {
1983 case GX_COLOR_FORMAT_565RGB:
1984 #if defined(GX_ENABLE_ARM_HELIUM)
1985 jpeg_info -> gx_jpeg_pixel_write_helium = _gx_image_reader_jpeg_565rgb_pixel_write_helium;
1986 #else
1987 jpeg_info -> gx_jpeg_pixel_write = _gx_image_reader_jpeg_565rgb_pixel_write;
1988 #endif
1989 jpeg_info -> gx_jpeg_output_bpp = 2;
1990 jpeg_info -> gx_jpeg_output_stride <<= 1;
1991 break;
1992
1993 case GX_COLOR_FORMAT_1555XRGB:
1994 #if defined(GX_ENABLE_ARM_HELIUM)
1995 jpeg_info -> gx_jpeg_pixel_write_helium = _gx_image_reader_jpeg_1555xrgb_pixel_write_helium;
1996 #else
1997 jpeg_info -> gx_jpeg_pixel_write = _gx_image_reader_jpeg_1555xrgb_pixel_write;
1998 #endif
1999 jpeg_info -> gx_jpeg_output_bpp = 2;
2000 jpeg_info -> gx_jpeg_output_stride <<= 1;
2001 break;
2002
2003 case GX_COLOR_FORMAT_32ARGB:
2004 case GX_COLOR_FORMAT_24XRGB:
2005 #if defined(GX_ENABLE_ARM_HELIUM)
2006 jpeg_info -> gx_jpeg_pixel_write_helium = _gx_image_reader_jpeg_24xrgb_pixel_write_helium;
2007 #else
2008 jpeg_info -> gx_jpeg_pixel_write = _gx_image_reader_jpeg_24xrgb_pixel_write;
2009 #endif
2010 jpeg_info -> gx_jpeg_output_bpp = 4;
2011 jpeg_info -> gx_jpeg_output_stride <<= 2;
2012 break;
2013
2014 case GX_IMAGE_FORMAT_24BPP:
2015 default:
2016 #if defined(GX_ENABLE_ARM_HELIUM)
2017 jpeg_info -> gx_jpeg_pixel_write_helium = _gx_image_reader_jpeg_24bpp_pixel_write_helium;
2018 #else
2019 jpeg_info -> gx_jpeg_pixel_write = _gx_image_reader_jpeg_24bpp_pixel_write;
2020 #endif
2021 jpeg_info -> gx_jpeg_output_bpp = 3;
2022 jpeg_info -> gx_jpeg_output_stride = (jpeg_info -> gx_jpeg_output_width * 3);
2023 jpeg_info -> gx_jpeg_output_color_format = GX_IMAGE_FORMAT_24BPP;
2024
2025 if (jpeg_info -> gx_jpeg_output_buffer)
2026 {
2027 return GX_NOT_SUPPORTED;
2028 }
2029 break;
2030 }
2031
2032 if (!jpeg_info -> gx_jpeg_output_buffer)
2033 {
2034 jpeg_info -> gx_jpeg_output_buffer = (GX_UBYTE *)_gx_system_memory_allocator((ULONG)(jpeg_info -> gx_jpeg_height * jpeg_info -> gx_jpeg_width * jpeg_info -> gx_jpeg_output_bpp));
2035 if (!jpeg_info -> gx_jpeg_output_buffer)
2036 {
2037 return GX_SYSTEM_MEMORY_ERROR;
2038 }
2039 }
2040
2041 return GX_SUCCESS;
2042 }
2043
2044 /**************************************************************************/
2045 /* */
2046 /* FUNCTION RELEASE */
2047 /* */
2048 /* _gx_image_reader_jpeg_one_mcu_write PORTABLE C */
2049 /* 6.3.0 */
2050 /* AUTHOR */
2051 /* */
2052 /* Kenneth Maxwell, Microsoft Corporation */
2053 /* */
2054 /* DESCRIPTION */
2055 /* */
2056 /* Write decoded data of one MCU block into specified memory. */
2057 /* */
2058 /* INPUT */
2059 /* */
2060 /* jpeg_info JPEG control block */
2061 /* xpos X position in image */
2062 /* ypos y position in image */
2063 /* h Horizontal sampling factor */
2064 /* v Vertical sampling factor */
2065 /* */
2066 /* OUTPUT */
2067 /* */
2068 /* Status Code */
2069 /* */
2070 /* CALLS */
2071 /* */
2072 /* vldrbq_gather_offset_s8 Gather bytes from memory */
2073 /* GX_JPEG_DECODE_YCBCR2RGB_HELIUM Convert YCbCr to RGB */
2074 /* GX_JPEG_DECODE_YCBCR2RGB Convert YCbCr to RGB */
2075 /* [gx_jpeg_pixel_write_helium] Write pixel to memory */
2076 /* [gx_jpeg_pixel_write] Write pixel to memory */
2077 /* */
2078 /* CALLED BY */
2079 /* */
2080 /* _gx_image_reader_jpeg_decode */
2081 /* */
2082 /* RELEASE HISTORY */
2083 /* */
2084 /* DATE NAME DESCRIPTION */
2085 /* */
2086 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2087 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2088 /* resulting in version 6.1 */
2089 /* 10-31-2023 Ting Zhu Modified comment(s), */
2090 /* added Helium support, */
2091 /* added partial canvas buffer */
2092 /* support, */
2093 /* resulting in version 6.3.0 */
2094 /* */
2095 /**************************************************************************/
_gx_image_reader_jpeg_one_mcu_write(GX_JPEG_INFO * jpeg_info,INT xpos,INT ypos,INT h,INT v)2096 static UINT _gx_image_reader_jpeg_one_mcu_write(GX_JPEG_INFO *jpeg_info, INT xpos, INT ypos, INT h, INT v)
2097 {
2098 GX_UBYTE *put;
2099 INT x;
2100 INT y;
2101 INT coff;
2102 INT xstart = 0;
2103 INT xend;
2104 INT ystart = 0;
2105 INT yend;
2106
2107 #if defined(GX_ENABLE_ARM_HELIUM)
2108 int8x16_t vY;
2109 int8x16_t vCb;
2110 int8x16_t vCr;
2111 GX_UBYTE size;
2112 uint8x16_t vred;
2113 uint8x16_t vgreen;
2114 uint8x16_t vblue;
2115 GX_UBYTE index;
2116 #else
2117 GX_BYTE Y;
2118 GX_BYTE Cb;
2119 GX_BYTE Cr;
2120 INT red;
2121 INT green;
2122 INT blue;
2123 #endif
2124
2125 yend = (v << 3);
2126 xend = (h << 3);
2127
2128
2129 if (xpos < jpeg_info -> gx_jpeg_output_clip.gx_rectangle_left)
2130 {
2131 xstart = jpeg_info -> gx_jpeg_output_clip.gx_rectangle_left - xpos;
2132 }
2133
2134 if (xpos + xend > jpeg_info -> gx_jpeg_output_clip.gx_rectangle_right + 1)
2135 {
2136 xend = jpeg_info -> gx_jpeg_output_clip.gx_rectangle_right + 1 - xpos;
2137 }
2138
2139 if (ypos < jpeg_info -> gx_jpeg_output_clip.gx_rectangle_top)
2140 {
2141 ystart = jpeg_info -> gx_jpeg_output_clip.gx_rectangle_top - ypos;
2142 }
2143
2144 if (ypos + yend > jpeg_info -> gx_jpeg_output_clip.gx_rectangle_bottom + 1)
2145 {
2146 yend = jpeg_info -> gx_jpeg_output_clip.gx_rectangle_bottom + 1 - ypos;
2147 }
2148
2149 put = (GX_UBYTE *)jpeg_info -> gx_jpeg_output_buffer;
2150 #if defined(GX_ENABLE_CANVAS_PARTIAL_FRAME_BUFFER)
2151 put += (ypos + ystart - jpeg_info -> gx_jpeg_output_buffer_offset_y) * jpeg_info -> gx_jpeg_output_stride;
2152 put += (xpos + xstart - jpeg_info -> gx_jpeg_output_buffer_offset_x) * jpeg_info -> gx_jpeg_output_bpp;
2153 #else
2154 put += (ypos + ystart) * jpeg_info -> gx_jpeg_output_stride;
2155 put += (xpos + xstart) * jpeg_info -> gx_jpeg_output_bpp;
2156 #endif
2157
2158 #if defined(GX_ENABLE_ARM_HELIUM)
2159 index = (h == 1 ? 0 : (h - 1 + (xstart % h)));
2160 #endif
2161
2162 for (y = ystart; y < yend; y++)
2163 {
2164 jpeg_info -> gx_jpeg_putdata = put;
2165
2166 #if defined(GX_ENABLE_ARM_HELIUM)
2167 for (x = xstart; x < xend; x += size)
2168 {
2169 size = xend - x;
2170
2171 if (size > 16)
2172 {
2173 size = 16;
2174 }
2175
2176 coff = x / h + ((y / v) << 3);
2177
2178 vY = vldrbq_s8(jpeg_info -> gx_jpeg_Y_block + x + y * h * 8);
2179 vCb = vldrbq_gather_offset_s8(jpeg_info -> gx_jpeg_Cb_block + coff, _gx_jpeg_cbcr_offset_table[index]);
2180 vCr = vldrbq_gather_offset_s8(jpeg_info -> gx_jpeg_Cr_block + coff, _gx_jpeg_cbcr_offset_table[index]);
2181
2182 /* Convert YCbCr to RGB. */
2183 GX_JPEG_DECODE_YCBCR2RGB_HELIUM(vred, vgreen, vblue, vY, vCb, vCr);
2184
2185 jpeg_info -> gx_jpeg_pixel_write_helium(jpeg_info, vred, vgreen, vblue, size);
2186 }
2187 #else
2188 for (x = xstart; x < xend; x++)
2189 {
2190 coff = x / h + ((y / v) << 3);
2191
2192 Y = jpeg_info -> gx_jpeg_Y_block[x + y * h * 8];
2193 Cb = jpeg_info -> gx_jpeg_Cb_block[coff];
2194 Cr = jpeg_info -> gx_jpeg_Cr_block[coff];
2195
2196 GX_JPEG_DECODE_YCBCR2RGB(red, green, blue, Y, Cb, Cr);
2197
2198 GX_SATURATE_TO_UBYTE(red, red);
2199 GX_SATURATE_TO_UBYTE(green, green);
2200 GX_SATURATE_TO_UBYTE(blue, blue);
2201
2202 jpeg_info -> gx_jpeg_pixel_write(jpeg_info, (GX_UBYTE)red, (GX_UBYTE)green, (GX_UBYTE)blue);
2203 }
2204 #endif
2205
2206 put += jpeg_info -> gx_jpeg_output_stride;
2207 }
2208
2209 return GX_SUCCESS;
2210 }
2211
2212 /**************************************************************************/
2213 /* */
2214 /* FUNCTION RELEASE */
2215 /* */
2216 /* _gx_image_reader_jpeg_one_mcu_rotated_write PORTABLE C */
2217 /* 6.3.0 */
2218 /* AUTHOR */
2219 /* */
2220 /* Ting Zhu, Microsoft Corporation */
2221 /* */
2222 /* DESCRIPTION */
2223 /* */
2224 /* Write decoded data of one MCU block into specified memory. */
2225 /* */
2226 /* INPUT */
2227 /* */
2228 /* jpeg_info JPEG control block */
2229 /* xpos X position in image */
2230 /* ypos y position in image */
2231 /* h Horizontal sampling factor */
2232 /* v Vertical sampling factor */
2233 /* */
2234 /* OUTPUT */
2235 /* */
2236 /* Status Code */
2237 /* */
2238 /* CALLS */
2239 /* */
2240 /* vldrbq_gather_offset_s8 Gather bytes from memory */
2241 /* GX_JPEG_DECODE_YCBCR2RGB_HELIUM Convert YCbCr to RGB */
2242 /* GX_JPEG_DECODE_YCBCR2RGB Convert YCbCr to RGB */
2243 /* [gx_jpeg_pixel_write_helium] Write pixel to memory */
2244 /* [gx_jpeg_pixel_write] Write pixel to memory */
2245 /* */
2246 /* CALLED BY */
2247 /* */
2248 /* _gx_image_reader_jpeg_decode */
2249 /* */
2250 /* RELEASE HISTORY */
2251 /* */
2252 /* DATE NAME DESCRIPTION */
2253 /* */
2254 /* 10-31-2023 Ting Zhu Initial Version 6.3.0 */
2255 /* */
2256 /**************************************************************************/
_gx_image_reader_jpeg_one_mcu_rotated_write(GX_JPEG_INFO * jpeg_info,INT xpos,INT ypos,INT h,INT v)2257 static UINT _gx_image_reader_jpeg_one_mcu_rotated_write(GX_JPEG_INFO *jpeg_info, INT xpos, INT ypos, INT h, INT v)
2258 {
2259 GX_UBYTE *put;
2260 INT x;
2261 INT coff;
2262 INT xstart = 0;
2263 INT xend;
2264 INT ystart = 0;
2265 INT yend;
2266 INT stride;
2267
2268 #if defined(GX_ENABLE_ARM_HELIUM)
2269 int8x16_t vY;
2270 int8x16_t vCb;
2271 int8x16_t vCr;
2272 uint8x16_t vred;
2273 uint8x16_t vgreen;
2274 uint8x16_t vblue;
2275 INT size;
2276 GX_UBYTE index;
2277 uint8x16_t yoffset;
2278 uint8x16_t cbcroffset;
2279 #else
2280 GX_BYTE Y;
2281 GX_BYTE Cb;
2282 GX_BYTE Cr;
2283 INT red;
2284 INT green;
2285 INT blue;
2286 INT y;
2287 GX_BYTE sign = 1;
2288 #endif
2289
2290 xend = (h << 3) - 1;
2291 yend = (v << 3) - 1;
2292
2293 if (xpos < jpeg_info -> gx_jpeg_output_clip.gx_rectangle_left)
2294 {
2295 xstart = jpeg_info -> gx_jpeg_output_clip.gx_rectangle_left - xpos;
2296 }
2297
2298 if (xpos + xend > jpeg_info -> gx_jpeg_output_clip.gx_rectangle_right)
2299 {
2300 xend = jpeg_info -> gx_jpeg_output_clip.gx_rectangle_right - xpos;
2301 }
2302
2303 if (xstart > xend)
2304 {
2305 return GX_SUCCESS;
2306 }
2307
2308 if (ypos < jpeg_info -> gx_jpeg_output_clip.gx_rectangle_top)
2309 {
2310 ystart = jpeg_info -> gx_jpeg_output_clip.gx_rectangle_top - ypos;
2311 }
2312
2313 if (ypos + yend > jpeg_info -> gx_jpeg_output_clip.gx_rectangle_bottom)
2314 {
2315 yend = jpeg_info -> gx_jpeg_output_clip.gx_rectangle_bottom - ypos;
2316 }
2317
2318 if (ystart > yend)
2319 {
2320 return GX_SUCCESS;
2321 }
2322
2323 #if defined(GX_ENABLE_ARM_HELIUM)
2324 size = yend - ystart + 1;
2325 #endif
2326
2327 stride = jpeg_info -> gx_jpeg_output_stride;
2328 put = (GX_UBYTE *)jpeg_info -> gx_jpeg_output_buffer;
2329
2330 if (jpeg_info -> gx_jpeg_output_rotation_angle == GX_SCREEN_ROTATION_CW)
2331 {
2332 put += (jpeg_info -> gx_jpeg_output_width - xpos - 1 - xstart) * stride;
2333 put += (ypos + ystart) * jpeg_info -> gx_jpeg_output_bpp;
2334 stride = (-stride);
2335 }
2336 else
2337 {
2338 put += (xpos + xstart) * stride;
2339 put += (jpeg_info -> gx_jpeg_output_height - ypos - 1 - yend) * jpeg_info -> gx_jpeg_output_bpp;
2340
2341 #if defined(GX_ENABLE_ARM_HELIUM)
2342 ystart = (v << 3) - 1 - yend;
2343 #else
2344 GX_SWAP_VALS(ystart, yend);
2345 sign = -1;
2346 #endif
2347 }
2348
2349 #if defined(GX_ENABLE_ARM_HELIUM)
2350 if (jpeg_info -> gx_jpeg_output_rotation_angle == GX_SCREEN_ROTATION_CW)
2351 {
2352 index = (v == 2 ? (1 + (ystart % 2)) : 0);
2353
2354 yoffset = _gx_jpeg_y_offset_rotated_table_cw[h >> 1];
2355 cbcroffset = _gx_jpeg_cbcr_offset_rotated_table_cw[index];
2356 }
2357 else
2358 {
2359 yoffset = _gx_jpeg_y_offset_rotated_table_ccw[h + v - 2];
2360 cbcroffset = _gx_jpeg_cbcr_offset_rotated_table_ccw[v - 1];
2361
2362 if(ystart)
2363 {
2364 for (x = 0; x < 16 - ystart; x++)
2365 {
2366 yoffset[x] = yoffset[ystart + x];
2367 cbcroffset[x] = cbcroffset[ystart + x];
2368 }
2369
2370 ystart = 0;
2371 }
2372 }
2373 #endif
2374
2375 for (x = xstart; x <= xend; x++)
2376 {
2377 jpeg_info -> gx_jpeg_putdata = put;
2378
2379 #if defined(GX_ENABLE_ARM_HELIUM)
2380 coff = x / h + ((ystart / v) << 3);
2381
2382 vY = vldrbq_gather_offset_s8(jpeg_info -> gx_jpeg_Y_block + x + ystart * h * 8, yoffset);
2383 vCb = vldrbq_gather_offset_s8(jpeg_info -> gx_jpeg_Cb_block + coff, cbcroffset);
2384 vCr = vldrbq_gather_offset_s8(jpeg_info -> gx_jpeg_Cr_block + coff, cbcroffset);
2385
2386 /* Convert YCbCr to RGB. */
2387 GX_JPEG_DECODE_YCBCR2RGB_HELIUM(vred, vgreen, vblue, vY, vCb, vCr);
2388
2389 jpeg_info -> gx_jpeg_pixel_write_helium(jpeg_info, vred, vgreen, vblue, size);
2390
2391 #else
2392 for (y = ystart; y != yend + sign; y += sign)
2393 {
2394 coff = x / h + ((y / v) << 3);
2395
2396 Y = jpeg_info -> gx_jpeg_Y_block[x + y * h * 8];
2397 Cb = jpeg_info -> gx_jpeg_Cb_block[coff];
2398 Cr = jpeg_info -> gx_jpeg_Cr_block[coff];
2399
2400 GX_JPEG_DECODE_YCBCR2RGB(red, green, blue, Y, Cb, Cr);
2401
2402 GX_SATURATE_TO_UBYTE(red, red);
2403 GX_SATURATE_TO_UBYTE(green, green);
2404 GX_SATURATE_TO_UBYTE(blue, blue);
2405
2406 jpeg_info -> gx_jpeg_pixel_write(jpeg_info, (GX_UBYTE)red, (GX_UBYTE)green, (GX_UBYTE)blue);
2407 }
2408 #endif
2409 put += stride;
2410 }
2411
2412 return GX_SUCCESS;
2413 }
2414
2415 /**************************************************************************/
2416 /* */
2417 /* FUNCTION RELEASE */
2418 /* */
2419 /* _gx_image_reader_jpeg_decompress PORTABLE C */
2420 /* 6.3.0 */
2421 /* AUTHOR */
2422 /* */
2423 /* Kenneth Maxwell, Microsoft Corporation */
2424 /* */
2425 /* DESCRIPTION */
2426 /* */
2427 /* Decompress JPG data stream. */
2428 /* */
2429 /* INPUT */
2430 /* */
2431 /* jpeg_info JPEG control block */
2432 /* */
2433 /* OUTPUT */
2434 /* */
2435 /* Status Code */
2436 /* */
2437 /* CALLS */
2438 /* */
2439 /* _gx_image_reader_jpeg_one_block_decode */
2440 /* Decode one blcok of jpeg data */
2441 /* _gx_image_reader_jpeg_one_mcu_write Write decoded data to */
2442 /* specified memory */
2443 /* */
2444 /* CALLED BY */
2445 /* */
2446 /* _gx_image_reader_jpeg_decode */
2447 /* */
2448 /* RELEASE HISTORY */
2449 /* */
2450 /* DATE NAME DESCRIPTION */
2451 /* */
2452 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2453 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2454 /* resulting in version 6.1 */
2455 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
2456 /* abort if block decode fails,*/
2457 /* resulting in version 6.2.0 */
2458 /* 10-31-2023 Ting Zhu Modified comment(s), */
2459 /* improved logic, */
2460 /* resulting in version 6.3.0 */
2461 /* */
2462 /**************************************************************************/
_gx_image_reader_jpeg_decompress(GX_JPEG_INFO * jpeg_info)2463 static UINT _gx_image_reader_jpeg_decompress(GX_JPEG_INFO *jpeg_info)
2464 {
2465 int h;
2466 int v;
2467 int x;
2468 int y;
2469 int xx;
2470 int yy;
2471 UINT status = GX_SUCCESS;
2472 UINT (*one_mcu_write)(GX_JPEG_INFO *jpeg_info, INT xpos, INT ypos, INT h, INT v);
2473
2474 h = (jpeg_info -> gx_jpeg_sample_factor[0] >> 4);
2475 v = (jpeg_info -> gx_jpeg_sample_factor[0] & 0x0f);
2476
2477 if (v > 2)
2478 {
2479 return GX_INVALID_FORMAT;
2480 }
2481
2482 status = _gx_image_reader_jpeg_pixel_write_info_set(jpeg_info);
2483
2484 if ((jpeg_info -> gx_jpeg_output_rotation_angle != 0) &&
2485 (jpeg_info -> gx_jpeg_output_color_format != GX_IMAGE_FORMAT_24BPP))
2486 {
2487 one_mcu_write = _gx_image_reader_jpeg_one_mcu_rotated_write;
2488 }
2489 else
2490 {
2491 one_mcu_write = _gx_image_reader_jpeg_one_mcu_write;
2492 }
2493
2494 for (y = 0; y < jpeg_info -> gx_jpeg_height; y += 8 * v)
2495 {
2496 for (x = 0; x < jpeg_info -> gx_jpeg_width; x += 8 * h)
2497 {
2498 /* Decode one MCU */
2499 for (yy = 0; yy < v && status == GX_SUCCESS; yy++)
2500 {
2501 for (xx = 0; xx < h && status == GX_SUCCESS; xx++)
2502 {
2503 /* Y */
2504 status = _gx_image_reader_jpeg_one_block_decode(jpeg_info, 0, jpeg_info -> gx_jpeg_Y_block + yy * 128 + xx * 8);
2505 }
2506 }
2507
2508 if (status == GX_SUCCESS && jpeg_info -> gx_jpeg_num_of_components > 1)
2509 {
2510 /* Cb */
2511 status = _gx_image_reader_jpeg_one_block_decode(jpeg_info, 1, jpeg_info -> gx_jpeg_Cb_block);
2512
2513 /* Cr */
2514 if (status == GX_SUCCESS)
2515 {
2516 status = _gx_image_reader_jpeg_one_block_decode(jpeg_info, 2, jpeg_info -> gx_jpeg_Cr_block);
2517 }
2518 }
2519
2520 if (status == GX_SUCCESS)
2521 {
2522 one_mcu_write(jpeg_info, jpeg_info -> gx_jpeg_output_xpos + x, jpeg_info -> gx_jpeg_output_ypos + y, h, v);
2523 }
2524 }
2525 }
2526
2527 return status;
2528 }
2529
2530 /**************************************************************************/
2531 /* */
2532 /* FUNCTION RELEASE */
2533 /* */
2534 /* _gx_image_reader_jpeg_decode_blocks PORTABLE C */
2535 /* 6.3.0 */
2536 /* AUTHOR */
2537 /* */
2538 /* Kenneth Maxwell, Microsoft Corporation */
2539 /* */
2540 /* DESCRIPTION */
2541 /* */
2542 /* This function decode a jpg format image. */
2543 /* */
2544 /* INPUT */
2545 /* */
2546 /* jpeg_info Jpeg decode control block */
2547 /* */
2548 /* OUTPUT */
2549 /* */
2550 /* status Completion status */
2551 /* */
2552 /* CALLS */
2553 /* */
2554 /* _gx_image_reader_jpeg_quantization_table_set */
2555 /* Set jpeg quantization table */
2556 /* _gx_image_reader_jpeg_frame_header_read */
2557 /* Read frame header information */
2558 /* _gx_image_reader_huffman_table_set Set up huffman table */
2559 /* _gx_image_reader_jpeg_scan_header_read */
2560 /* Read scan header information */
2561 /* _gx_image_reader_jpeg_decompress Decompress jped data stream */
2562 /* _gx_system_memory_free Application defined memory */
2563 /* free function */
2564 /* */
2565 /* CALLED BY */
2566 /* */
2567 /* _gx_image_reader_jpeg_decode */
2568 /* _gx_image_reader_jpeg_mcu_decode */
2569 /* */
2570 /* RELEASE HISTORY */
2571 /* */
2572 /* DATE NAME DESCRIPTION */
2573 /* */
2574 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2575 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2576 /* resulting in version 6.1 */
2577 /* 10-31-2023 Ting Zhu Modified comment(s), removed */
2578 /* huffman table free logic, */
2579 /* resulting in version 6.3.0 */
2580 /* */
2581 /**************************************************************************/
_gx_image_reader_jpeg_decode_blocks(GX_JPEG_INFO * jpeg_info)2582 static UINT _gx_image_reader_jpeg_decode_blocks(GX_JPEG_INFO *jpeg_info)
2583 {
2584 GX_UBYTE *jpeg_data;
2585 GX_UBYTE marker;
2586 UINT segment_len;
2587 UINT status = GX_SUCCESS;
2588
2589 if (jpeg_info -> gx_jpeg_data == GX_NULL || jpeg_info -> gx_jpeg_data_size < 10)
2590 {
2591 return GX_INVALID_VALUE;
2592 }
2593
2594 jpeg_data = jpeg_info -> gx_jpeg_data;
2595
2596 /* Read JPEG File flag that mark the start of a JPEG image. */
2597 if ((*jpeg_data++ != 0xff) || (*jpeg_data++ != 0xd8))
2598 {
2599 return GX_INVALID_FORMAT; /*Not a jpeg file */
2600 }
2601
2602 jpeg_info -> gx_jpeg_data_index += 2;
2603
2604 while ((jpeg_info -> gx_jpeg_data_index + 3 < jpeg_info -> gx_jpeg_data_size) &&
2605 (status == GX_SUCCESS))
2606 {
2607 jpeg_data = (jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index);
2608 marker = *(jpeg_data + 1);
2609
2610 if ((*jpeg_data == 0xff) && (marker != 0) && (marker != 0xff))
2611 {
2612 jpeg_data += 2;
2613 jpeg_info -> gx_jpeg_data_index += 2;
2614
2615 /* Read WORD length */
2616 segment_len = *(jpeg_data);
2617 segment_len <<= 8;
2618 segment_len |= *(jpeg_data + 1);
2619
2620 if ((UINT)jpeg_info -> gx_jpeg_data_index + segment_len > (UINT)jpeg_info -> gx_jpeg_data_size)
2621 {
2622 /* Invalid data size. */
2623 status = GX_FAILURE;
2624 break;
2625 }
2626
2627 switch (marker)
2628 {
2629 case 0xdb:
2630 /* Define Quantization Table */
2631 status = _gx_image_reader_jpeg_quantization_table_set(jpeg_info, segment_len);
2632 break;
2633
2634 case 0xc0:
2635 /* Start of Frame */
2636 status = _gx_image_reader_jpeg_frame_header_read(jpeg_info, segment_len);
2637 break;
2638
2639 case 0xc4:
2640 /* Define Huffman Table */
2641 status = _gx_image_reader_huffman_table_set(jpeg_info, segment_len);
2642 break;
2643
2644 case 0xdd:
2645 /* Read restart interval which specifies the number of MCU in restart interval. */
2646 jpeg_data += 2;
2647 jpeg_info -> gx_jpeg_restart_interval = *jpeg_data++;
2648 jpeg_info -> gx_jpeg_restart_interval <<= 8;
2649 jpeg_info -> gx_jpeg_restart_interval |= *jpeg_data++;
2650 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
2651 break;
2652
2653 case 0xda:
2654 /* Start of Scan, stores which Huffman tables are associated with which components
2655 The program start decoding the data section directly after it reads in this header. */
2656 _gx_image_reader_jpeg_scan_header_read(jpeg_info, segment_len);
2657
2658 /* Start decoding jpeg data stream. */
2659 status = _gx_image_reader_jpeg_decompress(jpeg_info);
2660 break;
2661
2662 default:
2663 /* Unkown marker, skip */
2664 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
2665 break;
2666 }
2667 }
2668 else
2669 {
2670 jpeg_info -> gx_jpeg_data_index++;
2671 }
2672 }
2673
2674 return status;
2675 }
2676
2677 /**************************************************************************/
2678 /* */
2679 /* FUNCTION RELEASE */
2680 /* */
2681 /* _gx_image_reader_jpeg_decode PORTABLE C */
2682 /* 6.3.0 */
2683 /* AUTHOR */
2684 /* */
2685 /* Kenneth Maxwell, Microsoft Corporation */
2686 /* */
2687 /* DESCRIPTION */
2688 /* */
2689 /* This function decodes a jpg format image and saves the decoded data */
2690 /* to a GX_PIXELMAP structure. */
2691 /* */
2692 /* INPUT */
2693 /* */
2694 /* read_data Input JPEG data stream */
2695 /* data_size JPEG size in bytes */
2696 /* outmap Output pixelmap */
2697 /* */
2698 /* OUTPUT */
2699 /* */
2700 /* status Completion status */
2701 /* */
2702 /* CALLS */
2703 /* */
2704 /* _gx_image_reader_jpeg_decode_blocks Decode a jpeg format image */
2705 /* */
2706 /* CALLED BY */
2707 /* */
2708 /* _gx_image_reader_image_decode */
2709 /* */
2710 /* RELEASE HISTORY */
2711 /* */
2712 /* DATE NAME DESCRIPTION */
2713 /* */
2714 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2715 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2716 /* resulting in version 6.1 */
2717 /* 10-31-2023 Ting Zhu Modified comment(s), */
2718 /* improved logic, */
2719 /* resulting in version 6.3.0 */
2720 /* */
2721 /**************************************************************************/
_gx_image_reader_jpeg_decode(GX_IMAGE_READER * image_reader,GX_PIXELMAP * outmap)2722 UINT _gx_image_reader_jpeg_decode(GX_IMAGE_READER *image_reader, GX_PIXELMAP *outmap)
2723 {
2724 UINT status;
2725 GX_JPEG_INFO *jpeg_info;
2726
2727
2728 if ((!_gx_system_memory_allocator) || (!_gx_system_memory_free))
2729 {
2730 return GX_SYSTEM_MEMORY_ERROR;
2731 }
2732
2733 jpeg_info = (GX_JPEG_INFO *)_gx_system_memory_allocator(sizeof(GX_JPEG_INFO));
2734
2735 if (!jpeg_info)
2736 {
2737 return GX_SYSTEM_MEMORY_ERROR;
2738 }
2739
2740 memset(jpeg_info, 0, sizeof(GX_JPEG_INFO));
2741
2742
2743 jpeg_info -> gx_jpeg_data = (GX_UBYTE *)image_reader -> gx_image_reader_source_data;
2744 jpeg_info -> gx_jpeg_data_size = (INT)image_reader -> gx_image_reader_source_data_size;
2745 jpeg_info -> gx_jpeg_data_index = 0;
2746
2747 if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_DITHER)
2748 {
2749 jpeg_info -> gx_jpeg_output_color_format = GX_IMAGE_FORMAT_24BPP;
2750 }
2751 else
2752 {
2753 jpeg_info -> gx_jpeg_output_color_format = image_reader -> gx_image_reader_color_format;
2754 }
2755
2756 if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_ROTATE_CW)
2757 {
2758 jpeg_info -> gx_jpeg_output_rotation_angle = GX_SCREEN_ROTATION_CW;
2759 }
2760 else if (image_reader -> gx_image_reader_mode & GX_IMAGE_READER_MODE_ROTATE_CCW)
2761 {
2762 jpeg_info -> gx_jpeg_output_rotation_angle = GX_SCREEN_ROTATION_CCW;
2763 }
2764
2765 status = _gx_image_reader_jpeg_decode_blocks(jpeg_info);
2766
2767 if (status == GX_SUCCESS)
2768 {
2769 outmap -> gx_pixelmap_data = jpeg_info -> gx_jpeg_output_buffer;
2770 outmap -> gx_pixelmap_data_size = (ULONG)(jpeg_info -> gx_jpeg_output_stride * jpeg_info -> gx_jpeg_height);
2771 outmap -> gx_pixelmap_width = (GX_VALUE)jpeg_info -> gx_jpeg_width;
2772 outmap -> gx_pixelmap_height = (GX_VALUE)jpeg_info -> gx_jpeg_height;
2773 outmap -> gx_pixelmap_flags = 0;
2774 outmap -> gx_pixelmap_format = jpeg_info -> gx_jpeg_output_color_format;
2775 }
2776
2777 _gx_system_memory_free((void *)jpeg_info);
2778
2779 return status;
2780 }
2781
2782 /**************************************************************************/
2783 /* */
2784 /* FUNCTION RELEASE */
2785 /* */
2786 /* _gx_image_reader_jpeg_mcu_decode PORTABLE C */
2787 /* 6.3.0 */
2788 /* AUTHOR */
2789 /* */
2790 /* Kenneth Maxwell, Microsoft Corporation */
2791 /* */
2792 /* DESCRIPTION */
2793 /* */
2794 /* This function decodes a jpg format image and draw it to canvas */
2795 /* directly. */
2796 /* */
2797 /* INPUT */
2798 /* */
2799 /* read_data Input JPEG data */
2800 /* data_size JPEG size in bytes */
2801 /* context Drawing contex */
2802 /* xpos X-coord of draw start point in*/
2803 /* canvas */
2804 /* ypos Y-coord of draw start point in*/
2805 /* canvas */
2806 /* */
2807 /* OUTPUT */
2808 /* */
2809 /* status Completion status */
2810 /* */
2811 /* CALLS */
2812 /* */
2813 /* _gx_image_reader_jpeg_decode_blocks Decode a jpeg format image */
2814 /* */
2815 /* CALLED BY */
2816 /* */
2817 /* GUIX Internal Code */
2818 /* */
2819 /* RELEASE HISTORY */
2820 /* */
2821 /* DATE NAME DESCRIPTION */
2822 /* */
2823 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2824 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2825 /* resulting in version 6.1 */
2826 /* 10-31-2023 Ting Zhu Modified comment(s), */
2827 /* improved logic, */
2828 /* resulting in version 6.3.0 */
2829 /* */
2830 /**************************************************************************/
_gx_image_reader_jpeg_mcu_decode(GX_CONST GX_UBYTE * read_data,ULONG data_size,GX_DRAW_CONTEXT * context,INT xpos,INT ypos)2831 UINT _gx_image_reader_jpeg_mcu_decode(GX_CONST GX_UBYTE *read_data, ULONG data_size,
2832 GX_DRAW_CONTEXT *context, INT xpos, INT ypos)
2833 {
2834 UINT status;
2835 GX_JPEG_INFO *jpeg_info;
2836
2837 if ((!_gx_system_memory_allocator) || (!_gx_system_memory_free))
2838 {
2839 return GX_SYSTEM_MEMORY_ERROR;
2840 }
2841
2842 jpeg_info = (GX_JPEG_INFO *)_gx_system_memory_allocator(sizeof(GX_JPEG_INFO));
2843
2844 if (!jpeg_info)
2845 {
2846 return GX_SYSTEM_MEMORY_ERROR;
2847 }
2848
2849 if (!context)
2850 {
2851 return GX_INVALID_CONTEXT;
2852 }
2853
2854 memset(jpeg_info, 0, sizeof(GX_JPEG_INFO));
2855
2856 jpeg_info -> gx_jpeg_data = (GX_UBYTE *)read_data;
2857 jpeg_info -> gx_jpeg_data_size = (INT)data_size;
2858 jpeg_info -> gx_jpeg_data_index = 0;
2859 jpeg_info -> gx_jpeg_output_xpos = xpos;
2860 jpeg_info -> gx_jpeg_output_ypos = ypos;
2861 jpeg_info -> gx_jpeg_output_color_format = context -> gx_draw_context_display -> gx_display_color_format;
2862 jpeg_info -> gx_jpeg_output_rotation_angle = context -> gx_draw_context_display -> gx_display_rotation_angle;
2863 jpeg_info -> gx_jpeg_output_buffer = (GX_UBYTE *)context -> gx_draw_context_memory;
2864 #ifdef GX_ENABLE_CANVAS_PARTIAL_FRAME_BUFFER
2865 jpeg_info -> gx_jpeg_output_width = (USHORT)context -> gx_draw_context_canvas -> gx_canvas_memory_width;
2866 jpeg_info -> gx_jpeg_output_height = (USHORT)context -> gx_draw_context_canvas -> gx_canvas_memory_height;
2867 jpeg_info -> gx_jpeg_output_buffer_offset_x = context -> gx_draw_context_offset_x;
2868 jpeg_info -> gx_jpeg_output_buffer_offset_y = context -> gx_draw_context_offset_y;
2869 #else
2870 jpeg_info -> gx_jpeg_output_width = (USHORT)context -> gx_draw_context_canvas -> gx_canvas_x_resolution;
2871 jpeg_info -> gx_jpeg_output_height = (USHORT)context -> gx_draw_context_canvas -> gx_canvas_y_resolution;
2872 #endif
2873 jpeg_info -> gx_jpeg_output_clip = *context -> gx_draw_context_clip;
2874
2875
2876 status = _gx_image_reader_jpeg_decode_blocks(jpeg_info);
2877
2878 _gx_system_memory_free((void *)jpeg_info);
2879
2880 return status;
2881 }
2882 #endif
2883
2884