1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** GUIX Component */
17 /** */
18 /** Utility Management (Utility) */
19 /** */
20 /**************************************************************************/
21
22 #define GX_SOURCE_CODE
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_context.h"
28 #include "gx_system.h"
29 #include "gx_utility.h"
30 #include "gx_image_reader.h"
31
32 #if defined(GX_SOFTWARE_DECODER_SUPPORT)
33
34 static UINT _gx_jpg_bit_buffer;
35 static UINT _gx_jpg_bit_count;
36
37 static GX_CONST GX_UBYTE _gx_jpg_reorder_index[] =
38 {
39 0, 1, 8, 16, 9, 2, 3, 10,
40 17, 24, 32, 25, 18, 11, 4, 5,
41 12, 19, 26, 33, 40, 48, 41, 34,
42 27, 20, 13, 6, 7, 14, 21, 28,
43 35, 42, 49, 56, 57, 50, 43, 36,
44 29, 22, 15, 23, 30, 37, 44, 51,
45 58, 59, 52, 45, 38, 31, 39, 46,
46 53, 60, 61, 54, 47, 55, 62, 63
47 };
48
49 /**************************************************************************/
50 /* */
51 /* FUNCTION RELEASE */
52 /* */
53 /* _gx_image_reader_jpeg_bits_get PORTABLE C */
54 /* 6.1 */
55 /* AUTHOR */
56 /* */
57 /* Kenneth Maxwell, Microsoft Corporation */
58 /* */
59 /* DESCRIPTION */
60 /* */
61 /* Extract a specified number of bits from JPEG data stream and */
62 /* advance the read pointer of the JPEG data stream. */
63 /* */
64 /* INPUT */
65 /* */
66 /* jpeg_info JPEG data context */
67 /* num_of_bits Number of bits to extract */
68 /* return_value Extracted data. */
69 /* */
70 /* OUTPUT */
71 /* */
72 /* None */
73 /* */
74 /* CALLS */
75 /* */
76 /* None */
77 /* */
78 /* CALLED BY */
79 /* */
80 /* _gx_image_reader_jpeg_dc_decode */
81 /* _gx_image_reader_jpeg_ac_decode */
82 /* */
83 /* RELEASE HISTORY */
84 /* */
85 /* DATE NAME DESCRIPTION */
86 /* */
87 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
88 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
89 /* resulting in version 6.1 */
90 /* */
91 /**************************************************************************/
_gx_image_reader_jpeg_bits_get(GX_JPEG_INFO * jpeg_info,UINT num_of_bits,UINT * return_value)92 static void _gx_image_reader_jpeg_bits_get(GX_JPEG_INFO *jpeg_info, UINT num_of_bits, UINT *return_value)
93 {
94 INT index = jpeg_info -> gx_jpeg_data_index;
95
96 while (_gx_jpg_bit_count <= num_of_bits)
97 {
98 if ((index < jpeg_info -> gx_jpeg_data_size) && (_gx_jpg_bit_count <= 24))
99 {
100 _gx_jpg_bit_buffer |= ((UINT)(jpeg_info -> gx_jpeg_data[index]) << (UINT)(24 - _gx_jpg_bit_count));
101
102 if ((jpeg_info -> gx_jpeg_data[index] == 0xff) &&
103 (index + 1 < jpeg_info -> gx_jpeg_data_size) &&
104 (jpeg_info -> gx_jpeg_data[index + 1] == 0x00))
105 {
106 index += 2;
107 }
108 else
109 {
110 index += 1;
111 }
112 }
113
114 _gx_jpg_bit_count += 8;
115 }
116
117 jpeg_info -> gx_jpeg_data_index = index;
118
119 (*return_value) = (UINT)_gx_jpg_bit_buffer;
120 }
121
122 /**************************************************************************/
123 /* */
124 /* FUNCTION RELEASE */
125 /* */
126 /* _gx_image_reader_jpeg_bits_skip PORTABLE C */
127 /* 6.1 */
128 /* AUTHOR */
129 /* */
130 /* Kenneth Maxwell, Microsoft Corporation */
131 /* */
132 /* DESCRIPTION */
133 /* */
134 /* Skips bits from tempory JPEG data stream. */
135 /* */
136 /* INPUT */
137 /* */
138 /* skip_bits Number of bits to skip */
139 /* */
140 /* OUTPUT */
141 /* */
142 /* None */
143 /* */
144 /* CALLS */
145 /* */
146 /* None */
147 /* */
148 /* CALLED BY */
149 /* */
150 /* _gx_image_reader_jpeg_dc_decode */
151 /* _gx_image_reader_jpeg_ac_decode */
152 /* */
153 /* RELEASE HISTORY */
154 /* */
155 /* DATE NAME DESCRIPTION */
156 /* */
157 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
158 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
159 /* resulting in version 6.1 */
160 /* */
161 /**************************************************************************/
_gx_image_reader_jpeg_bits_skip(UINT skip_bits)162 static void _gx_image_reader_jpeg_bits_skip(UINT skip_bits)
163 {
164 _gx_jpg_bit_buffer <<= skip_bits;
165
166 _gx_jpg_bit_count -= skip_bits;
167 }
168
169 /**************************************************************************/
170 /* */
171 /* FUNCTION RELEASE */
172 /* */
173 /* _gx_image_reader_jpeg_range PORTABLE C */
174 /* 6.1 */
175 /* AUTHOR */
176 /* */
177 /* Kenneth Maxwell, Microsoft Corporation */
178 /* */
179 /* DESCRIPTION */
180 /* */
181 /* Limit the value to be in the range of [0, 255] */
182 /* */
183 /* INPUT */
184 /* */
185 /* value Value to be checked */
186 /* */
187 /* OUTPUT */
188 /* */
189 /* GX_UBYTE Output value. */
190 /* */
191 /* CALLS */
192 /* */
193 /* None */
194 /* */
195 /* CALLED BY */
196 /* */
197 /* _gx_image_reader_jpeg_dequantize_idct */
198 /* */
199 /* RELEASE HISTORY */
200 /* */
201 /* DATE NAME DESCRIPTION */
202 /* */
203 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
204 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
205 /* resulting in version 6.1 */
206 /* */
207 /**************************************************************************/
_gx_image_reader_jpeg_range(INT i)208 static GX_UBYTE _gx_image_reader_jpeg_range(INT i)
209 {
210 if (i < 0)
211 {
212 return 0;
213 }
214 else if (i > 255)
215 {
216 return 255;
217 }
218 else
219 {
220 return((GX_UBYTE)i);
221 }
222 }
223
224 /**************************************************************************/
225 /* */
226 /* FUNCTION RELEASE */
227 /* */
228 /* _gx_image_reader_jpeg_YCbCr2RGB_888 PORTABLE C */
229 /* 6.1 */
230 /* AUTHOR */
231 /* */
232 /* Kenneth Maxwell, Microsoft Corporation */
233 /* */
234 /* DESCRIPTION */
235 /* */
236 /* Converts YCbCr value to 888RGB color space and write it to memory. */
237 /* */
238 /* INPUT */
239 /* */
240 /* y Luminance */
241 /* cb Chroma (Blue-difference) */
242 /* cr Chroma (Red-difference) */
243 /* put Retrieved 888RGB color */
244 /* */
245 /* OUTPUT */
246 /* */
247 /* Value 565 RGB value */
248 /* */
249 /* CALLS */
250 /* */
251 /* _gx_image_reader_jpeg_range Limit value in range [0, 255] */
252 /* */
253 /* CALLED BY */
254 /* */
255 /* _gx_image_reader_jpeg_one_mcu_write */
256 /* */
257 /* RELEASE HISTORY */
258 /* */
259 /* DATE NAME DESCRIPTION */
260 /* */
261 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
262 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
263 /* resulting in version 6.1 */
264 /* */
265 /**************************************************************************/
_gx_image_reader_jpeg_YCbCr2RGB_888(INT y,INT cb,INT cr,GX_UBYTE * put)266 static GX_COLOR _gx_image_reader_jpeg_YCbCr2RGB_888(INT y, INT cb, INT cr, GX_UBYTE *put)
267 {
268 INT temp_r;
269 INT temp_g;
270 INT temp_b;
271 GX_UBYTE r;
272 GX_UBYTE g;
273 GX_UBYTE b;
274
275
276 cb -= 128;
277 cr -= 128;
278
279 temp_r = y + cr + (cr >> 2) + (cr >> 3);
280 temp_g = y - ((cb >> 2) + (cb >> 4) + (cb >> 5)) - ((cr >> 1) + (cr >> 3) + (cr >> 4) + (cr >> 6));
281 temp_b = y + cb + (cb >> 1) + (cb >> 2);
282
283
284 /* Make sure the range of the RGB values are within bound. */
285 r = _gx_image_reader_jpeg_range(temp_r);
286 g = _gx_image_reader_jpeg_range(temp_g);
287 b = _gx_image_reader_jpeg_range(temp_b);
288
289 *put = r;
290 *(put + 1) = g;
291 *(put + 2) = b;
292
293 return 0;
294 }
295
296 /**************************************************************************/
297 /* */
298 /* FUNCTION RELEASE */
299 /* */
300 /* _gx_dislay_driver_jpeg_quantization_table_set PORTABLE C */
301 /* 6.2.0 */
302 /* AUTHOR */
303 /* */
304 /* Kenneth Maxwell, Microsoft Corporation */
305 /* */
306 /* DESCRIPTION */
307 /* */
308 /* Sets the JPEG quantization table. */
309 /* */
310 /* INPUT */
311 /* */
312 /* jpeg_info JPEG data control block */
313 /* segment_len Initial length of the segment */
314 /* */
315 /* OUTPUT */
316 /* */
317 /* None */
318 /* */
319 /* CALLS */
320 /* */
321 /* None */
322 /* */
323 /* CALLED BY */
324 /* */
325 /* _gx_image_reader_jpeg_decode */
326 /* */
327 /* RELEASE HISTORY */
328 /* */
329 /* DATE NAME DESCRIPTION */
330 /* */
331 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
332 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
333 /* resulting in version 6.1 */
334 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
335 /* prevented underflow from */
336 /* bad input data, */
337 /* resulting in version 6.2.0 */
338 /* */
339 /**************************************************************************/
_gx_image_reader_jpeg_quantization_table_set(GX_JPEG_INFO * jpeg_info,UINT segment_len)340 static UINT _gx_image_reader_jpeg_quantization_table_set(GX_JPEG_INFO *jpeg_info, UINT segment_len)
341 {
342 GX_UBYTE table_index;
343 GX_UBYTE *jpeg_data = jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index;
344 INT index;
345
346 /* Minus two-byte length. */
347 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
348 segment_len -= 2;
349 jpeg_data += 2;
350
351 while (segment_len)
352 {
353 /* The upper 4 bits specify the element precision: 0 indicates 8-bit, 1 indecates 16-bit. */
354 if ((*jpeg_data) & 0xf0)
355 {
356 /* Baseline DCT-based jpeg only support 8-bit precision. */
357 return GX_NOT_SUPPORTED;
358 }
359
360 /* The lower 4 bits specify the table destination identifier, specify one of four possible destinations. */
361 table_index = (*jpeg_data++) & 0x03;
362
363 /* Read quantization table element. */
364 for (index = 0; index < 64; index++)
365 {
366 jpeg_info -> gx_jpeg_quantization_table[table_index][index] = *jpeg_data++;
367 }
368
369 if (segment_len < 65)
370 {
371 return GX_INVALID_FORMAT;
372 }
373 segment_len -= 65;
374 }
375
376 return GX_SUCCESS;
377 }
378
379 /**************************************************************************/
380 /* */
381 /* FUNCTION RELEASE */
382 /* */
383 /* _gx_image_reader_jpeg_huffcode_find PORTABLE C */
384 /* 6.2.0 */
385 /* AUTHOR */
386 /* */
387 /* Kenneth Maxwell, Microsoft Corporation */
388 /* */
389 /* DESCRIPTION */
390 /* */
391 /* Lookup the huffman code. */
392 /* */
393 /* INPUT */
394 /* */
395 /* jpeg_info JPEG data control block */
396 /* table_class Table class, 0 = DC table, */
397 /* 1 = AC table */
398 /* table_id Table index */
399 /* scan_buffer Buffer to search from */
400 /* bit_len Retrieved Huffman Code Length */
401 /* code_value Retrieved Huffman Code */
402 /* */
403 /* OUTPUT */
404 /* */
405 /* Status Code */
406 /* */
407 /* CALLS */
408 /* */
409 /* None */
410 /* */
411 /* CALLED BY */
412 /* */
413 /* _gx_image_reader_jpeg_dc_decode */
414 /* _gx_image_reader_jpeg_ac_decode */
415 /* */
416 /* RELEASE HISTORY */
417 /* */
418 /* DATE NAME DESCRIPTION */
419 /* */
420 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
421 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
422 /* resulting in version 6.1 */
423 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
424 /* changed bit_count to */
425 /* GX_VALUE data type */
426 /* resulting in version 6.2.0 */
427 /* */
428 /**************************************************************************/
_gx_image_reader_jpeg_huffcode_find(GX_JPEG_INFO * jpeg_info,UINT table_class,UINT table_id,UINT scan_buffer,UINT * bit_len,GX_UBYTE * code_value)429 static UINT _gx_image_reader_jpeg_huffcode_find(GX_JPEG_INFO *jpeg_info,
430 UINT table_class,
431 UINT table_id,
432 UINT scan_buffer,
433 UINT *bit_len,
434 GX_UBYTE *code_value)
435 {
436 UINT i_bit;
437 GX_VALUE bit_count;
438 INT code;
439 INT code_cal = 0;
440 INT code_index = 0;
441
442 for (i_bit = 0; i_bit < 16; i_bit++)
443 {
444 bit_count = (GX_VALUE)(jpeg_info -> gx_jpeg_huffman_bits_count[table_class][table_id][i_bit]);
445
446 if (bit_count)
447 {
448 code = (INT) ((scan_buffer) >> (31 - i_bit));
449
450 if (code <= code_cal + bit_count - 1)
451 {
452 *bit_len = i_bit + 1;
453 *code_value = (GX_UBYTE)jpeg_info -> gx_jpeg_huffman_table[table_class][table_id][code_index + code - code_cal];
454 return GX_SUCCESS;
455 }
456 else
457 {
458 code_index += bit_count;
459 code_cal += bit_count;
460 }
461 }
462
463 code_cal <<= 1;
464 }
465
466 return GX_FAILURE;
467 }
468
469 /**************************************************************************/
470 /* */
471 /* FUNCTION RELEASE */
472 /* */
473 /* _gx_image_reader_huffman_table_set PORTABLE C */
474 /* 6.2.0 */
475 /* AUTHOR */
476 /* */
477 /* Kenneth Maxwell, Microsoft Corporation */
478 /* */
479 /* DESCRIPTION */
480 /* */
481 /* Sets up the huffman table. */
482 /* */
483 /* INPUT */
484 /* */
485 /* jpeg_info JPEG data control block */
486 /* segment_len Initial length of the segment */
487 /* */
488 /* OUTPUT */
489 /* */
490 /* None */
491 /* */
492 /* CALLS */
493 /* */
494 /* None */
495 /* */
496 /* CALLED BY */
497 /* */
498 /* _gx_image_reader_jpeg_decode_blocks */
499 /* */
500 /* RELEASE HISTORY */
501 /* */
502 /* DATE NAME DESCRIPTION */
503 /* */
504 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
505 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
506 /* resulting in version 6.1 */
507 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
508 /* added range test to prevent */
509 /* underflow, */
510 /* resulting in version 6.2.0 */
511 /* */
512 /**************************************************************************/
_gx_image_reader_huffman_table_set(GX_JPEG_INFO * jpeg_info,UINT segment_len)513 static UINT _gx_image_reader_huffman_table_set(GX_JPEG_INFO *jpeg_info, UINT segment_len)
514 {
515 GX_UBYTE *jpeg_data = jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index;
516 GX_UBYTE table_class;
517 GX_UBYTE table_id;
518 GX_UBYTE bit_count;
519 UINT code_index;
520 UINT i_bits;
521 UINT i_counts;
522 USHORT i_table_size;
523
524 /* must have at least one code for each of 16 huffman bit lengths */
525 if (segment_len < 19)
526 {
527 return GX_INVALID_FORMAT;
528 }
529
530 /* Minus two-byte length. */
531 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
532 segment_len -= 2;
533 jpeg_data += 2;
534
535 while (segment_len)
536 {
537 /* table_calss: 0 DC 1 AC */
538 table_class = ((*jpeg_data) >> 4) & 1;
539 table_id = (*jpeg_data++) & 0x01;
540
541 if (segment_len < 17)
542 {
543 return GX_INVALID_FORMAT;
544 }
545 segment_len -= 17;
546
547 i_table_size = 0;
548 code_index = 0;
549
550 /* Read the number of Huffman codes for each bit length, from 1 to 16. */
551 for (i_bits = 0; i_bits < 16; i_bits++)
552 {
553 bit_count = *jpeg_data++;
554
555 if (segment_len < bit_count)
556 {
557 return GX_INVALID_FORMAT;
558 }
559 jpeg_info -> gx_jpeg_huffman_bits_count[table_class][table_id][i_bits] = bit_count;
560 segment_len -= bit_count;
561 i_table_size = (USHORT)(i_table_size + bit_count);
562 }
563
564 /* The max i_table_size is 16 * 255, overflow cannot occur. */
565 jpeg_info -> gx_jpeg_huffman_table[table_class][table_id] = (INT *)_gx_system_memory_allocator(i_table_size * sizeof(INT));
566
567 if (jpeg_info -> gx_jpeg_huffman_table[table_class][table_id] == GX_NULL)
568 {
569 return GX_SYSTEM_MEMORY_ERROR;
570 }
571
572 /* Read the bytes that the Huffman codes represent, and generate Huffman tree that
573 map a Huffman code to a represent value. */
574 for (i_bits = 0; i_bits < 16; i_bits++)
575 {
576 for (i_counts = 0; i_counts < (UINT)jpeg_info -> gx_jpeg_huffman_bits_count[table_class][table_id][i_bits]; i_counts++)
577 {
578 /* Read byte values the Huffman code represents. */
579 jpeg_info -> gx_jpeg_huffman_table[table_class][table_id][code_index++] = (*jpeg_data++);
580 }
581 }
582 }
583
584 return GX_SUCCESS;
585 }
586
587 /**************************************************************************/
588 /* */
589 /* FUNCTION RELEASE */
590 /* */
591 /* _gx_display_driver_jpeg_frame_header_read PORTABLE C */
592 /* 6.1 */
593 /* AUTHOR */
594 /* */
595 /* Kenneth Maxwell, Microsoft Corporation */
596 /* */
597 /* DESCRIPTION */
598 /* */
599 /* Reads in the frame header infomration. */
600 /* */
601 /* INPUT */
602 /* */
603 /* jpeg_info JPEG data control block */
604 /* segment_len Initial length of the segment */
605 /* */
606 /* OUTPUT */
607 /* */
608 /* None */
609 /* */
610 /* CALLS */
611 /* */
612 /* None */
613 /* */
614 /* CALLED BY */
615 /* */
616 /* _gx_image_reader_jpeg_decode_blocks */
617 /* */
618 /* RELEASE HISTORY */
619 /* */
620 /* DATE NAME DESCRIPTION */
621 /* */
622 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
623 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
624 /* resulting in version 6.1 */
625 /* */
626 /**************************************************************************/
_gx_image_reader_jpeg_frame_header_read(GX_JPEG_INFO * jpeg_info,UINT segment_len)627 static UINT _gx_image_reader_jpeg_frame_header_read(GX_JPEG_INFO *jpeg_info, UINT segment_len)
628 {
629 GX_UBYTE *jpeg_data = jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index;
630 INT i_component;
631
632 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
633 jpeg_data += 2;
634
635 /* Skip precision field. */
636 jpeg_data++;
637
638 /* Read image width, WORD */
639 jpeg_info -> gx_jpeg_height = *jpeg_data++;
640 jpeg_info -> gx_jpeg_height = (USHORT)(jpeg_info -> gx_jpeg_height << 8);
641 jpeg_info -> gx_jpeg_height = (USHORT)(jpeg_info -> gx_jpeg_height | (*jpeg_data++));
642
643 /* Limit max jpeg height to 14 bits. */
644 if (jpeg_info -> gx_jpeg_height > GX_MAX_PIXELMAP_RESOLUTION)
645 {
646 return GX_INVALID_HEIGHT;
647 }
648
649 /* Read image height, WORD */
650 jpeg_info -> gx_jpeg_width = *jpeg_data++;
651 jpeg_info -> gx_jpeg_width = (USHORT)(jpeg_info -> gx_jpeg_width << 8);
652 jpeg_info -> gx_jpeg_width = (USHORT)(jpeg_info -> gx_jpeg_width | (*jpeg_data++));
653
654 /* Limit max jpeg width to 14 bits. */
655 if (jpeg_info -> gx_jpeg_width > GX_MAX_PIXELMAP_RESOLUTION)
656 {
657 return GX_INVALID_WIDTH;
658 }
659
660 /* Read image components. */
661 jpeg_info -> gx_jpeg_num_of_components = *jpeg_data++;
662
663 if (jpeg_info -> gx_jpeg_num_of_components > JPG_MAX_COMPONENTS)
664 {
665 return GX_FAILURE;
666 }
667
668 for (i_component = 0; i_component < jpeg_info -> gx_jpeg_num_of_components; i_component++)
669 {
670 /* Read component id */
671 jpeg_info -> gx_jpeg_component_id[i_component] = *jpeg_data++;
672
673 /* Read sample factor */
674 jpeg_info -> gx_jpeg_sample_factor[i_component] = *jpeg_data++;
675
676 /* Read quantization table index */
677 jpeg_info -> gx_jpeg_qantization_table_index[i_component] = *jpeg_data++;
678 }
679
680 return GX_SUCCESS;
681 }
682
683 /**************************************************************************/
684 /* */
685 /* FUNCTION RELEASE */
686 /* */
687 /* _gx_image_reader_jpeg_scan_header_read PORTABLE C */
688 /* 6.1 */
689 /* AUTHOR */
690 /* */
691 /* Kenneth Maxwell, Microsoft Corporation */
692 /* */
693 /* DESCRIPTION */
694 /* */
695 /* Reads in the scan header information. */
696 /* */
697 /* INPUT */
698 /* */
699 /* jpeg_info JPEG data control block */
700 /* segment_len Initial length of the segment */
701 /* */
702 /* OUTPUT */
703 /* */
704 /* None */
705 /* */
706 /* CALLS */
707 /* */
708 /* None */
709 /* */
710 /* CALLED BY */
711 /* */
712 /* _gx_image_reader_jpeg_decode_blocks */
713 /* */
714 /* RELEASE HISTORY */
715 /* */
716 /* DATE NAME DESCRIPTION */
717 /* */
718 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
719 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
720 /* resulting in version 6.1 */
721 /* */
722 /**************************************************************************/
_gx_image_reader_jpeg_scan_header_read(GX_JPEG_INFO * jpeg_info,UINT segment_len)723 static UINT _gx_image_reader_jpeg_scan_header_read(GX_JPEG_INFO *jpeg_info, UINT segment_len)
724 {
725 GX_UBYTE *jpeg_data = jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index;
726 INT index;
727
728 jpeg_data += 2;
729 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
730
731 /* Read the number of image components. */
732 jpeg_info -> gx_jpeg_num_of_components = *jpeg_data++;
733
734 if (jpeg_info -> gx_jpeg_num_of_components > JPG_MAX_COMPONENTS)
735 {
736 return GX_FAILURE;
737 }
738
739 for (index = 0; index < jpeg_info -> gx_jpeg_num_of_components; index++)
740 {
741 /* skip image component */
742 jpeg_data++;
743
744 /* high bits correspond to DC table index.
745 low bits correspond to AC table index
746 0: Y Huffman table
747 1: Chrominance Huffman table. */
748 jpeg_info -> gx_jpeg_dc_table_index[index] = ((*jpeg_data) & 0xf0) >> 4;
749 jpeg_info -> gx_jpeg_ac_table_index[index] = (*jpeg_data++) & 0x0f;
750 }
751
752 return GX_SUCCESS;
753 }
754
755 /**************************************************************************/
756 /* */
757 /* FUNCTION RELEASE */
758 /* */
759 /* _gx_image_reader_jpeg_dc_decode PORTABLE C */
760 /* 6.2.0 */
761 /* AUTHOR */
762 /* */
763 /* Kenneth Maxwell, Microsoft Corporation */
764 /* */
765 /* DESCRIPTION */
766 /* */
767 /* Decode the DC component. */
768 /* */
769 /* INPUT */
770 /* */
771 /* jpeg_info JPEG data control block */
772 /* i_component Component index */
773 /* */
774 /* OUTPUT */
775 /* */
776 /* Status */
777 /* */
778 /* CALLS */
779 /* */
780 /* _gx_image_reader_jpeg_bits_get Extract a specified number of*/
781 /* bits from JPEG data stream */
782 /* _gx_image_reader_jpeg_bits_skip Skips bits from tempory JPEG */
783 /* data stream */
784 /* _gx_image_reader_jpeg_huffman_code_find */
785 /* Lookup the huffman code */
786 /* */
787 /* CALLED BY */
788 /* */
789 /* _gx_image_reader_jpeg_one_block_decode */
790 /* */
791 /* RELEASE HISTORY */
792 /* */
793 /* DATE NAME DESCRIPTION */
794 /* */
795 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
796 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
797 /* resulting in version 6.1 */
798 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
799 /* added range test, */
800 /* resulting in version 6.2.0 */
801 /* */
802 /**************************************************************************/
_gx_image_reader_jpeg_dc_decode(GX_JPEG_INFO * jpeg_info,UINT i_component)803 static UINT _gx_image_reader_jpeg_dc_decode(GX_JPEG_INFO *jpeg_info, UINT i_component)
804 {
805 UINT scan_buffer;
806 UINT i_bits = 0;
807 GX_UBYTE code_value;
808 INT Diff;
809 UINT table_index = jpeg_info -> gx_jpeg_dc_table_index[i_component];
810 GX_BOOL negative;
811
812 if (table_index >= HUFF_TABLE_DIMENSION)
813 {
814 return GX_FAILURE;
815 }
816
817 _gx_image_reader_jpeg_bits_get(jpeg_info, 16, &scan_buffer);
818
819 if (_gx_image_reader_jpeg_huffcode_find(jpeg_info, 0, table_index, scan_buffer, &i_bits, &code_value) == 0)
820 {
821 _gx_image_reader_jpeg_bits_skip(i_bits);
822
823 if (code_value == 0)
824 {
825 jpeg_info -> gx_jpeg_vecter[0] = jpeg_info -> gx_jpeg_pre_dc[i_component];
826 }
827 else
828 {
829
830 _gx_image_reader_jpeg_bits_get(jpeg_info, code_value, (UINT *)&Diff);
831 _gx_image_reader_jpeg_bits_skip(code_value);
832
833 Diff = (INT)(((UINT)Diff) >> (32 - code_value));
834
835 negative = !(Diff >> (code_value - 1));
836
837 if (negative)
838 {
839 Diff += 1 - (1 << code_value);
840 }
841
842 jpeg_info -> gx_jpeg_vecter[0] = Diff + jpeg_info -> gx_jpeg_pre_dc[i_component];
843 jpeg_info -> gx_jpeg_pre_dc[i_component] = jpeg_info -> gx_jpeg_vecter[0];
844 }
845 }
846 else
847 {
848 return GX_FAILURE;
849 }
850
851 return GX_SUCCESS;
852 }
853
854 /**************************************************************************/
855 /* */
856 /* FUNCTION RELEASE */
857 /* */
858 /* _gx_image_reader_jpeg_ac_decode PORTABLE C */
859 /* 6.2.0 */
860 /* AUTHOR */
861 /* */
862 /* Kenneth Maxwell, Microsoft Corporation */
863 /* */
864 /* DESCRIPTION */
865 /* */
866 /* Decode the AC component. */
867 /* */
868 /* INPUT */
869 /* */
870 /* jpeg_info JPEG data control block */
871 /* i_component Component index */
872 /* */
873 /* OUTPUT */
874 /* */
875 /* Status Code */
876 /* */
877 /* CALLS */
878 /* */
879 /* _gx_image_reader_jpeg_bits_get Extract a specified number of*/
880 /* bits from JPEG data stream */
881 /* _gx_image_reader_jpeg_bits_skip Skips bits from tempory JPEG */
882 /* data stream */
883 /* _gx_image_reader_jpeg_huffman_code_find */
884 /* Lookup the huffman code */
885 /* */
886 /* CALLED BY */
887 /* */
888 /* _gx_image_reader_jpeg_one_block_decode */
889 /* */
890 /* RELEASE HISTORY */
891 /* */
892 /* DATE NAME DESCRIPTION */
893 /* */
894 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
895 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
896 /* resulting in version 6.1 */
897 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
898 /* added range test, */
899 /* resulting in version 6.2.0 */
900 /* */
901 /**************************************************************************/
_gx_image_reader_jpeg_ac_decode(GX_JPEG_INFO * jpeg_info,UINT i_component)902 static UINT _gx_image_reader_jpeg_ac_decode(GX_JPEG_INFO *jpeg_info, UINT i_component)
903 {
904 UINT scan_buffer;
905 UINT i_bits = 0;
906 GX_UBYTE code_value;
907 GX_UBYTE catogory;
908 GX_UBYTE runs_of_zero;
909 INT ac_coefficient;
910 UINT ac_counter = 1;
911 UINT table_index = jpeg_info -> gx_jpeg_ac_table_index[i_component];
912 INT negative;
913
914 if (table_index >= HUFF_TABLE_DIMENSION)
915 {
916 return GX_FAILURE;
917 }
918
919 while (ac_counter < 64)
920 {
921 i_bits = 0;
922 _gx_image_reader_jpeg_bits_get(jpeg_info, 16, &scan_buffer);
923
924 if (_gx_image_reader_jpeg_huffcode_find(jpeg_info, 1, table_index, scan_buffer, &i_bits, &code_value) == 0)
925 {
926 _gx_image_reader_jpeg_bits_skip(i_bits);
927
928 runs_of_zero = (0xf0 & code_value) >> 4;
929 catogory = 0x0f & code_value;
930
931 if (catogory == 0)
932 {
933 /* EOB encountered. */
934 if (runs_of_zero == 0)
935 {
936 ac_counter = 64;
937 }
938 else if (runs_of_zero == 0x0f)
939 {
940 ac_counter += 16;
941 }
942 }
943 else
944 {
945 ac_counter += runs_of_zero;
946
947 _gx_image_reader_jpeg_bits_get(jpeg_info, catogory, (UINT *)&ac_coefficient);
948 _gx_image_reader_jpeg_bits_skip(catogory);
949
950 ac_coefficient = (INT)(((UINT)ac_coefficient) >> (32 - catogory));
951
952 negative = !(ac_coefficient >> (catogory - 1));
953
954 if (negative)
955 {
956 ac_coefficient += 1 - (1 << catogory);
957 }
958
959 if (ac_counter < 64)
960 {
961 jpeg_info -> gx_jpeg_vecter[ac_counter++] = ac_coefficient;
962 }
963 }
964 }
965 else
966 {
967 return GX_FAILURE;
968 }
969 }
970
971 return GX_SUCCESS;
972 }
973
974 /* Define the triple Bufferfly Addition operation */
975 #define TRIPPLE_BUTTERFLY_ADDITION(a, b, c, d, r) p = a + b, n = a - b, a = p + c + r, b = n + d + r, c = p - c + r, d = n - d + r
976
977 /* Define the butterfly Multiplication */
978 #define BUTTERFLY_MULTIPLICATION(a, b, k1, k2, sh) n = k1 * (a + b), p = a, a = (n + (k2 - k1) * b) >> sh, b = (n - (k2 + k1) * p) >> sh
979
980 /**************************************************************************/
981 /* */
982 /* FUNCTION RELEASE */
983 /* */
984 /* _gx_image_reader_jpeg_1d_idct PORTABLE C */
985 /* 6.1 */
986 /* AUTHOR */
987 /* */
988 /* Kenneth Maxwell, Microsoft Corporation */
989 /* */
990 /* DESCRIPTION */
991 /* */
992 /* Performs 1D Inverse Discrete Consine Transformation. It is an */
993 /* implementation of LLM (Loeffler, Lighenberg, Moschytz) algorithm. */
994 /* */
995 /* INPUT */
996 /* */
997 /* input_data Input data */
998 /* output_data Buffer for output data */
999 /* post_scale Post scale value */
1000 /* round Value to reduce round error */
1001 /* */
1002 /* OUTPUT */
1003 /* */
1004 /* None */
1005 /* */
1006 /* CALLS */
1007 /* */
1008 /* None */
1009 /* */
1010 /* CALLED BY */
1011 /* */
1012 /* _gx_image_reader_jpeg_2d_idct */
1013 /* */
1014 /* RELEASE HISTORY */
1015 /* */
1016 /* DATE NAME DESCRIPTION */
1017 /* */
1018 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1019 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1020 /* resulting in version 6.1 */
1021 /* */
1022 /**************************************************************************/
_gx_image_reader_jpeg_1d_idct(INT * input_data,INT * output_data,INT post_scale,INT round)1023 static VOID _gx_image_reader_jpeg_1d_idct(INT *input_data, INT *output_data, INT post_scale, INT round)
1024 {
1025 INT p;
1026 INT n;
1027
1028 /* Prescale */
1029 input_data[0] <<= 9;
1030 input_data[1] <<= 7;
1031 input_data[3] *= 181;
1032 input_data[4] <<= 9;
1033 input_data[5] *= 181;
1034 input_data[7] <<= 7;
1035
1036 /* iDCT computation .*/
1037 BUTTERFLY_MULTIPLICATION(input_data[6], input_data[2], 277, 669, 0);
1038 TRIPPLE_BUTTERFLY_ADDITION(input_data[0], input_data[4], input_data[6], input_data[2], round);
1039 TRIPPLE_BUTTERFLY_ADDITION(input_data[1], input_data[7], input_data[3], input_data[5], 0);
1040 BUTTERFLY_MULTIPLICATION(input_data[5], input_data[3], 251, 50, 6);
1041 BUTTERFLY_MULTIPLICATION(input_data[1], input_data[7], 213, 142, 6);
1042
1043 /* Post-scale */
1044 output_data[0] = (input_data[0] + input_data[1]) >> post_scale;
1045 output_data[8] = (input_data[4] + input_data[5]) >> post_scale;
1046 output_data[16] = (input_data[2] + input_data[3]) >> post_scale;
1047 output_data[24] = (input_data[6] + input_data[7]) >> post_scale;
1048 output_data[32] = (input_data[6] - input_data[7]) >> post_scale;
1049 output_data[40] = (input_data[2] - input_data[3]) >> post_scale;
1050 output_data[48] = (input_data[4] - input_data[5]) >> post_scale;
1051 output_data[56] = (input_data[0] - input_data[1]) >> post_scale;
1052 }
1053
1054 /**************************************************************************/
1055 /* */
1056 /* FUNCTION RELEASE */
1057 /* */
1058 /* _gx_image_reader_jpeg_2d_idct PORTABLE C */
1059 /* 6.1 */
1060 /* AUTHOR */
1061 /* */
1062 /* Kenneth Maxwell, Microsoft Corporation */
1063 /* */
1064 /* DESCRIPTION */
1065 /* */
1066 /* Performs 2D Inverse Discrete Consine Transformation. */
1067 /* */
1068 /* INPUT */
1069 /* */
1070 /* block Input data */
1071 /* */
1072 /* OUTPUT */
1073 /* */
1074 /* None */
1075 /* */
1076 /* CALLS */
1077 /* */
1078 /* _gx_image_reader_jpeg_1d_idct Perform 1D Inverse Discrete */
1079 /* Consine Transformation */
1080 /* */
1081 /* CALLED BY */
1082 /* */
1083 /* _gx_image_reader_jpeg_dequantize_idct */
1084 /* */
1085 /* RELEASE HISTORY */
1086 /* */
1087 /* DATE NAME DESCRIPTION */
1088 /* */
1089 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1090 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1091 /* resulting in version 6.1 */
1092 /* */
1093 /**************************************************************************/
_gx_image_reader_jpeg_2d_idct(INT * block)1094 static VOID _gx_image_reader_jpeg_2d_idct(INT *block)
1095 {
1096 INT i;
1097 INT temp_block[64];
1098
1099 for (i = 0; i < 8; i++)
1100 {
1101 _gx_image_reader_jpeg_1d_idct(block + i * 8, temp_block + i, 9, 512); /* row */
1102 }
1103
1104 for (i = 0; i < 8; i++)
1105 {
1106 _gx_image_reader_jpeg_1d_idct(temp_block + i * 8, block + i, 12, 2048); /* col */
1107 }
1108 }
1109
1110 /**************************************************************************/
1111 /* */
1112 /* FUNCTION RELEASE */
1113 /* */
1114 /* _gx_image_reader_jpeg_dequantize_idct PORTABLE C */
1115 /* 6.2.0 */
1116 /* AUTHOR */
1117 /* */
1118 /* Kenneth Maxwell, Microsoft Corporation */
1119 /* */
1120 /* DESCRIPTION */
1121 /* */
1122 /* Dequatilizes decoded data and performs Inverse Discrete Consine */
1123 /* Transformation. */
1124 /* */
1125 /* INPUT */
1126 /* */
1127 /* jpeg_info JPEG data control block */
1128 /* data Pointer to decoded data */
1129 /* i_component Component index */
1130 /* */
1131 /* OUTPUT */
1132 /* */
1133 /* None */
1134 /* */
1135 /* CALLS */
1136 /* */
1137 /* _gx_image_reader_jpeg_2d_idct Perform 2D Inverse Discrete */
1138 /* Consine Transformation */
1139 /* _gx_image_reader_jpeg_range Limit value in range [0, 255] */
1140 /* */
1141 /* CALLED BY */
1142 /* */
1143 /* _gx_image_reader_jpeg_one_block_decode */
1144 /* */
1145 /* RELEASE HISTORY */
1146 /* */
1147 /* DATE NAME DESCRIPTION */
1148 /* */
1149 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1150 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1151 /* resulting in version 6.1 */
1152 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
1153 /* added range check for */
1154 /* stride, changed return val, */
1155 /* added range check for */
1156 /* table_index, */
1157 /* resulting in version 6.2.0 */
1158 /* */
1159 /**************************************************************************/
_gx_image_reader_jpeg_dequantize_idct(GX_JPEG_INFO * jpeg_info,GX_UBYTE * data,UINT i_component)1160 static UINT _gx_image_reader_jpeg_dequantize_idct(GX_JPEG_INFO *jpeg_info, GX_UBYTE *data, UINT i_component)
1161 {
1162 INT table_index;
1163 INT stride;
1164 GX_UBYTE *outptr = data;
1165 INT index;
1166 INT x;
1167 INT y;
1168 INT jpeg_block[64];
1169
1170 if (i_component >= JPG_MAX_COMPONENTS)
1171 {
1172 return GX_FAILURE;
1173 }
1174
1175 stride = ((jpeg_info -> gx_jpeg_sample_factor[i_component] & 0xf0) >> 1);
1176
1177 if (i_component == 0)
1178 {
1179 if (stride > 32)
1180 {
1181 return GX_FAILURE;
1182 }
1183 }
1184 else
1185 {
1186 if (stride > 8)
1187 {
1188 return GX_FAILURE;
1189 }
1190 }
1191
1192 table_index = jpeg_info -> gx_jpeg_qantization_table_index[i_component];
1193
1194 if (table_index >= JPG_QUANT_TABLE_DIMENSION)
1195 {
1196 return GX_FAILURE;
1197 }
1198
1199 for (index = 0; index < 64; index++)
1200 {
1201 jpeg_info -> gx_jpeg_vecter[index] *= jpeg_info -> gx_jpeg_quantization_table[table_index][index];
1202
1203 /* Reorder from zig-zag order to 8*8 block */
1204 jpeg_block[_gx_jpg_reorder_index[index]] = jpeg_info -> gx_jpeg_vecter[index];
1205 }
1206
1207 _gx_image_reader_jpeg_2d_idct(jpeg_block);
1208
1209 for (y = 0; y < 8; y++)
1210 {
1211 for (x = 0; x < 8; x++)
1212 {
1213 outptr[x] = _gx_image_reader_jpeg_range(jpeg_block[y * 8 + x] + 128);
1214 }
1215
1216 outptr += stride;
1217 }
1218 return GX_SUCCESS;
1219 }
1220
1221 /**************************************************************************/
1222 /* */
1223 /* FUNCTION RELEASE */
1224 /* */
1225 /* _gx_image_reader_jpeg_one_block_decode PORTABLE C */
1226 /* 6.2.0 */
1227 /* AUTHOR */
1228 /* */
1229 /* Kenneth Maxwell, Microsoft Corporation */
1230 /* */
1231 /* DESCRIPTION */
1232 /* */
1233 /* Decode one block of JPEG data. */
1234 /* */
1235 /* INPUT */
1236 /* */
1237 /* jpeg_info JPEG data control block */
1238 /* icomponent Component index */
1239 /* block_data Pointer to decoded data */
1240 /* */
1241 /* OUTPUT */
1242 /* */
1243 /* Status Code */
1244 /* */
1245 /* CALLS */
1246 /* */
1247 /* memset */
1248 /* _gx_image_reader_jpeg_dc_decode Decode dc component */
1249 /* _gx_image_reader_jpeg_ac_decode Decode ac component */
1250 /* _gx_image_reader_jpeg_dequantize_idct Dequatilize decoded data */
1251 /* */
1252 /* CALLED BY */
1253 /* */
1254 /* _gx_image_reader_jpeg_decode */
1255 /* */
1256 /* RELEASE HISTORY */
1257 /* */
1258 /* DATE NAME DESCRIPTION */
1259 /* */
1260 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1261 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1262 /* resulting in version 6.1 */
1263 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
1264 /* returned result of */
1265 /* dequantize_idct, */
1266 /* resulting in version 6.2.0 */
1267 /* */
1268 /**************************************************************************/
_gx_image_reader_jpeg_one_block_decode(GX_JPEG_INFO * jpeg_info,UINT i_component,GX_UBYTE * block_data)1269 static UINT _gx_image_reader_jpeg_one_block_decode(GX_JPEG_INFO *jpeg_info, UINT i_component, GX_UBYTE *block_data)
1270 {
1271 UINT status = GX_SUCCESS;
1272
1273 memset(jpeg_info -> gx_jpeg_vecter, 0, 64 * sizeof(UINT));
1274 _gx_image_reader_jpeg_dc_decode(jpeg_info, i_component);
1275 _gx_image_reader_jpeg_ac_decode(jpeg_info, i_component);
1276
1277 status = _gx_image_reader_jpeg_dequantize_idct(jpeg_info, block_data, i_component);
1278
1279 return status;
1280 }
1281
1282 /**************************************************************************/
1283 /* */
1284 /* FUNCTION RELEASE */
1285 /* */
1286 /* _gx_image_reader_jpeg_one_mcu_write PORTABLE C */
1287 /* 6.1 */
1288 /* AUTHOR */
1289 /* */
1290 /* Kenneth Maxwell, Microsoft Corporation */
1291 /* */
1292 /* DESCRIPTION */
1293 /* */
1294 /* Write decoded data of one MCU block into specified memory. */
1295 /* */
1296 /* INPUT */
1297 /* */
1298 /* jpeg_info JPEG control block */
1299 /* xpos X position in image */
1300 /* ypos y position in image */
1301 /* */
1302 /* OUTPUT */
1303 /* */
1304 /* Status Code */
1305 /* */
1306 /* CALLS */
1307 /* */
1308 /* _gx_image_reader_jpeg_YCbCr2RGB_888 Convert YCbCr value to 888RGB */
1309 /* color space */
1310 /* */
1311 /* CALLED BY */
1312 /* */
1313 /* _gx_image_reader_jpeg_decode */
1314 /* */
1315 /* RELEASE HISTORY */
1316 /* */
1317 /* DATE NAME DESCRIPTION */
1318 /* */
1319 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1320 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1321 /* resulting in version 6.1 */
1322 /* */
1323 /**************************************************************************/
_gx_image_reader_jpeg_one_mcu_write(GX_JPEG_INFO * jpeg_info,INT xpos,INT ypos)1324 static UINT _gx_image_reader_jpeg_one_mcu_write(GX_JPEG_INFO *jpeg_info, INT xpos, INT ypos)
1325 {
1326 GX_UBYTE *put;
1327 INT x;
1328 INT y;
1329 INT w;
1330 INT h;
1331 INT coff;
1332 INT Y;
1333 INT Cb;
1334 INT Cr;
1335 INT width_in_bytes;
1336
1337 h = (jpeg_info -> gx_jpeg_sample_factor[0] >> 4);
1338 w = (jpeg_info -> gx_jpeg_sample_factor[0] & 0x0f);
1339
1340 width_in_bytes = jpeg_info -> gx_jpeg_width * 3;
1341 put = (GX_UBYTE *)jpeg_info -> gx_jpeg_decoded_data;
1342 put += ypos * width_in_bytes;
1343 put += xpos * 3;
1344
1345 for (y = 0; y < 8 * h; y++)
1346 {
1347 if (ypos + y >= jpeg_info -> gx_jpeg_height)
1348 {
1349 break;
1350 }
1351
1352 for (x = 0; x < 8 * w; x++)
1353 {
1354 if (xpos + x >= jpeg_info -> gx_jpeg_width)
1355 {
1356 break;
1357 }
1358 coff = x / w + ((y / h) << 3);
1359
1360 Y = jpeg_info -> gx_jpeg_Y_block[x + y * w * 8];
1361 Cb = jpeg_info -> gx_jpeg_Cb_block[coff];
1362 Cr = jpeg_info -> gx_jpeg_Cr_block[coff];
1363
1364 _gx_image_reader_jpeg_YCbCr2RGB_888(Y, Cb, Cr, put + x * 3);
1365 }
1366
1367 put += width_in_bytes;
1368 }
1369
1370 return GX_SUCCESS;
1371 }
1372
1373 /**************************************************************************/
1374 /* */
1375 /* FUNCTION RELEASE */
1376 /* */
1377 /* _gx_image_reader_jpeg_decompress PORTABLE C */
1378 /* 6.2.0 */
1379 /* AUTHOR */
1380 /* */
1381 /* Kenneth Maxwell, Microsoft Corporation */
1382 /* */
1383 /* DESCRIPTION */
1384 /* */
1385 /* Decompress JPG data stream. */
1386 /* */
1387 /* INPUT */
1388 /* */
1389 /* jpeg_info JPEG control block */
1390 /* */
1391 /* OUTPUT */
1392 /* */
1393 /* Status Code */
1394 /* */
1395 /* CALLS */
1396 /* */
1397 /* _gx_image_reader_jpeg_one_block_decode */
1398 /* Decode one blcok of jpeg data */
1399 /* _gx_image_reader_jpeg_one_mcu_write Write decoded data to */
1400 /* specified memory */
1401 /* */
1402 /* CALLED BY */
1403 /* */
1404 /* _gx_image_reader_jpeg_decode */
1405 /* */
1406 /* RELEASE HISTORY */
1407 /* */
1408 /* DATE NAME DESCRIPTION */
1409 /* */
1410 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1411 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1412 /* resulting in version 6.1 */
1413 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
1414 /* abort if block decode fails,*/
1415 /* resulting in version 6.2.0 */
1416 /* */
1417 /**************************************************************************/
_gx_image_reader_jpeg_decompress(GX_JPEG_INFO * jpeg_info)1418 static UINT _gx_image_reader_jpeg_decompress(GX_JPEG_INFO *jpeg_info)
1419 {
1420 int h;
1421 int w;
1422 int x;
1423 int y;
1424 int xx;
1425 int yy;
1426 UINT status = GX_SUCCESS;
1427
1428 _gx_jpg_bit_buffer = 0;
1429 _gx_jpg_bit_count = 0;
1430
1431 h = jpeg_info -> gx_jpeg_height * 3;
1432 w = jpeg_info -> gx_jpeg_width * 3;
1433
1434 h = (jpeg_info -> gx_jpeg_sample_factor[0] >> 4);
1435 w = (jpeg_info -> gx_jpeg_sample_factor[0] & 0x0f);
1436
1437 if (jpeg_info -> gx_jpeg_mcu_draw == GX_NULL)
1438 {
1439 /* Safe int math is not required here, max width and height are limited to 14 bits so
1440 overflow cannot occur. */
1441 jpeg_info -> gx_jpeg_decoded_data_size = (UINT)(jpeg_info -> gx_jpeg_width * jpeg_info -> gx_jpeg_height * 3);
1442
1443 /* Allocate memory to load decoded data. */
1444 jpeg_info -> gx_jpeg_decoded_data = (GX_UBYTE *)_gx_system_memory_allocator((ULONG)jpeg_info -> gx_jpeg_decoded_data_size);
1445
1446 if (jpeg_info -> gx_jpeg_decoded_data == GX_NULL)
1447 {
1448 return GX_SYSTEM_MEMORY_ERROR;
1449 }
1450 }
1451
1452 for (y = 0; y < jpeg_info -> gx_jpeg_height; y += 8 * h)
1453 {
1454 for (x = 0; x < jpeg_info -> gx_jpeg_width; x += 8 * w)
1455 {
1456 /* Decode one MCU */
1457 for (yy = 0; yy < h && status == GX_SUCCESS; yy++)
1458 {
1459 for (xx = 0; xx < w && status == GX_SUCCESS; xx++)
1460 {
1461 /* Y */
1462 status = _gx_image_reader_jpeg_one_block_decode(jpeg_info, 0, jpeg_info -> gx_jpeg_Y_block + yy * 128 + xx * 8);
1463 }
1464 }
1465
1466 if (status == GX_SUCCESS && jpeg_info -> gx_jpeg_num_of_components > 1)
1467 {
1468 /* Cb */
1469 status = _gx_image_reader_jpeg_one_block_decode(jpeg_info, 1, jpeg_info -> gx_jpeg_Cb_block);
1470
1471 /* Cr */
1472 if (status == GX_SUCCESS)
1473 {
1474 status = _gx_image_reader_jpeg_one_block_decode(jpeg_info, 2, jpeg_info -> gx_jpeg_Cr_block);
1475 }
1476 }
1477
1478 if (status == GX_SUCCESS)
1479 {
1480 if (jpeg_info -> gx_jpeg_mcu_draw)
1481 {
1482 if (jpeg_info -> gx_jpeg_draw_context)
1483 {
1484 jpeg_info -> gx_jpeg_mcu_draw(jpeg_info,
1485 jpeg_info -> gx_jpeg_draw_xpos + x,
1486 jpeg_info -> gx_jpeg_draw_ypos + y);
1487 }
1488 }
1489 else
1490 {
1491 _gx_image_reader_jpeg_one_mcu_write(jpeg_info, x, y);
1492 }
1493 }
1494 }
1495 }
1496
1497 return status;
1498 }
1499
1500 /**************************************************************************/
1501 /* */
1502 /* FUNCTION RELEASE */
1503 /* */
1504 /* _gx_image_reader_jpeg_decode_blocks PORTABLE C */
1505 /* 6.1 */
1506 /* AUTHOR */
1507 /* */
1508 /* Kenneth Maxwell, Microsoft Corporation */
1509 /* */
1510 /* DESCRIPTION */
1511 /* */
1512 /* This function decode a jpg format image. */
1513 /* */
1514 /* INPUT */
1515 /* */
1516 /* jpeg_info Jpeg decode control block */
1517 /* */
1518 /* OUTPUT */
1519 /* */
1520 /* status Completion status */
1521 /* */
1522 /* CALLS */
1523 /* */
1524 /* _gx_image_reader_jpeg_quantization_table_set */
1525 /* Set jpeg quantization table */
1526 /* _gx_image_reader_jpeg_frame_header_read */
1527 /* Read frame header information */
1528 /* _gx_image_reader_huffman_table_set Set up huffman table */
1529 /* _gx_image_reader_jpeg_scan_header_read */
1530 /* Read scan header information */
1531 /* _gx_image_reader_jpeg_decompress Decompress jped data stream */
1532 /* _gx_system_memory_free Application defined memory */
1533 /* free function */
1534 /* */
1535 /* CALLED BY */
1536 /* */
1537 /* _gx_image_reader_jpeg_decode */
1538 /* _gx_image_reader_jpeg_mcu_decode */
1539 /* */
1540 /* RELEASE HISTORY */
1541 /* */
1542 /* DATE NAME DESCRIPTION */
1543 /* */
1544 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1545 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1546 /* resulting in version 6.1 */
1547 /* */
1548 /**************************************************************************/
_gx_image_reader_jpeg_decode_blocks(GX_JPEG_INFO * jpeg_info)1549 static UINT _gx_image_reader_jpeg_decode_blocks(GX_JPEG_INFO *jpeg_info)
1550 {
1551 GX_UBYTE *jpeg_data;
1552 GX_UBYTE marker;
1553 UINT segment_len;
1554 UINT index;
1555 UINT table_class;
1556 UINT status = GX_SUCCESS;
1557
1558 if (jpeg_info -> gx_jpeg_data == GX_NULL || jpeg_info -> gx_jpeg_data_size < 10)
1559 {
1560 return GX_INVALID_VALUE;
1561 }
1562
1563 jpeg_data = jpeg_info -> gx_jpeg_data;
1564
1565 /* Read JPEG File flag that mark the start of a JPEG image. */
1566 if ((*jpeg_data++ != 0xff) || (*jpeg_data++ != 0xd8))
1567 {
1568 return GX_INVALID_FORMAT; /*Not a jpeg file */
1569 }
1570
1571 jpeg_info -> gx_jpeg_data_index += 2;
1572
1573 while ((jpeg_info -> gx_jpeg_data_index + 3 < jpeg_info -> gx_jpeg_data_size) &&
1574 (status == GX_SUCCESS))
1575 {
1576 jpeg_data = (jpeg_info -> gx_jpeg_data + jpeg_info -> gx_jpeg_data_index);
1577 marker = *(jpeg_data + 1);
1578
1579 if ((*jpeg_data == 0xff) && (marker != 0) && (marker != 0xff))
1580 {
1581 jpeg_data += 2;
1582 jpeg_info -> gx_jpeg_data_index += 2;
1583
1584 /* Read WORD length */
1585 segment_len = *(jpeg_data);
1586 segment_len <<= 8;
1587 segment_len |= *(jpeg_data + 1);
1588
1589 if ((UINT)jpeg_info -> gx_jpeg_data_index + segment_len > (UINT)jpeg_info -> gx_jpeg_data_size)
1590 {
1591 /* Invalid data size. */
1592 status = GX_FAILURE;
1593 break;
1594 }
1595
1596 switch (marker)
1597 {
1598 case 0xdb:
1599 /* Define Quantization Table */
1600 status = _gx_image_reader_jpeg_quantization_table_set(jpeg_info, segment_len);
1601 break;
1602
1603 case 0xc0:
1604 /* Start of Frame */
1605 status = _gx_image_reader_jpeg_frame_header_read(jpeg_info, segment_len);
1606 break;
1607
1608 case 0xc4:
1609 /* Define Huffman Table */
1610 status = _gx_image_reader_huffman_table_set(jpeg_info, segment_len);
1611 break;
1612
1613 case 0xdd:
1614 /* Read restart interval which specifies the number of MCU in restart interval. */
1615 jpeg_data += 2;
1616 jpeg_info -> gx_jpeg_restart_interval = *jpeg_data++;
1617 jpeg_info -> gx_jpeg_restart_interval <<= 8;
1618 jpeg_info -> gx_jpeg_restart_interval |= *jpeg_data++;
1619 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
1620 break;
1621
1622 case 0xda:
1623 /* Start of Scan, stores which Huffman tables are associated with which components
1624 The program start decoding the data section directly after it reads in this header. */
1625 _gx_image_reader_jpeg_scan_header_read(jpeg_info, segment_len);
1626
1627 /* Start decoding jpeg data stream. */
1628 status = _gx_image_reader_jpeg_decompress(jpeg_info);
1629 break;
1630
1631 default:
1632 /* Unkown marker, skip */
1633 jpeg_info -> gx_jpeg_data_index += (INT)segment_len;
1634 break;
1635 }
1636 }
1637 else
1638 {
1639 jpeg_info -> gx_jpeg_data_index++;
1640 }
1641 }
1642
1643 for (table_class = 0; table_class < 2; table_class++)
1644 {
1645 for (index = 0; index < 2; index++)
1646 {
1647 if (jpeg_info -> gx_jpeg_huffman_table[table_class][index])
1648 {
1649 _gx_system_memory_free(jpeg_info -> gx_jpeg_huffman_table[table_class][index]);
1650 }
1651 }
1652 }
1653
1654 return status;
1655 }
1656
1657 /**************************************************************************/
1658 /* */
1659 /* FUNCTION RELEASE */
1660 /* */
1661 /* _gx_image_reader_jpeg_decode PORTABLE C */
1662 /* 6.1 */
1663 /* AUTHOR */
1664 /* */
1665 /* Kenneth Maxwell, Microsoft Corporation */
1666 /* */
1667 /* DESCRIPTION */
1668 /* */
1669 /* This function decodes a jpg format image and saves the decoded data */
1670 /* to a GX_PIXELMAP structure. */
1671 /* */
1672 /* INPUT */
1673 /* */
1674 /* read_data Input JPEG data stream */
1675 /* data_size JPEG size in bytes */
1676 /* outmap Output pixelmap */
1677 /* */
1678 /* OUTPUT */
1679 /* */
1680 /* status Completion status */
1681 /* */
1682 /* CALLS */
1683 /* */
1684 /* _gx_image_reader_jpeg_decode_blocks Decode a jpeg format image */
1685 /* */
1686 /* CALLED BY */
1687 /* */
1688 /* _gx_image_reader_image_decode */
1689 /* */
1690 /* RELEASE HISTORY */
1691 /* */
1692 /* DATE NAME DESCRIPTION */
1693 /* */
1694 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1695 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1696 /* resulting in version 6.1 */
1697 /* */
1698 /**************************************************************************/
_gx_image_reader_jpeg_decode(GX_CONST GX_UBYTE * read_data,ULONG data_size,GX_PIXELMAP * outmap)1699 UINT _gx_image_reader_jpeg_decode(GX_CONST GX_UBYTE *read_data, ULONG data_size,
1700 GX_PIXELMAP *outmap)
1701 {
1702 UINT status;
1703 GX_JPEG_INFO *jpeg_info;
1704
1705
1706 if ((!_gx_system_memory_allocator) || (!_gx_system_memory_free))
1707 {
1708 return GX_SYSTEM_MEMORY_ERROR;
1709 }
1710
1711 jpeg_info = (GX_JPEG_INFO *)_gx_system_memory_allocator(sizeof(GX_JPEG_INFO));
1712
1713 if (!jpeg_info)
1714 {
1715 return GX_SYSTEM_MEMORY_ERROR;
1716 }
1717
1718 memset(jpeg_info, 0, sizeof(GX_JPEG_INFO));
1719
1720 jpeg_info -> gx_jpeg_data = (GX_UBYTE *)read_data;
1721 jpeg_info -> gx_jpeg_data_size = (INT)data_size;
1722 jpeg_info -> gx_jpeg_data_index = 0;
1723 jpeg_info -> gx_jpeg_draw_context = GX_NULL;
1724
1725 status = _gx_image_reader_jpeg_decode_blocks(jpeg_info);
1726
1727 if (status == GX_SUCCESS)
1728 {
1729 outmap -> gx_pixelmap_data = jpeg_info -> gx_jpeg_decoded_data;
1730 outmap -> gx_pixelmap_data_size = jpeg_info -> gx_jpeg_decoded_data_size;
1731 outmap -> gx_pixelmap_width = (GX_VALUE)jpeg_info -> gx_jpeg_width;
1732 outmap -> gx_pixelmap_height = (GX_VALUE)jpeg_info -> gx_jpeg_height;
1733 outmap -> gx_pixelmap_flags = GX_PIXELMAP_RAW_FORMAT;
1734 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_24BPP;
1735 }
1736
1737 _gx_system_memory_free((void *)jpeg_info);
1738
1739 return status;
1740 }
1741
1742 /**************************************************************************/
1743 /* */
1744 /* FUNCTION RELEASE */
1745 /* */
1746 /* _gx_image_reader_jpeg_mcu_decode PORTABLE C */
1747 /* 6.1 */
1748 /* AUTHOR */
1749 /* */
1750 /* Kenneth Maxwell, Microsoft Corporation */
1751 /* */
1752 /* DESCRIPTION */
1753 /* */
1754 /* This function decodes a jpg format image and draw it to canvas */
1755 /* directly. */
1756 /* */
1757 /* INPUT */
1758 /* */
1759 /* read_data Input JPEG data */
1760 /* data_size JPEG size in bytes */
1761 /* context Drawing contex */
1762 /* xpos X-coord of draw start point in*/
1763 /* canvas */
1764 /* ypos Y-coord of draw start point in*/
1765 /* canvas */
1766 /* draw_function Callback of one mcu draw */
1767 /* */
1768 /* OUTPUT */
1769 /* */
1770 /* status Completion status */
1771 /* */
1772 /* CALLS */
1773 /* */
1774 /* _gx_image_reader_jpeg_decode_blocks Decode a jpeg format image */
1775 /* */
1776 /* CALLED BY */
1777 /* */
1778 /* GUIX Internal Code */
1779 /* */
1780 /* RELEASE HISTORY */
1781 /* */
1782 /* DATE NAME DESCRIPTION */
1783 /* */
1784 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1785 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1786 /* resulting in version 6.1 */
1787 /* */
1788 /**************************************************************************/
_gx_image_reader_jpeg_mcu_decode(GX_CONST GX_UBYTE * read_data,ULONG data_size,GX_DRAW_CONTEXT * context,INT xpos,INT ypos,UINT (draw_function)(GX_JPEG_INFO *,INT,INT))1789 UINT _gx_image_reader_jpeg_mcu_decode(GX_CONST GX_UBYTE *read_data, ULONG data_size,
1790 GX_DRAW_CONTEXT *context, INT xpos, INT ypos,
1791 UINT(draw_function)(GX_JPEG_INFO *, INT, INT))
1792 {
1793 UINT status;
1794 GX_JPEG_INFO *jpeg_info;
1795
1796 if ((!_gx_system_memory_allocator) || (!_gx_system_memory_free))
1797 {
1798 return GX_SYSTEM_MEMORY_ERROR;
1799 }
1800
1801 jpeg_info = (GX_JPEG_INFO *)_gx_system_memory_allocator(sizeof(GX_JPEG_INFO));
1802
1803 if (!jpeg_info)
1804 {
1805 return GX_SYSTEM_MEMORY_ERROR;
1806 }
1807
1808 memset(jpeg_info, 0, sizeof(GX_JPEG_INFO));
1809
1810 jpeg_info -> gx_jpeg_data = (GX_UBYTE *)read_data;
1811 jpeg_info -> gx_jpeg_data_size = (INT)data_size;
1812 jpeg_info -> gx_jpeg_data_index = 0;
1813 jpeg_info -> gx_jpeg_draw_context = context;
1814 jpeg_info -> gx_jpeg_mcu_draw = draw_function;
1815 jpeg_info -> gx_jpeg_draw_xpos = xpos;
1816 jpeg_info -> gx_jpeg_draw_ypos = ypos;
1817
1818 status = _gx_image_reader_jpeg_decode_blocks(jpeg_info);
1819
1820 _gx_system_memory_free((void *)jpeg_info);
1821
1822 return status;
1823 }
1824 #endif
1825
1826