GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/extensions/tjpgd.c
Date: 2025-08-08 18:10:24
Exec Total Coverage
Lines: 383 433 88.5%
Functions: 11 11 100.0%
Branches: 179 279 64.2%

Line Branch Exec Source
1 /*----------------------------------------------------------------------------/
2 / TJpgDec - Tiny JPEG Decompressor R0.03 (C)ChaN, 2021
3 /-----------------------------------------------------------------------------/
4 / The TJpgDec is a generic JPEG decompressor module for tiny embedded systems.
5 / This is a free software that opened for education, research and commercial
6 / developments under license policy of following terms.
7 /
8 / Copyright (C) 2021, ChaN, all right reserved.
9 /
10 / * The TJpgDec module is a free software and there is NO WARRANTY.
11 / * No restriction on use. You can use, modify and redistribute it for
12 / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
13 / * Redistributions of source code must retain the above copyright notice.
14 /
15 /-----------------------------------------------------------------------------/
16 / Oct 04, 2011 R0.01 First release.
17 / Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq.
18 / Sep 03, 2012 R0.01b Added JD_TBLCLIP option.
19 / Mar 16, 2019 R0.01c Supprted stdint.h.
20 / Jul 01, 2020 R0.01d Fixed wrong integer type usage.
21 / May 08, 2021 R0.02 Supprted grayscale image. Separated configuration options.
22 / Jun 11, 2021 R0.02a Some performance improvement.
23 / Jul 01, 2021 R0.03 Added JD_FASTDECODE option.
24 / Some performance improvement.
25 /----------------------------------------------------------------------------*/
26
27 #include "tjpgd.h"
28
29
30 #if JD_FASTDECODE == 2
31 #define HUFF_BIT 10 /* Bit length to apply fast huffman decode */
32 #define HUFF_LEN (1 << HUFF_BIT)
33 #define HUFF_MASK (HUFF_LEN - 1)
34 #endif
35
36
37 /*-----------------------------------------------*/
38 /* Zigzag-order to raster-order conversion table */
39 /*-----------------------------------------------*/
40
41 static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */
42 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
43 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
44 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
45 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
46 };
47
48
49
50 /*-------------------------------------------------*/
51 /* Input scale factor of Arai algorithm */
52 /* (scaled up 16 bits for fixed point operations) */
53 /*-------------------------------------------------*/
54
55 static const uint16_t Ipsf[64] = { /* See also aa_idct.png */
56 (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192),
57 (uint16_t)(1.38704*8192), (uint16_t)(1.92388*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.08979*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.38268*8192),
58 (uint16_t)(1.30656*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.70711*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.36048*8192),
59 (uint16_t)(1.17588*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.38268*8192), (uint16_t)(1.17588*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.32442*8192),
60 (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192),
61 (uint16_t)(0.78570*8192), (uint16_t)(1.08979*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.92388*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.61732*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.21677*8192),
62 (uint16_t)(0.54120*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.63638*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.42522*8192), (uint16_t)(0.29290*8192), (uint16_t)(0.14932*8192),
63 (uint16_t)(0.27590*8192), (uint16_t)(0.38268*8192), (uint16_t)(0.36048*8192), (uint16_t)(0.32442*8192), (uint16_t)(0.27590*8192), (uint16_t)(0.21678*8192), (uint16_t)(0.14932*8192), (uint16_t)(0.07612*8192)
64 };
65
66
67
68 /*---------------------------------------------*/
69 /* Conversion table for fast clipping process */
70 /*---------------------------------------------*/
71
72 #if JD_TBLCLIP
73
74 #define BYTECLIP(v) Clip8[(unsigned int)(v) & 0x3FF]
75
76 static const uint8_t Clip8[1024] = {
77 /* 0..255 */
78 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
79 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
80 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
81 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
82 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
83 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
84 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
85 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
86 /* 256..511 */
87 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
88 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
89 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
90 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
91 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
92 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
93 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
94 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
95 /* -512..-257 */
96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 /* -256..-1 */
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
113 };
114
115 #else /* JD_TBLCLIP */
116
117 static uint8_t BYTECLIP (int val)
118 {
119 if (val < 0) return 0;
120 if (val > 255) return 255;
121 return (uint8_t)val;
122 }
123
124 #endif
125
126
127
128 /*-----------------------------------------------------------------------*/
129 /* Allocate a memory block from memory pool */
130 /*-----------------------------------------------------------------------*/
131
132 17 static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */
133 JDEC* jd, /* Pointer to the decompressor object */
134 size_t ndata /* Number of bytes to allocate */
135 )
136 {
137 17 char *rp = 0;
138
139
140 17 ndata = (ndata + 3u) & ~3u; /* Align block size to the word boundary */
141
142
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (jd->sz_pool >= ndata) {
143 17 jd->sz_pool -= ndata;
144 17 rp = (char*)jd->pool; /* Get start of available memory pool */
145 17 jd->pool = (void*)(rp + ndata); /* Allocate requierd bytes */
146 }
147
148 17 return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */
149 }
150
151
152
153
154 /*-----------------------------------------------------------------------*/
155 /* Create de-quantization and prescaling tables with a DQT segment */
156 /*-----------------------------------------------------------------------*/
157
158 2 static JRESULT create_qt_tbl ( /* 0:OK, !0:Failed */
159 JDEC* jd, /* Pointer to the decompressor object */
160 const uint8_t* data, /* Pointer to the quantizer tables */
161 size_t ndata /* Size of input data */
162 )
163 {
164 unsigned int zi;
165 int32_t *pb;
166
167
168
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 while (ndata) { /* Process all tables in the segment */
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */
170 2 ndata -= 65;
171 2 uint8_t d = *data++; /* Get table property */
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */
173 2 unsigned int i = d & 3; /* Get table ID */
174 2 pb = alloc_pool(jd, 64 * sizeof (int32_t));/* Allocate a memory block for the table */
175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!pb) return JDR_MEM1; /* Err: not enough memory */
176 2 jd->qttbl[i] = pb; /* Register the table */
177
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 2 times.
130 for (i = 0; i < 64; i++) { /* Load the table */
178 128 zi = Zig[i]; /* Zigzag-order to raster-order conversion */
179 128 pb[zi] = (int32_t)((uint32_t)*data++ * Ipsf[zi]); /* Apply scale factor of Arai algorithm to the de-quantizers */
180 }
181 }
182
183 2 return JDR_OK;
184 }
185
186
187
188
189 /*-----------------------------------------------------------------------*/
190 /* Create huffman code tables with a DHT segment */
191 /*-----------------------------------------------------------------------*/
192
193 4 static JRESULT create_huffman_tbl ( /* 0:OK, !0:Failed */
194 JDEC* jd, /* Pointer to the decompressor object */
195 const uint8_t* data, /* Pointer to the packed huffman tables */
196 size_t ndata /* Size of input data */
197 )
198 {
199 unsigned int i, j, b, cls, num;
200 size_t np;
201 uint8_t d, *pb, *pd;
202 uint16_t hc, *ph;
203
204
205
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 while (ndata) { /* Process all tables in the segment */
206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */
207 4 ndata -= 17;
208 4 d = *data++; /* Get table number and class */
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */
210 4 cls = d >> 4; num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */
211 4 pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!pb) return JDR_MEM1; /* Err: not enough memory */
213 4 jd->huffbits[num][cls] = pb;
214
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4 times.
68 for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */
215 64 np += (pb[i] = *data++); /* Get sum of code words for each code */
216 }
217 4 ph = alloc_pool(jd, np * sizeof (uint16_t));/* Allocate a memory block for the code word table */
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!ph) return JDR_MEM1; /* Err: not enough memory */
219 4 jd->huffcode[num][cls] = ph;
220 4 hc = 0;
221
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4 times.
68 for (j = i = 0; i < 16; i++) { /* Re-build huffman code word table */
222 64 b = pb[i];
223
2/2
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 64 times.
412 while (b--) ph[j++] = hc++;
224 64 hc <<= 1;
225 }
226
227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ndata < np) return JDR_FMT1; /* Err: wrong data size */
228 4 ndata -= np;
229 4 pd = alloc_pool(jd, np); /* Allocate a memory block for the decoded data */
230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!pd) return JDR_MEM1; /* Err: not enough memory */
231 4 jd->huffdata[num][cls] = pd;
232
2/2
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 4 times.
352 for (i = 0; i < np; i++) { /* Load decoded data corresponds to each code word */
233 348 d = *data++;
234
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
348 if (!cls && d > 11) return JDR_FMT1;
235 348 pd[i] = d;
236 }
237 #if JD_FASTDECODE == 2
238 { /* Create fast huffman decode table */
239 unsigned int span, td, ti;
240 uint16_t *tbl_ac = 0;
241 uint8_t *tbl_dc = 0;
242
243 if (cls) {
244 tbl_ac = alloc_pool(jd, HUFF_LEN * sizeof (uint16_t)); /* LUT for AC elements */
245 if (!tbl_ac) return JDR_MEM1; /* Err: not enough memory */
246 jd->hufflut_ac[num] = tbl_ac;
247 memset(tbl_ac, 0xFF, HUFF_LEN * sizeof (uint16_t)); /* Default value (0xFFFF: may be long code) */
248 } else {
249 tbl_dc = alloc_pool(jd, HUFF_LEN * sizeof (uint8_t)); /* LUT for AC elements */
250 if (!tbl_dc) return JDR_MEM1; /* Err: not enough memory */
251 jd->hufflut_dc[num] = tbl_dc;
252 memset(tbl_dc, 0xFF, HUFF_LEN * sizeof (uint8_t)); /* Default value (0xFF: may be long code) */
253 }
254 for (i = b = 0; b < HUFF_BIT; b++) { /* Create LUT */
255 for (j = pb[b]; j; j--) {
256 ti = ph[i] << (HUFF_BIT - 1 - b) & HUFF_MASK; /* Index of input pattern for the code */
257 if (cls) {
258 td = pd[i++] | ((b + 1) << 8); /* b15..b8: code length, b7..b0: zero run and data length */
259 for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_ac[ti++] = (uint16_t)td) ;
260 } else {
261 td = pd[i++] | ((b + 1) << 4); /* b7..b4: code length, b3..b0: data length */
262 for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_dc[ti++] = (uint8_t)td) ;
263 }
264 }
265 }
266 jd->longofs[num][cls] = i; /* Code table offset for long code */
267 }
268 #endif
269 }
270
271 4 return JDR_OK;
272 }
273
274
275
276
277 /*-----------------------------------------------------------------------*/
278 /* Extract a huffman decoded data from input stream */
279 /*-----------------------------------------------------------------------*/
280
281 58470 static int huffext ( /* >=0: decoded data, <0: error code */
282 JDEC* jd, /* Pointer to the decompressor object */
283 unsigned int id, /* Table ID (0:Y, 1:C) */
284 unsigned int cls /* Table class (0:DC, 1:AC) */
285 )
286 {
287 58470 size_t dc = jd->dctr;
288 58470 uint8_t *dp = jd->dptr;
289 58470 unsigned int d, flg = 0;
290
291 #if JD_FASTDECODE == 0
292 uint8_t bm, nd, bl;
293 const uint8_t *hb = jd->huffbits[id][cls]; /* Bit distribution table */
294 const uint16_t *hc = jd->huffcode[id][cls]; /* Code word table */
295 const uint8_t *hd = jd->huffdata[id][cls]; /* Data table */
296
297
298 bm = jd->dbit; /* Bit mask to extract */
299 d = 0; bl = 16; /* Max code length */
300 do {
301 if (!bm) { /* Next byte? */
302 if (!dc) { /* No input data is available, re-fill input buffer */
303 dp = jd->inbuf; /* Top of input buffer */
304 dc = jd->infunc(jd, dp, JD_SZBUF);
305 if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */
306 } else {
307 dp++; /* Next data ptr */
308 }
309 dc--; /* Decrement number of available bytes */
310 if (flg) { /* In flag sequence? */
311 flg = 0; /* Exit flag sequence */
312 if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
313 *dp = 0xFF; /* The flag is a data 0xFF */
314 } else {
315 if (*dp == 0xFF) { /* Is start of flag sequence? */
316 flg = 1; continue; /* Enter flag sequence, get trailing byte */
317 }
318 }
319 bm = 0x80; /* Read from MSB */
320 }
321 d <<= 1; /* Get a bit */
322 if (*dp & bm) d++;
323 bm >>= 1;
324
325 for (nd = *hb++; nd; nd--) { /* Search the code word in this bit length */
326 if (d == *hc++) { /* Matched? */
327 jd->dbit = bm; jd->dctr = dc; jd->dptr = dp;
328 return *hd; /* Return the decoded data */
329 }
330 hd++;
331 }
332 bl--;
333 } while (bl);
334
335 #else
336 const uint8_t *hb, *hd;
337 const uint16_t *hc;
338 58470 unsigned int nc, bl, wbit = jd->dbit % 32;
339 58470 uint32_t w = jd->wreg & ((1UL << wbit) - 1);
340
341
342
2/2
✓ Branch 0 taken 39836 times.
✓ Branch 1 taken 58470 times.
98306 while (wbit < 16) { /* Prepare 16 bits into the working register */
343
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 39803 times.
39836 if (jd->marker) {
344 33 d = 0xFF; /* Input stream has stalled for a marker. Generate stuff bits */
345 } else {
346
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 39726 times.
39803 if (!dc) { /* Buffer empty, re-fill input buffer */
347 77 dp = jd->inbuf; /* Top of input buffer */
348 77 dc = jd->infunc(jd, dp, JD_SZBUF);
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */
350 }
351 39803 d = *dp++; dc--;
352
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 39420 times.
39803 if (flg) { /* In flag sequence? */
353 383 flg = 0; /* Exit flag sequence */
354
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 338 times.
383 if (d != 0) jd->marker = (uint8_t)d; /* Not an escape of 0xFF but a marker */
355 383 d = 0xFF;
356 } else {
357
2/2
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 39037 times.
39420 if (d == 0xFF) { /* Is start of flag sequence? */
358 383 flg = 1; continue; /* Enter flag sequence, get trailing byte */
359 }
360 }
361 }
362 39453 w = w << 8 | d; /* Shift 8 bits in the working register */
363 39453 wbit += 8;
364 }
365 58470 jd->dctr = dc; jd->dptr = dp;
366 58470 jd->wreg = w;
367
368 #if JD_FASTDECODE == 2
369 /* Table serch for the short codes */
370 d = (unsigned int)(w >> (wbit - HUFF_BIT)); /* Short code as table index */
371 if (cls) { /* AC element */
372 d = jd->hufflut_ac[id][d]; /* Table decode */
373 if (d != 0xFFFF) { /* It is done if hit in short code */
374 jd->dbit = wbit - (d >> 8); /* Snip the code length */
375 return d & 0xFF; /* b7..0: zero run and following data bits */
376 }
377 } else { /* DC element */
378 d = jd->hufflut_dc[id][d]; /* Table decode */
379 if (d != 0xFF) { /* It is done if hit in short code */
380 jd->dbit = wbit - (d >> 4); /* Snip the code length */
381 return d & 0xF; /* b3..0: following data bits */
382 }
383 }
384
385 /* Incremental serch for the codes longer than HUFF_BIT */
386 hb = jd->huffbits[id][cls] + HUFF_BIT; /* Bit distribution table */
387 hc = jd->huffcode[id][cls] + jd->longofs[id][cls]; /* Code word table */
388 hd = jd->huffdata[id][cls] + jd->longofs[id][cls]; /* Data table */
389 bl = HUFF_BIT + 1;
390 #else
391 /* Incremental serch for all codes */
392 58470 hb = jd->huffbits[id][cls]; /* Bit distribution table */
393 58470 hc = jd->huffcode[id][cls]; /* Code word table */
394 58470 hd = jd->huffdata[id][cls]; /* Data table */
395 58470 bl = 1;
396 #endif
397
1/2
✓ Branch 0 taken 211543 times.
✗ Branch 1 not taken.
211543 for ( ; bl <= 16; bl++) { /* Incremental search */
398 211543 nc = *hb++;
399
2/2
✓ Branch 0 taken 152370 times.
✓ Branch 1 taken 59173 times.
211543 if (nc) {
400 152370 d = w >> (wbit - bl);
401 do { /* Search the code word in this bit length */
402
2/2
✓ Branch 0 taken 58470 times.
✓ Branch 1 taken 248246 times.
306716 if (d == *hc++) { /* Matched? */
403 58470 jd->dbit = (uint8_t)(wbit - bl); /* Snip the huffman code */
404 58470 return *hd; /* Return the decoded data */
405 }
406 248246 hd++;
407
2/2
✓ Branch 0 taken 154346 times.
✓ Branch 1 taken 93900 times.
248246 } while (--nc);
408 }
409 }
410 #endif
411
412 return 0 - (int)JDR_FMT1; /* Err: code not found (may be collapted data) */
413 }
414
415
416
417
418 /*-----------------------------------------------------------------------*/
419 /* Extract N bits from input stream */
420 /*-----------------------------------------------------------------------*/
421
422 43620 static int bitext ( /* >=0: extracted data, <0: error code */
423 JDEC* jd, /* Pointer to the decompressor object */
424 unsigned int nbit /* Number of bits to extract (1 to 16) */
425 )
426 {
427 43620 size_t dc = jd->dctr;
428 43620 uint8_t *dp = jd->dptr;
429 43620 unsigned int d, flg = 0;
430
431 #if JD_FASTDECODE == 0
432 uint8_t mbit = jd->dbit;
433
434 d = 0;
435 do {
436 if (!mbit) { /* Next byte? */
437 if (!dc) { /* No input data is available, re-fill input buffer */
438 dp = jd->inbuf; /* Top of input buffer */
439 dc = jd->infunc(jd, dp, JD_SZBUF);
440 if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */
441 } else {
442 dp++; /* Next data ptr */
443 }
444 dc--; /* Decrement number of available bytes */
445 if (flg) { /* In flag sequence? */
446 flg = 0; /* Exit flag sequence */
447 if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
448 *dp = 0xFF; /* The flag is a data 0xFF */
449 } else {
450 if (*dp == 0xFF) { /* Is start of flag sequence? */
451 flg = 1; continue; /* Enter flag sequence */
452 }
453 }
454 mbit = 0x80; /* Read from MSB */
455 }
456 d <<= 1; /* Get a bit */
457 if (*dp & mbit) d |= 1;
458 mbit >>= 1;
459 nbit--;
460 } while (nbit);
461
462 jd->dbit = mbit; jd->dctr = dc; jd->dptr = dp;
463 return (int)d;
464
465 #else
466 43620 unsigned int wbit = jd->dbit % 32;
467 43620 uint32_t w = jd->wreg & ((1UL << wbit) - 1);
468
469
470
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 43620 times.
43750 while (wbit < nbit) { /* Prepare nbit bits into the working register */
471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
130 if (jd->marker) {
472 d = 0xFF; /* Input stream stalled, generate stuff bits */
473 } else {
474
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 129 times.
130 if (!dc) { /* Buffer empty, re-fill input buffer */
475 1 dp = jd->inbuf; /* Top of input buffer */
476 1 dc = jd->infunc(jd, dp, JD_SZBUF);
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */
478 }
479 130 d = *dp++; dc--;
480
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 126 times.
130 if (flg) { /* In flag sequence? */
481 4 flg = 0; /* Exit flag sequence */
482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (d != 0) jd->marker = (uint8_t)d; /* Not an escape of 0xFF but a marker */
483 4 d = 0xFF;
484 } else {
485
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 122 times.
126 if (d == 0xFF) { /* Is start of flag sequence? */
486 4 flg = 1; continue; /* Enter flag sequence, get trailing byte */
487 }
488 }
489 }
490 126 w = w << 8 | d; /* Get 8 bits into the working register */
491 126 wbit += 8;
492 }
493 43620 jd->wreg = w; jd->dbit = (uint8_t)(wbit - nbit);
494 43620 jd->dctr = dc; jd->dptr = dp;
495
496 43620 return (int)(w >> ((wbit - nbit) % 32));
497 #endif
498 }
499
500
501
502
503 /*-----------------------------------------------------------------------*/
504 /* Process restart interval */
505 /*-----------------------------------------------------------------------*/
506
507 44 static JRESULT restart (
508 JDEC* jd, /* Pointer to the decompressor object */
509 uint16_t rstn /* Expected restert sequense number */
510 )
511 {
512 unsigned int i;
513 44 uint8_t *dp = jd->dptr;
514 44 size_t dc = jd->dctr;
515
516 #if JD_FASTDECODE == 0
517 uint16_t d = 0;
518
519 /* Get two bytes from the input stream */
520 for (i = 0; i < 2; i++) {
521 if (!dc) { /* No input data is available, re-fill input buffer */
522 dp = jd->inbuf;
523 dc = jd->infunc(jd, dp, JD_SZBUF);
524 if (!dc) return JDR_INP;
525 } else {
526 dp++;
527 }
528 dc--;
529 d = d << 8 | *dp; /* Get a byte */
530 }
531 jd->dptr = dp; jd->dctr = dc; jd->dbit = 0;
532
533 /* Check the marker */
534 if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) {
535 return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */
536 }
537
538 #else
539 uint16_t marker;
540
541
542
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (jd->marker) { /* Generate a maker if it has been detected */
543 44 marker = 0xFF00 | jd->marker;
544 44 jd->marker = 0;
545 } else {
546 marker = 0;
547 for (i = 0; i < 2; i++) { /* Get a restart marker */
548 if (!dc) { /* No input data is available, re-fill input buffer */
549 dp = jd->inbuf;
550 dc = jd->infunc(jd, dp, JD_SZBUF);
551 if (!dc) return JDR_INP;
552 }
553 marker = (marker << 8) | *dp++; /* Get a byte */
554 dc--;
555 }
556 jd->dptr = dp; jd->dctr = dc;
557 }
558
559 /* Check the marker */
560
2/4
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
44 if ((marker & 0xFFD8) != 0xFFD0 || (marker & 7) != (rstn & 7)) {
561 return JDR_FMT1; /* Err: expected RSTn marker was not detected (may be collapted data) */
562 }
563
564 44 jd->dbit = 0; /* Discard stuff bits */
565 #endif
566
567 44 jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Reset DC offset */
568 44 return JDR_OK;
569 }
570
571
572
573
574 /*-----------------------------------------------------------------------*/
575 /* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */
576 /*-----------------------------------------------------------------------*/
577
578 2795 static void block_idct (
579 int32_t* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */
580 jd_yuv_t* dst /* Pointer to the destination to store the block as byte array */
581 )
582 {
583 2795 const int32_t M13 = (int32_t)(1.41421*4096), M2 = (int32_t)(1.08239*4096), M4 = (int32_t)(2.61313*4096), M5 = (int32_t)(1.84776*4096);
584 int32_t v0, v1, v2, v3, v4, v5, v6, v7;
585 int32_t t10, t11, t12, t13;
586 int i;
587
588 /* Process columns */
589
2/2
✓ Branch 0 taken 22360 times.
✓ Branch 1 taken 2795 times.
25155 for (i = 0; i < 8; i++) {
590 22360 v0 = src[8 * 0]; /* Get even elements */
591 22360 v1 = src[8 * 2];
592 22360 v2 = src[8 * 4];
593 22360 v3 = src[8 * 6];
594
595 22360 t10 = v0 + v2; /* Process the even elements */
596 22360 t12 = v0 - v2;
597 22360 t11 = (v1 - v3) * M13 >> 12;
598 22360 v3 += v1;
599 22360 t11 -= v3;
600 22360 v0 = t10 + v3;
601 22360 v3 = t10 - v3;
602 22360 v1 = t11 + t12;
603 22360 v2 = t12 - t11;
604
605 22360 v4 = src[8 * 7]; /* Get odd elements */
606 22360 v5 = src[8 * 1];
607 22360 v6 = src[8 * 5];
608 22360 v7 = src[8 * 3];
609
610 22360 t10 = v5 - v4; /* Process the odd elements */
611 22360 t11 = v5 + v4;
612 22360 t12 = v6 - v7;
613 22360 v7 += v6;
614 22360 v5 = (t11 - v7) * M13 >> 12;
615 22360 v7 += t11;
616 22360 t13 = (t10 + t12) * M5 >> 12;
617 22360 v4 = t13 - (t10 * M2 >> 12);
618 22360 v6 = t13 - (t12 * M4 >> 12) - v7;
619 22360 v5 -= v6;
620 22360 v4 -= v5;
621
622 22360 src[8 * 0] = v0 + v7; /* Write-back transformed values */
623 22360 src[8 * 7] = v0 - v7;
624 22360 src[8 * 1] = v1 + v6;
625 22360 src[8 * 6] = v1 - v6;
626 22360 src[8 * 2] = v2 + v5;
627 22360 src[8 * 5] = v2 - v5;
628 22360 src[8 * 3] = v3 + v4;
629 22360 src[8 * 4] = v3 - v4;
630
631 22360 src++; /* Next column */
632 }
633
634 /* Process rows */
635 2795 src -= 8;
636
2/2
✓ Branch 0 taken 22360 times.
✓ Branch 1 taken 2795 times.
25155 for (i = 0; i < 8; i++) {
637 22360 v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */
638 22360 v1 = src[2];
639 22360 v2 = src[4];
640 22360 v3 = src[6];
641
642 22360 t10 = v0 + v2; /* Process the even elements */
643 22360 t12 = v0 - v2;
644 22360 t11 = (v1 - v3) * M13 >> 12;
645 22360 v3 += v1;
646 22360 t11 -= v3;
647 22360 v0 = t10 + v3;
648 22360 v3 = t10 - v3;
649 22360 v1 = t11 + t12;
650 22360 v2 = t12 - t11;
651
652 22360 v4 = src[7]; /* Get odd elements */
653 22360 v5 = src[1];
654 22360 v6 = src[5];
655 22360 v7 = src[3];
656
657 22360 t10 = v5 - v4; /* Process the odd elements */
658 22360 t11 = v5 + v4;
659 22360 t12 = v6 - v7;
660 22360 v7 += v6;
661 22360 v5 = (t11 - v7) * M13 >> 12;
662 22360 v7 += t11;
663 22360 t13 = (t10 + t12) * M5 >> 12;
664 22360 v4 = t13 - (t10 * M2 >> 12);
665 22360 v6 = t13 - (t12 * M4 >> 12) - v7;
666 22360 v5 -= v6;
667 22360 v4 -= v5;
668
669 /* Descale the transformed values 8 bits and output a row */
670 #if JD_FASTDECODE >= 1
671 22360 dst[0] = (int16_t)((v0 + v7) >> 8);
672 22360 dst[7] = (int16_t)((v0 - v7) >> 8);
673 22360 dst[1] = (int16_t)((v1 + v6) >> 8);
674 22360 dst[6] = (int16_t)((v1 - v6) >> 8);
675 22360 dst[2] = (int16_t)((v2 + v5) >> 8);
676 22360 dst[5] = (int16_t)((v2 - v5) >> 8);
677 22360 dst[3] = (int16_t)((v3 + v4) >> 8);
678 22360 dst[4] = (int16_t)((v3 - v4) >> 8);
679 #else
680 dst[0] = BYTECLIP((v0 + v7) >> 8);
681 dst[7] = BYTECLIP((v0 - v7) >> 8);
682 dst[1] = BYTECLIP((v1 + v6) >> 8);
683 dst[6] = BYTECLIP((v1 - v6) >> 8);
684 dst[2] = BYTECLIP((v2 + v5) >> 8);
685 dst[5] = BYTECLIP((v2 - v5) >> 8);
686 dst[3] = BYTECLIP((v3 + v4) >> 8);
687 dst[4] = BYTECLIP((v3 - v4) >> 8);
688 #endif
689
690 22360 dst += 8; src += 8; /* Next row */
691 }
692 2795 }
693
694
695
696
697 /*-----------------------------------------------------------------------*/
698 /* Load all blocks in an MCU into working buffer */
699 /*-----------------------------------------------------------------------*/
700
701 1530 static JRESULT mcu_load (
702 JDEC* jd /* Pointer to the decompressor object */
703 )
704 {
705 1530 int32_t *tmp = (int32_t*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */
706 int d, e;
707 unsigned int blk, nby, i, bc, z, id;
708 jd_yuv_t *bp;
709 const int32_t *dqf;
710
711
712 1530 nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */
713 1530 bp = jd->mcubuf; /* Pointer to the first block of MCU */
714
715
2/2
✓ Branch 0 taken 9180 times.
✓ Branch 1 taken 1530 times.
10710 for (blk = 0; blk < nby + 2; blk++) { /* Get nby Y blocks and two C blocks */
716
2/2
✓ Branch 0 taken 3060 times.
✓ Branch 1 taken 6120 times.
9180 unsigned int cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */
717
718
3/4
✓ Branch 0 taken 3060 times.
✓ Branch 1 taken 6120 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3060 times.
9180 if (cmp && jd->ncomp != 3) { /* Clear C blocks if not exist (monochrome image) */
719 for (i = 0; i < 64; bp[i++] = 128) ;
720
721 } else { /* Load Y/C blocks from input stream */
722 9180 id = cmp ? 1 : 0; /* Huffman table ID of this component */
723
724 /* Extract a DC element from input stream */
725 9180 d = huffext(jd, id, 0); /* Extract a huffman coded data (bit length) */
726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input */
727 9180 bc = (unsigned int)d;
728 9180 d = jd->dcv[cmp]; /* DC value of previous block */
729
2/2
✓ Branch 0 taken 3550 times.
✓ Branch 1 taken 5630 times.
9180 if (bc) { /* If there is any difference from previous block */
730 3550 e = bitext(jd, bc); /* Extract data bits */
731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3550 times.
3550 if (e < 0) return (JRESULT)(0 - e); /* Err: input */
732 3550 bc = 1 << (bc - 1); /* MSB position */
733
2/2
✓ Branch 0 taken 1798 times.
✓ Branch 1 taken 1752 times.
3550 if (!((unsigned int)e & bc)) e -= (int)(bc << 1) - 1; /* Restore negative value if needed */
734 3550 d += e; /* Get current value */
735 3550 jd->dcv[cmp] = (int16_t)d; /* Save current DC value for next block */
736 }
737 9180 dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */
738 9180 tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */
739
740 /* Extract following 63 AC elements from input stream */
741 9180 memset(&tmp[1], 0, 63 * sizeof (int32_t)); /* Initialize all AC elements */
742 9180 z = 1; /* Top of the AC elements (in zigzag-order) */
743 do {
744 49290 d = huffext(jd, id, 1); /* Extract a huffman coded value (zero runs and bit length) */
745
2/2
✓ Branch 0 taken 9178 times.
✓ Branch 1 taken 40112 times.
49290 if (d == 0) break; /* EOB? */
746
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40112 times.
40112 if (d < 0) return (JRESULT)(0 - d); /* Err: invalid code or input error */
747 40112 bc = (unsigned int)d;
748 40112 z += bc >> 4; /* Skip leading zero run */
749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40112 times.
40112 if (z >= 64) return JDR_FMT1; /* Too long zero run */
750
2/2
✓ Branch 0 taken 40070 times.
✓ Branch 1 taken 42 times.
40112 if (bc &= 0x0F) { /* Bit length? */
751 40070 d = bitext(jd, bc); /* Extract data bits */
752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40070 times.
40070 if (d < 0) return (JRESULT)(0 - d); /* Err: input device */
753 40070 bc = 1 << (bc - 1); /* MSB position */
754
2/2
✓ Branch 0 taken 20256 times.
✓ Branch 1 taken 19814 times.
40070 if (!((unsigned int)d & bc)) d -= (int)(bc << 1) - 1; /* Restore negative value if needed */
755 40070 i = Zig[z]; /* Get raster-order index */
756 40070 tmp[i] = d * dqf[i] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */
757 }
758
2/2
✓ Branch 0 taken 40110 times.
✓ Branch 1 taken 2 times.
40112 } while (++z < 64); /* Next AC element */
759
760 if (JD_FORMAT != 2 || !cmp) { /* C components may not be processed if in grayscale output */
761
3/4
✓ Branch 0 taken 2795 times.
✓ Branch 1 taken 6385 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2795 times.
9180 if (z == 1 || (JD_USE_SCALE && jd->scale == 3)) { /* If no AC element or scale ratio is 1/8, IDCT can be ommited and the block is filled with DC value */
762 6385 d = (jd_yuv_t)((*tmp / 256) + 128);
763 6385 if (JD_FASTDECODE >= 1) {
764
2/2
✓ Branch 0 taken 408640 times.
✓ Branch 1 taken 6385 times.
415025 for (i = 0; i < 64; bp[i++] = (jd_yuv_t)d) ;
765 } else {
766 memset(bp, d, 64);
767 }
768 } else {
769 2795 block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */
770 }
771 }
772 }
773
774 9180 bp += 64; /* Next block */
775 }
776
777 1530 return JDR_OK; /* All blocks have been loaded successfully */
778 }
779
780
781
782
783 /*-----------------------------------------------------------------------*/
784 /* Output an MCU: Convert YCrCb to RGB and output it in RGB form */
785 /*-----------------------------------------------------------------------*/
786
787 1530 static JRESULT mcu_output (
788 JDEC* jd, /* Pointer to the decompressor object */
789 int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */
790 unsigned int x, /* MCU location in the image */
791 unsigned int y /* MCU location in the image */
792 )
793 {
794 1530 const int CVACC = (sizeof (int) > 2) ? 1024 : 128; /* Adaptive accuracy for both 16-/32-bit systems */
795 unsigned int ix, iy, mx, my, rx, ry;
796 int yy, cb, cr;
797 jd_yuv_t *py, *pc;
798 uint8_t *pix;
799 JRECT rect;
800
801
802 1530 mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */
803
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1485 times.
1530 rx = (x + mx <= jd->width) ? mx : jd->width - x; /* Output rectangular size (it may be clipped at right/bottom end of image) */
804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1530 times.
1530 ry = (y + my <= jd->height) ? my : jd->height - y;
805 if (JD_USE_SCALE) {
806 1530 rx >>= jd->scale; ry >>= jd->scale;
807
2/4
✓ Branch 0 taken 1530 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1530 times.
1530 if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */
808 1530 x >>= jd->scale; y >>= jd->scale;
809 }
810 1530 rect.left = (uint16_t)x; rect.right = (uint16_t)(x + rx - 1); /* Rectangular area in the frame buffer */
811 1530 rect.top = (uint16_t)y; rect.bottom = (uint16_t)(y + ry - 1);
812
813
814
1/2
✓ Branch 0 taken 1530 times.
✗ Branch 1 not taken.
1530 if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */
815 1530 pix = (uint8_t*)jd->workbuf;
816
817 if (JD_FORMAT != 2) { /* RGB output (build an RGB MCU from Y/C component) */
818
2/2
✓ Branch 0 taken 24480 times.
✓ Branch 1 taken 1530 times.
26010 for (iy = 0; iy < my; iy++) {
819 24480 pc = py = jd->mcubuf;
820
1/2
✓ Branch 0 taken 24480 times.
✗ Branch 1 not taken.
24480 if (my == 16) { /* Double block height? */
821 24480 pc += 64 * 4 + (iy >> 1) * 8;
822
2/2
✓ Branch 0 taken 12240 times.
✓ Branch 1 taken 12240 times.
24480 if (iy >= 8) py += 64;
823 } else { /* Single block height */
824 pc += mx * 8 + iy * 8;
825 }
826 24480 py += iy * 8;
827
2/2
✓ Branch 0 taken 391680 times.
✓ Branch 1 taken 24480 times.
416160 for (ix = 0; ix < mx; ix++) {
828 391680 cb = pc[0] - 128; /* Get Cb/Cr component and remove offset */
829 391680 cr = pc[64] - 128;
830
1/2
✓ Branch 0 taken 391680 times.
✗ Branch 1 not taken.
391680 if (mx == 16) { /* Double block width? */
831
2/2
✓ Branch 0 taken 24480 times.
✓ Branch 1 taken 367200 times.
391680 if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */
832 391680 pc += ix & 1; /* Step forward chroma pointer every two pixels */
833 } else { /* Single block width */
834 pc++; /* Step forward chroma pointer every pixel */
835 }
836 391680 yy = *py++; /* Get Y component */
837 391680 *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr) / CVACC);
838 391680 *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC);
839 391680 *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb) / CVACC);
840 }
841 }
842 } else { /* Monochrome output (build a grayscale MCU from Y comopnent) */
843 for (iy = 0; iy < my; iy++) {
844 py = jd->mcubuf + iy * 8;
845 if (my == 16) { /* Double block height? */
846 if (iy >= 8) py += 64;
847 }
848 for (ix = 0; ix < mx; ix++) {
849 if (mx == 16) { /* Double block width? */
850 if (ix == 8) py += 64 - 8; /* Jump to next block if double block height */
851 }
852 *pix++ = (uint8_t)*py++; /* Get and store a Y value as grayscale */
853 }
854 }
855 }
856
857 /* Descale the MCU rectangular if needed */
858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1530 times.
1530 if (JD_USE_SCALE && jd->scale) {
859 unsigned int i, j, r, g, b, s, w, a;
860 uint8_t *op;
861
862 /* Get averaged RGB value of each square correcponds to a pixel */
863 s = jd->scale * 2; /* Number of shifts for averaging */
864 w = 1 << jd->scale; /* Width of square */
865 a = (mx - w) * (JD_FORMAT != 2 ? 3 : 1); /* Bytes to skip for next line in the square */
866 op = (uint8_t*)jd->workbuf;
867 for (iy = 0; iy < my; iy += w) {
868 for (ix = 0; ix < mx; ix += w) {
869 pix = (uint8_t*)jd->workbuf + (iy * mx + ix) * (JD_FORMAT != 2 ? 3 : 1);
870 r = g = b = 0;
871 for (i = 0; i < w; i++) { /* Accumulate RGB value in the square */
872 for (j = 0; j < w; j++) {
873 r += *pix++; /* Accumulate R or Y (monochrome output) */
874 if (JD_FORMAT != 2) { /* RGB output? */
875 g += *pix++; /* Accumulate G */
876 b += *pix++; /* Accumulate B */
877 }
878 }
879 pix += a;
880 } /* Put the averaged pixel value */
881 *op++ = (uint8_t)(r >> s); /* Put R or Y (monochrome output) */
882 if (JD_FORMAT != 2) { /* RGB output? */
883 *op++ = (uint8_t)(g >> s); /* Put G */
884 *op++ = (uint8_t)(b >> s); /* Put B */
885 }
886 }
887 }
888 }
889
890 } else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */
891
892 /* Build a 1/8 descaled RGB MCU from discrete comopnents */
893 pix = (uint8_t*)jd->workbuf;
894 pc = jd->mcubuf + mx * my;
895 cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */
896 cr = pc[64] - 128;
897 for (iy = 0; iy < my; iy += 8) {
898 py = jd->mcubuf;
899 if (iy == 8) py += 64 * 2;
900 for (ix = 0; ix < mx; ix += 8) {
901 yy = *py; /* Get Y component */
902 py += 64;
903 if (JD_FORMAT != 2) {
904 *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr / CVACC));
905 *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC);
906 *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb / CVACC));
907 } else {
908 *pix++ = (uint8_t)yy;
909 }
910 }
911 }
912 }
913
914 /* Squeeze up pixel table if a part of MCU is to be truncated */
915 1530 mx >>= jd->scale;
916
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1485 times.
1530 if (rx < mx) { /* Is the MCU spans rigit edge? */
917 uint8_t *s, *d;
918 unsigned int i, j;
919
920 45 s = d = (uint8_t*)jd->workbuf;
921
2/2
✓ Branch 0 taken 720 times.
✓ Branch 1 taken 45 times.
765 for (i = 0; i < ry; i++) {
922
2/2
✓ Branch 0 taken 8640 times.
✓ Branch 1 taken 720 times.
9360 for (j = 0; j < rx; j++) { /* Copy effective pixels */
923 8640 *d++ = *s++;
924 if (JD_FORMAT != 2) {
925 8640 *d++ = *s++;
926 8640 *d++ = *s++;
927 }
928 }
929 720 s += (mx - rx) * (JD_FORMAT != 2 ? 3 : 1); /* Skip truncated pixels */
930 }
931 }
932
933 /* Convert RGB888 to RGB565 if needed */
934 if (JD_FORMAT == 1) {
935 uint8_t *s = (uint8_t*)jd->workbuf;
936 uint16_t *d = (uint16_t*)s;
937 unsigned int n = rx * ry;
938
939 do {
940 uint16_t w = (*s++ & 0xF8) << 8; /* RRRRR----------- */
941 w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */
942 w |= *s++ >> 3; /* -----------BBBBB */
943 *d++ = w;
944 } while (--n);
945 }
946
947 /* Output the rectangular */
948 1530 return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR;
949 }
950
951
952
953
954 /*-----------------------------------------------------------------------*/
955 /* Analyze the JPEG image and Initialize decompressor object */
956 /*-----------------------------------------------------------------------*/
957
958 #define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t*)(ptr))<<8)|(uint16_t)*(uint8_t*)((ptr)+1))
959
960
961 1 JRESULT jd_prepare (
962 JDEC* jd, /* Blank decompressor object */
963 size_t (*infunc)(JDEC*, uint8_t*, size_t), /* JPEG strem input function */
964 void* pool, /* Working buffer for the decompression session */
965 size_t sz_pool, /* Size of working buffer */
966 void* dev /* I/O device identifier for the session */
967 )
968 {
969 uint8_t *seg, b;
970 uint16_t marker;
971 unsigned int n, i, ofs;
972 JRESULT rc;
973
974
975 1 memset(jd, 0, sizeof (JDEC)); /* Clear decompression object (this might be a problem if machine's null pointer is not all bits zero) */
976 1 jd->pool = pool; /* Work memroy */
977 1 jd->sz_pool = sz_pool; /* Size of given work memory */
978 1 jd->infunc = infunc; /* Stream input function */
979 1 jd->device = dev; /* I/O device identifier */
980
981 1 jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */
982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!seg) return JDR_MEM1;
983
984 1 ofs = marker = 0; /* Find SOI marker */
985 do {
986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (jd->infunc(jd, seg, 1) != 1) return JDR_INP; /* Err: SOI was not detected */
987 2 ofs++;
988 2 marker = marker << 8 | seg[0];
989
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 } while (marker != 0xFFD8);
990
991 11 for (;;) { /* Parse JPEG segments */
992 /* Get a JPEG marker */
993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (jd->infunc(jd, seg, 4) != 4) return JDR_INP;
994 12 marker = LDB_WORD(seg); /* Marker */
995 12 size_t len = LDB_WORD(seg + 2); /* Length field */
996
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (len <= 2 || (marker >> 8) != 0xFF) return JDR_FMT1;
997 12 len -= 2; /* Segent content size */
998 12 ofs += 4 + len; /* Number of bytes loaded */
999
1000
6/7
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
12 switch (marker & 0xFF) {
1001 1 case 0xC0: /* SOF0 (baseline JPEG) */
1002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len > JD_SZBUF) return JDR_MEM2;
1003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */
1004
1005 1 jd->width = LDB_WORD(&seg[3]); /* Image width in unit of pixel */
1006 1 jd->height = LDB_WORD(&seg[1]); /* Image height in unit of pixel */
1007 1 jd->ncomp = seg[5]; /* Number of color components */
1008
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (jd->ncomp != 3 && jd->ncomp != 1) return JDR_FMT3; /* Err: Supports only Grayscale and Y/Cb/Cr */
1009
1010 /* Check each image component */
1011
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (i = 0; i < jd->ncomp; i++) {
1012 3 b = seg[7 + 3 * i]; /* Get sampling factor */
1013
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (i == 0) { /* Y component */
1014
2/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (b != 0x11 && b != 0x22 && b != 0x21) { /* Check sampling factor */
1015 return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */
1016 }
1017 1 jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */
1018 } else { /* Cb/Cr component */
1019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cb/Cr must be 1 */
1020 }
1021 3 jd->qtid[i] = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */
1022
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (jd->qtid[i] > 3) return JDR_FMT3; /* Err: Invalid ID */
1023 }
1024 1 break;
1025
1026 1 case 0xDD: /* DRI - Define Restart Interval */
1027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len > JD_SZBUF) return JDR_MEM2;
1028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */
1029
1030 1 jd->nrst = LDB_WORD(seg); /* Get restart interval (MCUs) */
1031 1 break;
1032
1033 4 case 0xC4: /* DHT - Define Huffman Tables */
1034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (len > JD_SZBUF) return JDR_MEM2;
1035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */
1036
1037 4 rc = create_huffman_tbl(jd, seg, len); /* Create huffman tables */
1038
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (rc) return rc;
1039 4 break;
1040
1041 2 case 0xDB: /* DQT - Define Quaitizer Tables */
1042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (len > JD_SZBUF) return JDR_MEM2;
1043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */
1044
1045 2 rc = create_qt_tbl(jd, seg, len); /* Create de-quantizer tables */
1046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (rc) return rc;
1047 2 break;
1048
1049 1 case 0xDA: /* SOS - Start of Scan */
1050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len > JD_SZBUF) return JDR_MEM2;
1051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (jd->infunc(jd, seg, len) != len) return JDR_INP; /* Load segment data */
1052
1053
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!jd->width || !jd->height) return JDR_FMT1; /* Err: Invalid image size */
1054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (seg[0] != jd->ncomp) return JDR_FMT3; /* Err: Wrong color components */
1055
1056 /* Check if all tables corresponding to each components have been loaded */
1057
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (i = 0; i < jd->ncomp; i++) {
1058 3 b = seg[2 + 2 * i]; /* Get huffman table ID */
1059
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */
1060 3 n = i ? 1 : 0; /* Component class */
1061
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (!jd->huffbits[n][0] || !jd->huffbits[n][1]) { /* Check huffman table for this component */
1062 return JDR_FMT1; /* Err: Nnot loaded */
1063 }
1064
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!jd->qttbl[jd->qtid[i]]) { /* Check dequantizer table for this component */
1065 return JDR_FMT1; /* Err: Not loaded */
1066 }
1067 }
1068
1069 /* Allocate working buffer for MCU and pixel output */
1070 1 n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */
1071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */
1072 1 len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */
1073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */
1074 1 jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */
1075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */
1076 1 jd->mcubuf = alloc_pool(jd, (n + 2) * 64 * sizeof (jd_yuv_t)); /* Allocate MCU working buffer */
1077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */
1078
1079 /* Align stream read offset to JD_SZBUF */
1080
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ofs %= JD_SZBUF) {
1081 1 jd->dctr = jd->infunc(jd, seg + ofs, (size_t)(JD_SZBUF - ofs));
1082 }
1083 1 jd->dptr = seg + ofs - (JD_FASTDECODE ? 0 : 1);
1084
1085 1 return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */
1086
1087 case 0xC1: /* SOF1 */
1088 case 0xC2: /* SOF2 */
1089 case 0xC3: /* SOF3 */
1090 case 0xC5: /* SOF5 */
1091 case 0xC6: /* SOF6 */
1092 case 0xC7: /* SOF7 */
1093 case 0xC9: /* SOF9 */
1094 case 0xCA: /* SOF10 */
1095 case 0xCB: /* SOF11 */
1096 case 0xCD: /* SOF13 */
1097 case 0xCE: /* SOF14 */
1098 case 0xCF: /* SOF15 */
1099 case 0xD9: /* EOI */
1100 return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */
1101
1102 3 default: /* Unknown segment (comment, exif or etc..) */
1103 /* Skip segment data (null pointer specifies to remove data from the stream) */
1104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (jd->infunc(jd, 0, len) != len) return JDR_INP;
1105 }
1106 }
1107 }
1108
1109
1110
1111
1112 /*-----------------------------------------------------------------------*/
1113 /* Start to decompress the JPEG picture */
1114 /*-----------------------------------------------------------------------*/
1115
1116 1 JRESULT jd_decomp (
1117 JDEC* jd, /* Initialized decompression object */
1118 int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */
1119 uint8_t scale /* Output de-scaling factor (0 to 3) */
1120 )
1121 {
1122 unsigned int x, y, mx, my;
1123 uint16_t rst, rsc;
1124 JRESULT rc;
1125
1126
1127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR;
1128 1 jd->scale = scale;
1129
1130 1 mx = jd->msx * 8; my = jd->msy * 8; /* Size of the MCU (pixel) */
1131
1132 1 jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */
1133 1 rst = rsc = 0;
1134
1135 1 rc = JDR_OK;
1136
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1 times.
46 for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */
1137
2/2
✓ Branch 0 taken 1530 times.
✓ Branch 1 taken 45 times.
1575 for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */
1138
3/4
✓ Branch 0 taken 1530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 1486 times.
1530 if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */
1139 44 rc = restart(jd, rsc++);
1140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (rc != JDR_OK) return rc;
1141 44 rst = 1;
1142 }
1143 1530 rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream, dequantize and apply IDCT) */
1144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1530 times.
1530 if (rc != JDR_OK) return rc;
1145 1530 rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (YCbCr to RGB, scaling and output) */
1146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1530 times.
1530 if (rc != JDR_OK) return rc;
1147 }
1148 }
1149
1150 1 return rc;
1151 }
1152