| rev |
line source |
|
nengel@0
|
1 /*
|
|
nengel@0
|
2 * Small jpeg decoder library
|
|
nengel@0
|
3 *
|
|
nengel@0
|
4 * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
|
|
nengel@0
|
5 * All rights reserved.
|
|
nengel@0
|
6 * Redistribution and use in source and binary forms, with or without
|
|
nengel@0
|
7 * modification, are permitted provided that the following conditions are met:
|
|
nengel@0
|
8 *
|
|
nengel@0
|
9 * - Redistributions of source code must retain the above copyright notice,
|
|
nengel@0
|
10 * this list of conditions and the following disclaimer.
|
|
nengel@0
|
11 *
|
|
nengel@0
|
12 * - Redistributions in binary form must reproduce the above copyright notice,
|
|
nengel@0
|
13 * this list of conditions and the following disclaimer in the documentation
|
|
nengel@0
|
14 * and/or other materials provided with the distribution.
|
|
nengel@0
|
15 *
|
|
nengel@0
|
16 * - Neither the name of the author nor the names of its contributors may be
|
|
nengel@0
|
17 * used to endorse or promote products derived from this software without
|
|
nengel@0
|
18 * specific prior written permission.
|
|
nengel@0
|
19 *
|
|
nengel@0
|
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
nengel@0
|
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
nengel@0
|
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
nengel@0
|
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
nengel@0
|
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
nengel@0
|
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
nengel@0
|
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
nengel@0
|
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
nengel@0
|
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
nengel@0
|
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
nengel@0
|
30 * POSSIBILITY OF SUCH DAMAGE.
|
|
nengel@0
|
31 *
|
|
nengel@0
|
32 */
|
|
nengel@0
|
33
|
|
nengel@0
|
34 #include <stdio.h>
|
|
nengel@0
|
35 #include <stdlib.h>
|
|
nengel@0
|
36 #include <string.h>
|
|
nengel@0
|
37 #include <stdint.h>
|
|
nengel@0
|
38 #include <errno.h>
|
|
nengel@0
|
39
|
|
nengel@0
|
40 #include "tinyjpeg.h"
|
|
nengel@0
|
41 #include "tinyjpeg-internal.h"
|
|
nengel@0
|
42
|
|
nengel@0
|
43 /* Global variable to return the last error found while deconding */
|
|
nengel@0
|
44 char error_string[256];
|
|
nengel@0
|
45
|
|
nengel@0
|
46 static const unsigned char zigzag[64] =
|
|
nengel@0
|
47 {
|
|
nengel@0
|
48 0, 1, 5, 6, 14, 15, 27, 28,
|
|
nengel@0
|
49 2, 4, 7, 13, 16, 26, 29, 42,
|
|
nengel@0
|
50 3, 8, 12, 17, 25, 30, 41, 43,
|
|
nengel@0
|
51 9, 11, 18, 24, 31, 40, 44, 53,
|
|
nengel@0
|
52 10, 19, 23, 32, 39, 45, 52, 54,
|
|
nengel@0
|
53 20, 22, 33, 38, 46, 51, 55, 60,
|
|
nengel@0
|
54 21, 34, 37, 47, 50, 56, 59, 61,
|
|
nengel@0
|
55 35, 36, 48, 49, 57, 58, 62, 63
|
|
nengel@0
|
56 };
|
|
nengel@0
|
57
|
|
nengel@0
|
58 /*
|
|
nengel@0
|
59 * 4 functions to manage the stream
|
|
nengel@0
|
60 *
|
|
nengel@0
|
61 * fill_nbits: put at least nbits in the reservoir of bits.
|
|
nengel@0
|
62 * But convert any 0xff,0x00 into 0xff
|
|
nengel@0
|
63 * get_nbits: read nbits from the stream, and put it in result,
|
|
nengel@0
|
64 * bits is removed from the stream and the reservoir is filled
|
|
nengel@0
|
65 * automaticaly. The result is signed according to the number of
|
|
nengel@0
|
66 * bits.
|
|
nengel@0
|
67 * look_nbits: read nbits from the stream without marking as read.
|
|
nengel@0
|
68 * skip_nbits: read nbits from the stream but do not return the result.
|
|
nengel@0
|
69 *
|
|
nengel@0
|
70 * stream: current pointer in the jpeg data (read bytes per bytes)
|
|
nengel@0
|
71 * nbits_in_reservoir: number of bits filled into the reservoir
|
|
nengel@0
|
72 * reservoir: register that contains bits information. Only nbits_in_reservoir
|
|
nengel@0
|
73 * is valid.
|
|
nengel@0
|
74 * nbits_in_reservoir
|
|
nengel@0
|
75 * <-- 17 bits -->
|
|
nengel@0
|
76 * Ex: 0000 0000 1010 0000 1111 0000 <== reservoir
|
|
nengel@0
|
77 * ^
|
|
nengel@0
|
78 * bit 1
|
|
nengel@0
|
79 * To get two bits from this example
|
|
nengel@0
|
80 * result = (reservoir >> 15) & 3
|
|
nengel@0
|
81 *
|
|
nengel@0
|
82 */
|
|
nengel@0
|
83
|
|
nengel@0
|
84 #define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
|
|
nengel@0
|
85 while (nbits_in_reservoir<nbits_wanted) \
|
|
nengel@0
|
86 { \
|
|
nengel@0
|
87 unsigned char c; \
|
|
nengel@0
|
88 if (stream >= priv->stream_end) \
|
|
nengel@0
|
89 return -1; \
|
|
nengel@0
|
90 c = *stream++; \
|
|
nengel@0
|
91 reservoir <<= 8; \
|
|
nengel@0
|
92 if (c == 0xff && *stream == 0x00) \
|
|
nengel@0
|
93 stream++; \
|
|
nengel@0
|
94 reservoir |= c; \
|
|
nengel@0
|
95 nbits_in_reservoir+=8; \
|
|
nengel@0
|
96 } \
|
|
nengel@0
|
97 } while(0);
|
|
nengel@0
|
98
|
|
nengel@0
|
99
|
|
nengel@0
|
100 /* Signed version !!!! */
|
|
nengel@0
|
101 #define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
|
|
nengel@0
|
102 fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
|
|
nengel@0
|
103 result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \
|
|
nengel@0
|
104 nbits_in_reservoir -= (nbits_wanted); \
|
|
nengel@0
|
105 reservoir &= ((1U<<nbits_in_reservoir)-1); \
|
|
nengel@0
|
106 if ((unsigned int)result < (1UL<<((nbits_wanted)-1))) \
|
|
nengel@0
|
107 result += (0xFFFFFFFFUL<<(nbits_wanted))+1; \
|
|
nengel@0
|
108 } while(0);
|
|
nengel@0
|
109
|
|
nengel@0
|
110 #define look_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
|
|
nengel@0
|
111 fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
|
|
nengel@0
|
112 result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \
|
|
nengel@0
|
113 } while(0);
|
|
nengel@0
|
114
|
|
nengel@0
|
115 /* To speed up the decoding, we assume that the reservoir has enough bits */
|
|
nengel@0
|
116 #define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
|
|
nengel@0
|
117 nbits_in_reservoir -= (nbits_wanted); \
|
|
nengel@0
|
118 reservoir &= ((1U<<nbits_in_reservoir)-1); \
|
|
nengel@0
|
119 } while(0);
|
|
nengel@0
|
120
|
|
nengel@0
|
121 static void resync(struct jdec_private *priv);
|
|
nengel@0
|
122
|
|
nengel@0
|
123 /**
|
|
nengel@0
|
124 * Get the next (valid) huffman code in the stream.
|
|
nengel@0
|
125 *
|
|
nengel@0
|
126 * To speedup the procedure, we look HUFFMAN_HASH_NBITS bits and the code is
|
|
nengel@0
|
127 * lower than HUFFMAN_HASH_NBITS we have automaticaly the length of the code
|
|
nengel@0
|
128 * and the value by using two lookup table.
|
|
nengel@0
|
129 * Else if the value is not found, just search (linear) into an array for each
|
|
nengel@0
|
130 * bits is the code is present.
|
|
nengel@0
|
131 *
|
|
nengel@0
|
132 * If the code is not present for any reason, -1 is return.
|
|
nengel@0
|
133 */
|
|
nengel@0
|
134 static int get_next_huffman_code(struct jdec_private *priv, struct huffman_table *huffman_table)
|
|
nengel@0
|
135 {
|
|
nengel@0
|
136 int value, hcode;
|
|
nengel@0
|
137 unsigned int extra_nbits, nbits;
|
|
nengel@0
|
138 uint16_t *slowtable;
|
|
nengel@0
|
139
|
|
nengel@0
|
140 look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, HUFFMAN_HASH_NBITS, hcode);
|
|
nengel@0
|
141 value = huffman_table->lookup[hcode];
|
|
nengel@0
|
142 if (__likely(value >= 0))
|
|
nengel@0
|
143 {
|
|
nengel@0
|
144 unsigned int code_size = huffman_table->code_size[value];
|
|
nengel@0
|
145 skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, code_size);
|
|
nengel@0
|
146 return value;
|
|
nengel@0
|
147 }
|
|
nengel@0
|
148
|
|
nengel@0
|
149 /* Decode more bits each time ... */
|
|
nengel@0
|
150 for (extra_nbits=0; extra_nbits<16-HUFFMAN_HASH_NBITS; extra_nbits++)
|
|
nengel@0
|
151 {
|
|
nengel@0
|
152 nbits = HUFFMAN_HASH_NBITS + 1 + extra_nbits;
|
|
nengel@0
|
153
|
|
nengel@0
|
154 look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits, hcode);
|
|
nengel@0
|
155 slowtable = huffman_table->slowtable[extra_nbits];
|
|
nengel@0
|
156 /* Search if the code is in this array */
|
|
nengel@0
|
157 while (slowtable[0]) {
|
|
nengel@0
|
158 if (slowtable[0] == hcode) {
|
|
nengel@0
|
159 skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits);
|
|
nengel@0
|
160 return slowtable[1];
|
|
nengel@0
|
161 }
|
|
nengel@0
|
162 slowtable+=2;
|
|
nengel@0
|
163 }
|
|
nengel@0
|
164 }
|
|
nengel@0
|
165 return 0;
|
|
nengel@0
|
166 }
|
|
nengel@0
|
167
|
|
nengel@0
|
168 /**
|
|
nengel@0
|
169 *
|
|
nengel@0
|
170 * Decode a single block that contains the DCT coefficients.
|
|
nengel@0
|
171 * The table coefficients is already dezigzaged at the end of the operation.
|
|
nengel@0
|
172 *
|
|
nengel@0
|
173 */
|
|
nengel@0
|
174 static int process_Huffman_data_unit(struct jdec_private *priv, int component)
|
|
nengel@0
|
175 {
|
|
nengel@0
|
176 unsigned char j;
|
|
nengel@0
|
177 unsigned int huff_code;
|
|
nengel@0
|
178 int retcode;
|
|
nengel@0
|
179 unsigned char size_val, count_0;
|
|
nengel@0
|
180
|
|
nengel@0
|
181 struct component *c = &priv->component_infos[component];
|
|
nengel@0
|
182 short int DCT[64];
|
|
nengel@0
|
183
|
|
nengel@0
|
184 /* Initialize the DCT coef table */
|
|
nengel@0
|
185 memset(DCT, 0, sizeof(DCT));
|
|
nengel@0
|
186
|
|
nengel@0
|
187 /* DC coefficient decoding */
|
|
nengel@0
|
188 retcode = get_next_huffman_code(priv, c->DC_table);
|
|
nengel@0
|
189 // End of stream
|
|
nengel@0
|
190 if(retcode == -1)
|
|
nengel@0
|
191 return -1;
|
|
nengel@0
|
192 else
|
|
nengel@0
|
193 huff_code = (unsigned int)retcode;
|
|
nengel@0
|
194 //trace("+ %x\n", huff_code);
|
|
nengel@0
|
195 if (huff_code) {
|
|
nengel@0
|
196 get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, huff_code, DCT[0]);
|
|
nengel@0
|
197 DCT[0] += c->previous_DC;
|
|
nengel@0
|
198 c->previous_DC = DCT[0];
|
|
nengel@0
|
199 } else {
|
|
nengel@0
|
200 DCT[0] = c->previous_DC;
|
|
nengel@0
|
201 }
|
|
nengel@0
|
202
|
|
nengel@0
|
203 /* AC coefficient decoding */
|
|
nengel@0
|
204 j = 1;
|
|
nengel@0
|
205 while (j<64)
|
|
nengel@0
|
206 {
|
|
nengel@0
|
207 huff_code = get_next_huffman_code(priv, c->AC_table);
|
|
nengel@0
|
208 //trace("- %x\n", huff_code);
|
|
nengel@0
|
209
|
|
nengel@0
|
210 size_val = huff_code & 0xF;
|
|
nengel@0
|
211 count_0 = huff_code >> 4;
|
|
nengel@0
|
212
|
|
nengel@0
|
213 if (size_val == 0)
|
|
nengel@0
|
214 { /* RLE */
|
|
nengel@0
|
215 if (count_0 == 0)
|
|
nengel@0
|
216 break; /* EOB found, go out */
|
|
nengel@0
|
217 else if (count_0 == 0xF)
|
|
nengel@0
|
218 j += 16; /* skip 16 zeros */
|
|
nengel@0
|
219 }
|
|
nengel@0
|
220 else
|
|
nengel@0
|
221 {
|
|
nengel@0
|
222 j += count_0; /* skip count_0 zeroes */
|
|
nengel@0
|
223 if (__unlikely(j >= 64))
|
|
nengel@0
|
224 {
|
|
nengel@0
|
225 snprintf(error_string, sizeof(error_string), "Bad huffman data (buffer overflow)");
|
|
nengel@0
|
226 break;
|
|
nengel@0
|
227 }
|
|
nengel@0
|
228 get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]);
|
|
nengel@0
|
229 j++;
|
|
nengel@0
|
230 }
|
|
nengel@0
|
231 }
|
|
nengel@0
|
232
|
|
nengel@0
|
233 for (j = 0; j < 64; j++)
|
|
nengel@0
|
234 c->DCT[j] = DCT[zigzag[j]];
|
|
nengel@0
|
235 return 0;
|
|
nengel@0
|
236 }
|
|
nengel@0
|
237
|
|
nengel@0
|
238 /*******************************************************************************
|
|
nengel@0
|
239 *
|
|
nengel@0
|
240 * Colorspace conversion routine
|
|
nengel@0
|
241 *
|
|
nengel@0
|
242 * Note:
|
|
nengel@0
|
243 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
|
|
nengel@0
|
244 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
|
|
nengel@0
|
245 * The conversion equations to be implemented are therefore
|
|
nengel@0
|
246 * R = Y + 1.40200 * Cr
|
|
nengel@0
|
247 * G = Y - 0.34414 * Cb - 0.71414 * Cr
|
|
nengel@0
|
248 * B = Y + 1.77200 * Cb
|
|
nengel@0
|
249 *
|
|
nengel@0
|
250 ******************************************************************************/
|
|
nengel@0
|
251
|
|
nengel@0
|
252 static unsigned char clamp(int i)
|
|
nengel@0
|
253 {
|
|
nengel@0
|
254 if (i<0)
|
|
nengel@0
|
255 return 0;
|
|
nengel@0
|
256 else if (i>255)
|
|
nengel@0
|
257 return 255;
|
|
nengel@0
|
258 else
|
|
nengel@0
|
259 return i;
|
|
nengel@0
|
260 }
|
|
nengel@0
|
261
|
|
nengel@0
|
262 #define SCALEBITS 10
|
|
nengel@0
|
263 #define ONE_HALF (1UL << (SCALEBITS-1))
|
|
nengel@0
|
264 #define FIX(x) ((int)((x) * (1UL<<SCALEBITS) + 0.5))
|
|
nengel@0
|
265
|
|
nengel@0
|
266 /**
|
|
nengel@0
|
267 * YCrCb -> RGB24 (2x2)
|
|
nengel@0
|
268 * .-------.
|
|
nengel@0
|
269 * | 1 | 2 |
|
|
nengel@0
|
270 * |---+---|
|
|
nengel@0
|
271 * | 3 | 4 |
|
|
nengel@0
|
272 * `-------'
|
|
nengel@0
|
273 */
|
|
nengel@0
|
274 static void YCrCB_to_RGB24_2x2(struct jdec_private *priv)
|
|
nengel@0
|
275 {
|
|
nengel@0
|
276 const unsigned char *Y, *Cb, *Cr;
|
|
nengel@0
|
277 unsigned char *p, *p2;
|
|
nengel@0
|
278 int i,j;
|
|
nengel@0
|
279 int offset_to_next_row;
|
|
nengel@0
|
280
|
|
nengel@0
|
281 p = priv->plane;
|
|
nengel@0
|
282 p2 = priv->plane + priv->width*3;
|
|
nengel@0
|
283 Y = priv->Y;
|
|
nengel@0
|
284 Cb = priv->Cb;
|
|
nengel@0
|
285 Cr = priv->Cr;
|
|
nengel@0
|
286 offset_to_next_row = (priv->width*3*2) - 16*3;
|
|
nengel@0
|
287 for (i=0; i<8; i++) {
|
|
nengel@0
|
288
|
|
nengel@0
|
289 for (j=0; j<8; j++) {
|
|
nengel@0
|
290
|
|
nengel@0
|
291 int y, cb, cr;
|
|
nengel@0
|
292 int add_r, add_g, add_b;
|
|
nengel@0
|
293 int r, g , b;
|
|
nengel@0
|
294
|
|
nengel@0
|
295 cb = *Cb++ - 128;
|
|
nengel@0
|
296 cr = *Cr++ - 128;
|
|
nengel@0
|
297 add_r = FIX(1.40200) * cr + ONE_HALF;
|
|
nengel@0
|
298 add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
|
|
nengel@0
|
299 add_b = FIX(1.77200) * cb + ONE_HALF;
|
|
nengel@0
|
300
|
|
nengel@0
|
301 y = (*Y++) << SCALEBITS;
|
|
nengel@0
|
302 r = (y + add_r) >> SCALEBITS;
|
|
nengel@0
|
303 *p++ = clamp(r);
|
|
nengel@0
|
304 g = (y + add_g) >> SCALEBITS;
|
|
nengel@0
|
305 *p++ = clamp(g);
|
|
nengel@0
|
306 b = (y + add_b) >> SCALEBITS;
|
|
nengel@0
|
307 *p++ = clamp(b);
|
|
nengel@0
|
308
|
|
nengel@0
|
309 y = (*Y++) << SCALEBITS;
|
|
nengel@0
|
310 r = (y + add_r) >> SCALEBITS;
|
|
nengel@0
|
311 *p++ = clamp(r);
|
|
nengel@0
|
312 g = (y + add_g) >> SCALEBITS;
|
|
nengel@0
|
313 *p++ = clamp(g);
|
|
nengel@0
|
314 b = (y + add_b) >> SCALEBITS;
|
|
nengel@0
|
315 *p++ = clamp(b);
|
|
nengel@0
|
316
|
|
nengel@0
|
317 y = (Y[16-2]) << SCALEBITS;
|
|
nengel@0
|
318 r = (y + add_r) >> SCALEBITS;
|
|
nengel@0
|
319 *p2++ = clamp(r);
|
|
nengel@0
|
320 g = (y + add_g) >> SCALEBITS;
|
|
nengel@0
|
321 *p2++ = clamp(g);
|
|
nengel@0
|
322 b = (y + add_b) >> SCALEBITS;
|
|
nengel@0
|
323 *p2++ = clamp(b);
|
|
nengel@0
|
324
|
|
nengel@0
|
325 y = (Y[16-1]) << SCALEBITS;
|
|
nengel@0
|
326 r = (y + add_r) >> SCALEBITS;
|
|
nengel@0
|
327 *p2++ = clamp(r);
|
|
nengel@0
|
328 g = (y + add_g) >> SCALEBITS;
|
|
nengel@0
|
329 *p2++ = clamp(g);
|
|
nengel@0
|
330 b = (y + add_b) >> SCALEBITS;
|
|
nengel@0
|
331 *p2++ = clamp(b);
|
|
nengel@0
|
332 }
|
|
nengel@0
|
333 Y += 16;
|
|
nengel@0
|
334 p += offset_to_next_row;
|
|
nengel@0
|
335 p2 += offset_to_next_row;
|
|
nengel@0
|
336 }
|
|
nengel@0
|
337 }
|
|
nengel@0
|
338
|
|
nengel@0
|
339 /*
|
|
nengel@0
|
340 * Decode a 2x2
|
|
nengel@0
|
341 * .-------.
|
|
nengel@0
|
342 * | 1 | 2 |
|
|
nengel@0
|
343 * |---+---|
|
|
nengel@0
|
344 * | 3 | 4 |
|
|
nengel@0
|
345 * `-------'
|
|
nengel@0
|
346 */
|
|
nengel@0
|
347 static int decode_MCU_2x2_3planes(struct jdec_private *priv)
|
|
nengel@0
|
348 {
|
|
nengel@0
|
349 // Y
|
|
nengel@0
|
350 if(process_Huffman_data_unit(priv, cY))
|
|
nengel@0
|
351 return -1;
|
|
nengel@0
|
352 IDCT(&priv->component_infos[cY], priv->Y, 16);
|
|
nengel@0
|
353 if(process_Huffman_data_unit(priv, cY))
|
|
nengel@0
|
354 return -1;
|
|
nengel@0
|
355 IDCT(&priv->component_infos[cY], priv->Y+8, 16);
|
|
nengel@0
|
356 if(process_Huffman_data_unit(priv, cY))
|
|
nengel@0
|
357 return -1;
|
|
nengel@0
|
358 IDCT(&priv->component_infos[cY], priv->Y+64*2, 16);
|
|
nengel@0
|
359 if(process_Huffman_data_unit(priv, cY))
|
|
nengel@0
|
360 return -1;
|
|
nengel@0
|
361 IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16);
|
|
nengel@0
|
362
|
|
nengel@0
|
363 // Cb
|
|
nengel@0
|
364 if(process_Huffman_data_unit(priv, cCb))
|
|
nengel@0
|
365 return -1;
|
|
nengel@0
|
366 IDCT(&priv->component_infos[cCb], priv->Cb, 8);
|
|
nengel@0
|
367
|
|
nengel@0
|
368 // Cr
|
|
nengel@0
|
369 if(process_Huffman_data_unit(priv, cCr))
|
|
nengel@0
|
370 return -1;
|
|
nengel@0
|
371 IDCT(&priv->component_infos[cCr], priv->Cr, 8);
|
|
nengel@0
|
372
|
|
nengel@0
|
373 return 0;
|
|
nengel@0
|
374 }
|
|
nengel@0
|
375
|
|
nengel@0
|
376 static void resync(struct jdec_private *priv)
|
|
nengel@0
|
377 {
|
|
nengel@0
|
378 int i;
|
|
nengel@0
|
379
|
|
nengel@0
|
380 /* Init DC coefficients */
|
|
nengel@0
|
381 for (i=0; i<COMPONENTS; i++)
|
|
nengel@0
|
382 priv->component_infos[i].previous_DC = 0;
|
|
nengel@0
|
383
|
|
nengel@0
|
384 priv->reservoir = 0;
|
|
nengel@0
|
385 priv->nbits_in_reservoir = 0;
|
|
nengel@0
|
386 }
|
|
nengel@0
|
387
|
|
nengel@0
|
388 static int find_next_rst_marker(struct jdec_private *priv)
|
|
nengel@0
|
389 {
|
|
nengel@0
|
390 int rst_marker_found = 0;
|
|
nengel@0
|
391 int marker;
|
|
nengel@0
|
392 const unsigned char *stream = priv->stream;
|
|
nengel@0
|
393
|
|
nengel@0
|
394 /* Parse marker */
|
|
nengel@0
|
395 while (!rst_marker_found)
|
|
nengel@0
|
396 {
|
|
nengel@0
|
397 while (*stream++ != 0xff)
|
|
nengel@0
|
398 {
|
|
nengel@0
|
399 if (stream >= priv->stream_end)
|
|
nengel@0
|
400 error("EOF while search for a RST marker.");
|
|
nengel@0
|
401 }
|
|
nengel@0
|
402 /* Skip any padding ff byte (this is normal) */
|
|
nengel@0
|
403 while (*stream == 0xff)
|
|
nengel@0
|
404 stream++;
|
|
nengel@0
|
405
|
|
nengel@0
|
406 marker = *stream++;
|
|
nengel@0
|
407 if ((RST+priv->last_rst_marker_seen) == marker)
|
|
nengel@0
|
408 rst_marker_found = 1;
|
|
nengel@0
|
409 else if (marker >= RST && marker <= RST7)
|
|
nengel@0
|
410 error("Wrong Reset marker found, abording");
|
|
nengel@0
|
411 else if (marker == EOI)
|
|
nengel@0
|
412 return 0;
|
|
nengel@0
|
413 }
|
|
nengel@0
|
414 trace("RST Marker %d found at offset %ld\n", priv->last_rst_marker_seen, stream - priv->stream_begin);
|
|
nengel@0
|
415
|
|
nengel@0
|
416 priv->stream = stream;
|
|
nengel@0
|
417 priv->last_rst_marker_seen++;
|
|
nengel@0
|
418 priv->last_rst_marker_seen &= 7;
|
|
nengel@0
|
419
|
|
nengel@0
|
420 return 0;
|
|
nengel@0
|
421 }
|
|
nengel@0
|
422
|
|
nengel@0
|
423 /*******************************************************************************
|
|
nengel@0
|
424 *
|
|
nengel@0
|
425 * Functions exported of the library.
|
|
nengel@0
|
426 *
|
|
nengel@0
|
427 * Note: Some applications can access directly to internal pointer of the
|
|
nengel@0
|
428 * structure. It's is not recommended, but if you have many images to
|
|
nengel@0
|
429 * uncompress with the same parameters, some functions can be called to speedup
|
|
nengel@0
|
430 * the decoding.
|
|
nengel@0
|
431 *
|
|
nengel@0
|
432 ******************************************************************************/
|
|
nengel@0
|
433
|
|
nengel@0
|
434 /**
|
|
nengel@0
|
435 * Allocate a new tinyjpeg decoder object.
|
|
nengel@0
|
436 *
|
|
nengel@0
|
437 * Before calling any other functions, an object need to be called.
|
|
nengel@0
|
438 */
|
|
nengel@0
|
439 struct jdec_private *tinyjpeg_init(void)
|
|
nengel@0
|
440 {
|
|
nengel@0
|
441 struct jdec_private *priv;
|
|
nengel@0
|
442
|
|
nengel@2
|
443 priv = (struct jdec_private *)VMS_App__malloc(1* sizeof(struct jdec_private));
|
|
nengel@0
|
444 if (priv == NULL)
|
|
nengel@0
|
445 return NULL;
|
|
nengel@2
|
446 memset(priv,0,sizeof(struct jdec_private));
|
|
nengel@0
|
447 return priv;
|
|
nengel@0
|
448 }
|
|
nengel@0
|
449
|
|
nengel@0
|
450 /**
|
|
nengel@0
|
451 * Free a tinyjpeg object.
|
|
nengel@0
|
452 *
|
|
nengel@0
|
453 * No others function can be called after this one.
|
|
nengel@0
|
454 */
|
|
nengel@0
|
455 void tinyjpeg_free(struct jdec_private *priv)
|
|
nengel@0
|
456 {
|
|
nengel@2
|
457 VMS_App__free(priv);
|
|
nengel@0
|
458 }
|
|
nengel@0
|
459
|
|
nengel@0
|
460
|
|
nengel@0
|
461 /**
|
|
nengel@0
|
462 * Create a new JPEG decode task
|
|
nengel@0
|
463 *
|
|
nengel@0
|
464 */
|
|
nengel@0
|
465 struct jdec_private *create_jdec_priv_task(struct jdec_private *priv, int tasknum)
|
|
nengel@0
|
466 {
|
|
nengel@0
|
467 struct jdec_private *jdec_task;
|
|
nengel@0
|
468
|
|
nengel@0
|
469 jdec_task = tinyjpeg_init();
|
|
nengel@0
|
470 resync(priv);
|
|
nengel@0
|
471 if (tasknum > 0){
|
|
nengel@0
|
472 find_next_rst_marker(priv);
|
|
nengel@0
|
473 }
|
|
nengel@0
|
474 memcpy(jdec_task, priv, sizeof(struct jdec_private));
|
|
nengel@0
|
475
|
|
nengel@0
|
476 jdec_task->mcus_posx = (tasknum * priv->restart_interval) % priv->mcus_in_width;
|
|
nengel@0
|
477 jdec_task->mcus_posy = (tasknum * priv->restart_interval) / priv->mcus_in_width;
|
|
nengel@0
|
478
|
|
nengel@0
|
479 return jdec_task;
|
|
nengel@0
|
480 }
|
|
nengel@0
|
481
|
|
nengel@0
|
482 /**
|
|
nengel@0
|
483 * Initialize the tinyjpeg object and prepare the decoding of the stream.
|
|
nengel@0
|
484 *
|
|
nengel@0
|
485 * Check if the jpeg can be decoded with this jpeg decoder.
|
|
nengel@0
|
486 * Fill some table used for preprocessing.
|
|
nengel@0
|
487 */
|
|
nengel@0
|
488 int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size)
|
|
nengel@0
|
489 {
|
|
nengel@0
|
490 int ret;
|
|
nengel@0
|
491
|
|
nengel@0
|
492 /* Identify the file */
|
|
nengel@0
|
493 if ((buf[0] != 0xFF) || (buf[1] != SOI))
|
|
nengel@0
|
494 error("Not a JPG file ?\n");
|
|
nengel@0
|
495
|
|
nengel@0
|
496 priv->stream_begin = buf+2;
|
|
nengel@0
|
497 priv->stream_length = size-2;
|
|
nengel@0
|
498 priv->stream_end = priv->stream_begin + priv->stream_length;
|
|
nengel@0
|
499
|
|
nengel@0
|
500 ret = parse_JFIF(priv, priv->stream_begin);
|
|
nengel@0
|
501
|
|
nengel@0
|
502 return ret;
|
|
nengel@0
|
503 }
|
|
nengel@0
|
504
|
|
nengel@0
|
505 /**
|
|
nengel@0
|
506 * Decode and convert the jpeg image
|
|
nengel@0
|
507 *
|
|
nengel@0
|
508 * Note: components will be automaticaly allocated if no memory is attached.
|
|
nengel@0
|
509 */
|
|
nengel@0
|
510 void tinyjpeg_decode_task(void *data, SlaveVP *animatingSlv )
|
|
nengel@0
|
511 {
|
|
nengel@0
|
512 //struct jdec_private *priv, uint8_t* context
|
|
nengel@0
|
513 tinyjpeg_decode_task_args* args = (tinyjpeg_decode_task_args*) data;
|
|
nengel@0
|
514
|
|
nengel@0
|
515 struct jdec_private *priv = args->priv;
|
|
nengel@0
|
516 uint8_t* context = args->context;
|
|
nengel@0
|
517
|
|
nengel@0
|
518 // Make OmpSs not complain while compiling
|
|
nengel@0
|
519 //(void) context;
|
|
nengel@0
|
520
|
|
nengel@0
|
521 unsigned int x, xstride_by_mcu, ystride_by_mcu;
|
|
nengel@0
|
522 unsigned int bytes_per_blocklines, bytes_per_mcu;
|
|
nengel@0
|
523 decode_MCU_fct decode_MCU;
|
|
nengel@0
|
524 convert_colorspace_fct convert_to_pixfmt;
|
|
nengel@0
|
525
|
|
nengel@0
|
526 bytes_per_blocklines = priv->width * RGB_DEPTH;
|
|
nengel@0
|
527 bytes_per_mcu = RGB_DEPTH*8;
|
|
nengel@0
|
528
|
|
nengel@0
|
529 // Only 2x2 CU sizes are supported in this simple decoder
|
|
nengel@0
|
530 decode_MCU = decode_MCU_2x2_3planes;
|
|
nengel@0
|
531 convert_to_pixfmt = YCrCB_to_RGB24_2x2;
|
|
nengel@0
|
532 xstride_by_mcu = MCU_X_STRIDE;
|
|
nengel@0
|
533 ystride_by_mcu = MCU_Y_STRIDE;
|
|
nengel@0
|
534
|
|
nengel@0
|
535 bytes_per_blocklines *= ystride_by_mcu;
|
|
nengel@0
|
536 bytes_per_mcu *= xstride_by_mcu/8;
|
|
nengel@0
|
537
|
|
nengel@0
|
538 /* Just the decode the image by macroblock */
|
|
nengel@0
|
539
|
|
nengel@0
|
540 priv->plane = priv->components[0] + (priv->mcus_posy * bytes_per_blocklines) + (priv->mcus_posx * bytes_per_mcu);
|
|
nengel@0
|
541
|
|
nengel@0
|
542 for (x=0; x < priv->restart_interval; x++) {
|
|
nengel@0
|
543 if(decode_MCU(priv)) {
|
|
nengel@0
|
544 fprintf(stderr, "%s\n", error_string);
|
|
nengel@0
|
545 }
|
|
nengel@0
|
546 convert_to_pixfmt(priv);
|
|
nengel@0
|
547
|
|
nengel@0
|
548 priv->plane += bytes_per_mcu;
|
|
nengel@0
|
549 priv->mcus_posx++;
|
|
nengel@0
|
550 if (priv->mcus_posx >= priv->mcus_in_width){
|
|
nengel@0
|
551 priv->mcus_posy++;
|
|
nengel@0
|
552 priv->mcus_posx = 0;
|
|
nengel@0
|
553 priv->plane += (bytes_per_blocklines - priv->width*3);
|
|
nengel@0
|
554 }
|
|
nengel@0
|
555 }
|
|
seanhalle@1
|
556 VSs__end_task(animatingSlv);
|
|
nengel@0
|
557 }
|
|
nengel@0
|
558
|
|
nengel@0
|
559 const char *tinyjpeg_get_errorstring()
|
|
nengel@0
|
560 {
|
|
nengel@0
|
561 return error_string;
|
|
nengel@0
|
562 }
|
|
nengel@0
|
563
|
|
nengel@0
|
564 void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height)
|
|
nengel@0
|
565 {
|
|
nengel@0
|
566 *width = priv->width;
|
|
nengel@0
|
567 *height = priv->height;
|
|
nengel@0
|
568 }
|
|
nengel@0
|
569
|
|
nengel@0
|
570 int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components)
|
|
nengel@0
|
571 {
|
|
nengel@0
|
572 int i;
|
|
nengel@0
|
573 for (i=0; priv->components[i] && i<COMPONENTS; i++)
|
|
nengel@0
|
574 components[i] = priv->components[i];
|
|
nengel@0
|
575 return 0;
|
|
nengel@0
|
576 } |