root/trunk/tinyjpeg/tinyjpeg/tinyjpeg.d

Revision 60, 54.4 kB (checked in by lindquist, 5 years ago)

updated tinyjpeg to compile with tango. console tracing and error messages are borked with tango right now.

Line 
1 /*
2  * Small jpeg decoder library
3  *
4  * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
5  * All rights reserved.
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * - Redistributions of source code must retain the above copyright notice,
10  *  this list of conditions and the following disclaimer.
11  *
12  * - Redistributions in binary form must reproduce the above copyright notice,
13  *  this list of conditions and the following disclaimer in the documentation
14  *  and/or other materials provided with the distribution.
15  *
16  * - Neither the name of the author nor the names of its contributors may be
17  *  used to endorse or promote products derived from this software without
18  *  specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33
34 /*
35  * Ported to the D programming language by
36  * Tomas Lindquist Olsen <tomas@famolsen.dk>
37  */
38
39 module tinyjpeg.tinyjpeg;
40
41 version(Tango) {
42     import tango.stdc.stdint;
43     import tango.stdc.stdlib;
44     import tango.stdc.string;
45     private char[] format(...)
46     {
47         return "formatted output is not yet supported with Tango";
48     }
49 }
50 else {
51     import std.c.stdlib;
52     import std.c.string;
53     import std.stdint;
54     import std.string;
55     debug(TinyJpegTrace) {
56         import std.stdio;
57     }
58 }
59
60 import tinyjpeg.jidctflt;
61 public import tinyjpeg.internal;
62
63 /* Flags that can be set by any applications */
64 enum { TINYJPEG_FLAGS_MJPEG_TABLE = (1<<1) }
65
66 /* Format accepted in outout */
67 enum /*tinyjpeg_fmt*/ {
68    TINYJPEG_FMT_GREY = 1,
69    TINYJPEG_FMT_BGR24,
70    TINYJPEG_FMT_RGB24,
71    TINYJPEG_FMT_YUV420P,
72 }
73
74 enum /*std_markers*/ {
75    DQT  = 0xDB, /* Define Quantization Table */
76    SOF  = 0xC0, /* Start of Frame (size information) */
77    DHT  = 0xC4, /* Huffman Table */
78    SOI  = 0xD8, /* Start of Image */
79    SOS  = 0xDA, /* Start of Scan */
80    RST  = 0xD0, /* Reset Marker d0 -> .. */
81    RST7 = 0xD7, /* Reset Marker .. -> d7 */
82    EOI  = 0xD9, /* End of Image */
83    DRI  = 0xDD, /* Define Restart Interval */
84    APP0 = 0xE0,
85 }
86
87 enum {
88     cY  = 0,
89     cCb = 1,
90     cCr = 2
91 }
92
93 enum {
94     BLACK_Y = 0,
95     BLACK_U = 127,
96     BLACK_V = 127
97 }
98
99 // thrown if some tinyjpeg error occured
100 private class TinyJpegException : Exception
101 {
102     this(char[] msg)
103     {
104         super(msg);
105     }
106 }
107
108 // debug trace function
109 debug(TinyJpegTrace) {
110     version(Tango)
111         private void trace(...) {}
112     else
113         private alias writef trace;
114 } else {
115     private void trace(...) {}
116 }
117
118 private int error(jdec_private* priv, char[] err)
119 {
120     priv.error_string = err;
121     return -1;
122 }
123
124
125 /*private char *print_bits(uint value, char *bitstr)
126 {
127   int i, j;
128   i=31;
129   while (i>0)
130    {
131      if (value & (1U<<i))
132        break;
133      i--;
134    }
135   j=0;
136   while (i>=0)
137    {
138      bitstr[j++] = (value & (1U<<i))?'1':'0';
139      i--;
140    }
141   bitstr[j] = 0;
142   return bitstr;
143 }*/
144
145 private void print_next_16bytes(int offset, ubyte *stream)
146 {
147   trace("%4.4x: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
148     offset,
149     stream[0], stream[1], stream[2], stream[3],
150     stream[4], stream[5], stream[6], stream[7],
151     stream[8], stream[9], stream[10], stream[11],
152     stream[12], stream[13], stream[14], stream[15]);
153 }
154
155 private const ubyte zigzag[64] =
156 [
157    0,  1,  5,  6, 14, 15, 27, 28,
158    2,  4,  7, 13, 16, 26, 29, 42,
159    3,  8, 12, 17, 25, 30, 41, 43,
160    9, 11, 18, 24, 31, 40, 44, 53,
161   10, 19, 23, 32, 39, 45, 52, 54,
162   20, 22, 33, 38, 46, 51, 55, 60,
163   21, 34, 37, 47, 50, 56, 59, 61,
164   35, 36, 48, 49, 57, 58, 62, 63
165 ];
166
167 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
168 /* IMPORTANT: these are only valid for 8-bit data precision! */
169 private const ubyte bits_dc_luminance[17] =
170 [
171   0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
172 ];
173 private const ubyte val_dc_luminance[] =
174 [
175   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
176 ];
177
178 private const ubyte bits_dc_chrominance[17] =
179 [
180   0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
181 ];
182 private const ubyte val_dc_chrominance[] =
183 [
184   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
185 ];
186
187 private const ubyte bits_ac_luminance[17] =
188 [
189   0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
190 ];
191 private const ubyte val_ac_luminance[] =
192 [
193   0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
194   0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
195   0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
196   0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
197   0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
198   0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
199   0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
200   0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
201   0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
202   0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
203   0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
204   0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
205   0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
206   0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
207   0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
208   0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
209   0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
210   0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
211   0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
212   0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
213   0xf9, 0xfa
214 ];
215
216 private const ubyte bits_ac_chrominance[17] =
217 [
218   0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
219 ];
220
221 private const ubyte val_ac_chrominance[] =
222 [
223   0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
224   0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
225   0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
226   0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
227   0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
228   0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
229   0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
230   0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
231   0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
232   0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
233   0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
234   0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
235   0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
236   0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
237   0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
238   0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
239   0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
240   0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
241   0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
242   0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
243   0xf9, 0xfa
244 ];
245
246
247 /*
248  * 4 functions to manage the stream
249  *
250  *  fill_nbits: put at least nbits in the reservoir of bits.
251  *              But convert any 0xff,0x00 into 0xff
252  *  get_nbits: read nbits from the stream, and put it in result,
253  *             bits is removed from the stream and the reservoir is filled
254  *             automaticaly. The result is signed according to the number of
255  *             bits.
256  *  look_nbits: read nbits from the stream without marking as read.
257  *  skip_nbits: read nbits from the stream but do not return the result.
258  *
259  * stream: current pointer in the jpeg data (read bytes per bytes)
260  * nbits_in_reservoir: number of bits filled into the reservoir
261  * reservoir: register that contains bits information. Only nbits_in_reservoir
262  *            is valid.
263  *                          nbits_in_reservoir
264  *                        <--    17 bits    -.
265  *            Ex: 0000 0000 1010 0000 1111 0000   <== reservoir
266  *                        ^
267  *                        bit 1
268  *            To get two bits from this example
269  *                 result = (reservoir >> 15) & 3
270  *
271  */
272 template fill_nbits(char[] reservoir, char[] nbits_in_reservoir, char[] stream, char[] nbits_wanted)
273 {
274     const fill_nbits =
275     "while ("~nbits_in_reservoir~"<"~nbits_wanted~"){"~
276     "ubyte c;"~
277     "if ("~stream~" >= priv.stream_end)"~
278     "  throw new TinyJpegException(`longjmp(priv.jump_state, -EIO)`);"~
279     "c = *"~stream~"++;"~
280     reservoir~" <<= 8;"~
281     "if (c == 0xff && *"~stream~" == 0x00)"~
282       stream~"++;"~
283     reservoir~" |= c;"~
284     nbits_in_reservoir~"+=8;"~
285     "}";
286 }
287 /*#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
288    while (nbits_in_reservoir<nbits_wanted) \
289     { \
290       ubyte c; \
291       if (stream >= priv.stream_end) \
292         longjmp(priv.jump_state, -EIO); \
293       c = *stream++; \
294       reservoir <<= 8; \
295       if (c == 0xff && *stream == 0x00) \
296         stream++; \
297       reservoir |= c; \
298       nbits_in_reservoir+=8; \
299     } \
300 }  while(0);*/
301
302 /* Signed version !!!! */
303 template get_nbits(char[] reservoir, char[] nbits_in_reservoir, char[] stream, char[] nbits_wanted, char[] result)
304 {
305     const get_nbits = "{"~
306     "mixin(fill_nbits!(`"~reservoir~"`,`"~nbits_in_reservoir~"`,`"~stream~"`,`("~nbits_wanted~")`));"~
307     result~" = (("~reservoir~")>>>("~nbits_in_reservoir~"-("~nbits_wanted~")));"~
308     nbits_in_reservoir~" -= ("~nbits_wanted~");"~
309     reservoir~" &= ((1U<<"~nbits_in_reservoir~")-1);"~
310     "if (cast(uint)"~result~" < (1U<<(("~nbits_wanted~")-1)))"~
311       result~" += (0xFFFFFFFFU<<("~nbits_wanted~"))+1;"~
312     "}";
313 }
314 /*#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
315    fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
316    result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \
317    nbits_in_reservoir -= (nbits_wanted);  \
318    reservoir &= ((1U<<nbits_in_reservoir)-1); \
319    if ((uint)result < (1UL<<((nbits_wanted)-1))) \
320        result += (0xFFFFFFFFUL<<(nbits_wanted))+1; \
321 }  while(0);*/
322
323 template look_nbits(char[] reservoir, char[] nbits_in_reservoir, char[] stream, char[] nbits_wanted, char[] result)
324 {
325     const look_nbits = "{"~
326     "mixin(fill_nbits!(`"~reservoir~"`,`"~nbits_in_reservoir~"`,`"~stream~"`,`("~nbits_wanted~")`));"~
327     result~" = (("~reservoir~")>>>("~nbits_in_reservoir~"-("~nbits_wanted~")));"~
328     "}";
329 }
330 /*#define look_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
331    fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
332    result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \
333 }  while(0);*/
334
335 /* To speed up the decoding, we assume that the reservoir have enough bit
336  * slow version:
337  * #define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
338  *   fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \
339  *   nbits_in_reservoir -= (nbits_wanted); \
340  *   reservoir &= ((1U<<nbits_in_reservoir)-1); \
341  * }  while(0);
342  */
343 template skip_nbits(char[] reservoir, char[] nbits_in_reservoir, char[] stream, char[] nbits_wanted)
344 {
345     const skip_nbits = "{"~
346     nbits_in_reservoir~" -= ("~nbits_wanted~");"~
347     reservoir~" &= ((1U<<"~nbits_in_reservoir~")-1);"~
348     "}";
349 }
350 /*#define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
351    nbits_in_reservoir -= (nbits_wanted); \
352    reservoir &= ((1U<<nbits_in_reservoir)-1); \
353 }  while(0);*/
354
355
356 template be16_to_cpu(char[] x)
357 {
358     version(LittleEndian)
359         const be16_to_cpu = "((("~x~")[0]<<8)|("~x~")[1])";
360     else
361         const be16_to_cpu = "*cast(short*)"~x~".ptr";
362 }
363 //#define be16_to_cpu(x) (((x)[0]<<8)|(x)[1])
364
365 /**
366  * Get the next (valid) huffman code in the stream.
367  *
368  * To speedup the procedure, we look HUFFMAN_HASH_NBITS bits and the code is
369  * lower than HUFFMAN_HASH_NBITS we have automaticaly the length of the code
370  * and the value by using two lookup table.
371  * Else if the value is not found, just search (linear) into an array for each
372  * bits is the code is present.
373  *
374  * If the code is not present for any reason, -1 is return.
375  */
376 private int get_next_huffman_code(jdec_private *priv, huffman_table *huffman_tab)
377 {
378   int value, hcode;
379   uint extra_nbits, nbits;
380   uint16_t *slowtable;
381
382   mixin(look_nbits!("priv.reservoir", "priv.nbits_in_reservoir", "priv.stream", "HUFFMAN_HASH_NBITS", "hcode"));
383   value = huffman_tab.lookup[hcode];
384   if (value >= 0)
385   {
386      uint code_size = huffman_tab.code_size[value];
387      mixin(skip_nbits!("priv.reservoir", "priv.nbits_in_reservoir", "priv.stream", "code_size"));
388      return value;
389   }
390
391   /* Decode more bits each time ... */
392   for (extra_nbits=0; extra_nbits<16-HUFFMAN_HASH_NBITS; extra_nbits++)
393    {
394      nbits = HUFFMAN_HASH_NBITS + 1 + extra_nbits;
395
396      mixin(look_nbits!("priv.reservoir", "priv.nbits_in_reservoir", "priv.stream", "nbits", "hcode"));
397      slowtable = huffman_tab.slowtable[extra_nbits].ptr;
398      /* Search if the code is in this array */
399      while (slowtable[0]) {
400     if (slowtable[0] == hcode) {
401        mixin(skip_nbits!("priv.reservoir", "priv.nbits_in_reservoir", "priv.stream", "nbits"));
402        return slowtable[1];
403     }
404     slowtable+=2;
405      }
406    }
407   return 0;
408 }
409
410
411
412
413 /**
414  *
415  * Decode a single block that contains the DCT coefficients.
416  * The table coefficients is already dezigzaged at the end of the operation.
417  *
418  */
419 private void process_Huffman_data_unit(jdec_private *priv, int comp)
420 {
421   ubyte j;
422   uint huff_code;
423   ubyte size_val, count_0;
424
425   component *co = &priv.component_infos[comp];
426   short DCT[64];
427
428   /* Initialize the DCT coef table */
429   memset(DCT.ptr, 0, DCT.sizeof);
430   static assert (DCT.sizeof == 128);
431
432   /* DC coefficient decoding */
433   huff_code = get_next_huffman_code(priv, co.DC_table);
434   //trace("+ %x\n", huff_code);
435   if (huff_code) {
436      mixin(get_nbits!("priv.reservoir", "priv.nbits_in_reservoir", "priv.stream", "huff_code", "DCT[0]"));
437      DCT[0] += co.previous_DC;
438      co.previous_DC = DCT[0];
439   } else {
440      DCT[0] = co.previous_DC;
441   }
442
443
444   /* AC coefficient decoding */
445   j = 1;
446   while (j<64)
447    {
448      huff_code = get_next_huffman_code(priv, co.AC_table);
449      //trace("- %x\n", huff_code);
450
451      size_val = huff_code & 0xF;
452      count_0 = huff_code >>> 4;
453
454      if (size_val == 0)
455       { /* RLE */
456     if (count_0 == 0)
457       break;    /* EOB found, go out */
458     else if (count_0 == 0xF)
459       j += 16;  /* skip 16 zeros */
460       }
461      else
462       {
463     j += count_0;   /* skip count_0 zeroes */
464     if (j >= 64)
465     {
466       error(priv,"Bad huffman data (buffer overflow)");
467       break;
468     }
469     mixin(get_nbits!("priv.reservoir", "priv.nbits_in_reservoir", "priv.stream", "size_val", "DCT[j]"));
470     j++;
471       }
472    }
473
474   for (j = 0; j < 64; j++)
475     co.DCT[j] = DCT[zigzag[j]];
476 }
477
478 /*
479  * Takes two array of bits, and build the huffman table for size, and code
480  *
481  * lookup will return the symbol if the code is less or equal than HUFFMAN_HASH_NBITS.
482  * code_size will be used to known how many bits this symbol is encoded.
483  * slowtable will be used when the first lookup didn't give the result.
484  */
485 private void build_huffman_table(ubyte *bits, ubyte *vals, huffman_table *table)
486 {
487   uint i, j, code, code_size, val, nbits;
488   ubyte huffsize[HUFFMAN_BITS_SIZE+1];
489   ubyte *hz;
490   uint huffcode[HUFFMAN_BITS_SIZE+1];
491   uint *hc;
492   int next_free_entry;
493
494   /*
495    * Build a temp array
496    *   huffsize[X] => numbers of bits to write vals[X]
497    */
498   hz = huffsize.ptr;
499   for (i=1; i<=16; i++)
500    {
501      for (j=1; j<=bits[i]; j++)
502        *hz++ = i;
503    }
504   *hz = 0;
505
506   memset(table.lookup.ptr, 0xff, table.lookup.sizeof);
507   for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++)
508     table.slowtable[i][0] = 0;
509
510   /* Build a temp array
511    *   huffcode[X] => code used to write vals[X]
512    */
513   code = 0;
514   hc = huffcode.ptr;
515   hz = huffsize.ptr;
516   nbits = *hz;
517   while (*hz)
518    {
519      while (*hz == nbits)
520       {
521         *hc++ = code++;
522         hz++;
523       }
524      code <<= 1;
525      nbits++;
526    }
527
528   /*
529    * Build the lookup table, and the slowtable if needed.
530    */
531   next_free_entry = -1;
532   for (i=0; huffsize[i]; i++)
533    {
534      val = vals[i];
535      code = huffcode[i];
536      code_size = huffsize[i];
537
538      trace("val=%2.2x code=%8.8x codesize=%2.2d\n", val, code, code_size);
539
540      table.code_size[val] = code_size;
541      if (code_size <= HUFFMAN_HASH_NBITS)
542       {
543     /*
544      * Good: val can be put in the lookup table, so fill all value of this
545      * column with value val
546      */
547     int repeat = 1U<<(HUFFMAN_HASH_NBITS - code_size);
548     code <<= HUFFMAN_HASH_NBITS - code_size;
549     while ( repeat-- )
550       table.lookup[code++] = val;
551
552       }
553      else
554       {
555     /* Perhaps sorting the array will be an optimization */
556     uint16_t *slowtable = table.slowtable[code_size-HUFFMAN_HASH_NBITS-1].ptr;
557     while(slowtable[0])
558       slowtable+=2;
559     slowtable[0] = code;
560     slowtable[1] = val;
561     slowtable[2] = 0;
562     /* TODO: NEED TO CHECK FOR AN OVERFLOW OF THE TABLE */
563       }
564
565    }
566
567 }
568
569 private void build_default_huffman_tables(jdec_private *priv)
570 {
571   if (   (priv.flags & TINYJPEG_FLAGS_MJPEG_TABLE)
572       && priv.default_huffman_table_initialized)
573     return;
574
575   build_huffman_table(bits_dc_luminance.ptr, val_dc_luminance.ptr, &priv.HTDC[0]);
576   build_huffman_table(bits_ac_luminance.ptr, val_ac_luminance.ptr, &priv.HTAC[0]);
577
578   build_huffman_table(bits_dc_chrominance.ptr, val_dc_chrominance.ptr, &priv.HTDC[1]);
579   build_huffman_table(bits_ac_chrominance.ptr, val_ac_chrominance.ptr, &priv.HTAC[1]);
580
581   priv.default_huffman_table_initialized = 1;
582 }
583
584
585
586 /*******************************************************************************
587  *
588  * Colorspace conversion routine
589  *
590  *
591  * Note:
592  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
593  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
594  * The conversion equations to be implemented are therefore
595  *      R = Y                + 1.40200 * Cr
596  *      G = Y - 0.34414 * Cb - 0.71414 * Cr
597  *      B = Y + 1.77200 * Cb
598  *
599  ******************************************************************************/
600
601 private ubyte clamp(int i)
602 {
603   if (i<0)
604     return 0;
605   else if (i>255)
606     return 255;
607   else
608     return i;
609 }
610
611
612 /**
613  *  YCrCb . YUV420P (1x1)
614  *  .---.
615  *  | 1 |
616  *  `---'
617  */
618 private void YCrCB_to_YUV420P_1x1(jdec_private *priv)
619 {
620   ubyte* s, y;
621   ubyte *p;
622   int i,j;
623
624   p = priv.plane[0];
625   y = priv.Y.ptr;
626   for (i=0; i<8; i++)
627    {
628      memcpy(p, y, 8);
629      p+=priv.width;
630      y+=8;
631    }
632
633   p = priv.plane[1];
634   s = priv.Cb.ptr;
635   for (i=0; i<8; i+=2)
636    {
637      for (j=0; j<8; j+=2, s+=2)
638        *p++ = *s;
639      s += 8; /* Skip one line */
640      p += priv.width/2 - 4;
641    }
642
643   p = priv.plane[2];
644   s = priv.Cr.ptr;
645   for (i=0; i<8; i+=2)
646    {
647      for (j=0; j<8; j+=2, s+=2)
648        *p++ = *s;
649      s += 8; /* Skip one line */
650      p += priv.width/2 - 4;
651    }
652 }
653
654 /**
655  *  YCrCb . YUV420P (2x1)
656  *  .-------.
657  *  | 1 | 2 |
658  *  `-------'
659  */
660 private void YCrCB_to_YUV420P_2x1(jdec_private *priv)
661 {
662   ubyte *p;
663   ubyte* s, y1;
664   uint i;
665
666   p = priv.plane[0];
667   y1 = priv.Y.ptr;
668   for (i=0; i<8; i++)
669    {
670      memcpy(p, y1, 16);
671      p += priv.width;
672      y1 += 16;
673    }
674
675   p = priv.plane[1];
676   s = priv.Cb.ptr;
677   for (i=0; i<8; i+=2)
678    {
679      memcpy(p, s, 8);
680      s += 16; /* Skip one line */
681      p += priv.width/2;
682    }
683
684   p = priv.plane[2];
685   s = priv.Cr.ptr;
686   for (i=0; i<8; i+=2)
687    {
688      memcpy(p, s, 8);
689      s += 16; /* Skip one line */
690      p += priv.width/2;
691    }
692 }
693
694
695 /**
696  *  YCrCb . YUV420P (1x2)
697  *  .---.
698  *  | 1 |
699  *  |---|
700  *  | 2 |
701  *  `---'
702  */
703 private void YCrCB_to_YUV420P_1x2(jdec_private *priv)
704 {
705   ubyte* s, y;
706   ubyte *p;
707   int i,j;
708
709   p = priv.plane[0];
710   y = priv.Y.ptr;
711   for (i=0; i<16; i++)
712    {
713      memcpy(p, y, 8);
714      p+=priv.width;
715      y+=8;
716    }
717
718   p = priv.plane[1];
719   s = priv.Cb.ptr;
720   for (i=0; i<8; i++)
721    {
722      for (j=0; j<8; j+=2, s+=2)
723        *p++ = *s;
724      p += priv.width/2 - 4;
725    }
726
727   p = priv.plane[2];
728   s = priv.Cr.ptr;
729   for (i=0; i<8; i++)
730    {
731      for (j=0; j<8; j+=2, s+=2)
732        *p++ = *s;
733      p += priv.width/2 - 4;
734    }
735 }
736
737 /**
738  *  YCrCb . YUV420P (2x2)
739  *  .-------.
740  *  | 1 | 2 |
741  *  |---+---|
742  *  | 3 | 4 |
743  *  `-------'
744  */
745 private void YCrCB_to_YUV420P_2x2(jdec_private *priv)
746 {
747   ubyte *p;
748   ubyte* s, y1;
749   uint i;
750
751   p = priv.plane[0];
752   y1 = priv.Y.ptr;
753   for (i=0; i<16; i++)
754    {
755      memcpy(p, y1, 16);
756      p += priv.width;
757      y1 += 16;
758    }
759
760   p = priv.plane[1];
761   s = priv.Cb.ptr;
762   for (i=0; i<8; i++)
763    {
764      memcpy(p, s, 8);
765      s += 8;
766      p += priv.width/2;
767    }
768
769   p = priv.plane[2];
770   s = priv.Cr.ptr;
771   for (i=0; i<8; i++)
772    {
773      memcpy(p, s, 8);
774      s += 8;
775      p += priv.width/2;
776    }
777 }
778
779 /**
780  *  YCrCb . RGB24 (1x1)
781  *  .---.
782  *  | 1 |
783  *  `---'
784  */
785 private void YCrCB_to_RGB24_1x1(jdec_private *priv)
786 {
787   ubyte* Y, Cb, Cr;
788   ubyte *p;
789   int i,j;
790   int offset_to_next_row;
791
792   enum {
793     SCALEBITS = 10,
794     ONE_HALF = (1U << (SCALEBITS-1))
795   }
796   static int FIX(float x) {
797     return cast(int)(x * (1U<<SCALEBITS) + 0.5);
798   }
799
800   p = priv.plane[0];
801   Y = priv.Y.ptr;
802   Cb = priv.Cb.ptr;
803   Cr = priv.Cr.ptr;
804   offset_to_next_row = priv.width*3 - 8*3;
805   for (i=0; i<8; i++) {
806
807     for (j=0; j<8; j++) {
808
809        int y, cb, cr;
810        int add_r, add_g, add_b;
811        int r, g , b;
812
813        y  = (*Y++) << SCALEBITS;
814        cb = *Cb++ - 128;
815        cr = *Cr++ - 128;
816        add_r = FIX(1.40200) * cr + ONE_HALF;
817        add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
818        add_b = FIX(1.77200) * cb + ONE_HALF;
819
820        r = (y + add_r) >> SCALEBITS;
821        *p++ = clamp(r);
822        g = (y + add_g) >> SCALEBITS;
823        *p++ = clamp(g);
824        b = (y + add_b) >> SCALEBITS;
825        *p++ = clamp(b);
826
827     }
828
829     p += offset_to_next_row;
830   }
831
832 }
833
834 /**
835  *  YCrCb . BGR24 (1x1)
836  *  .---.
837  *  | 1 |
838  *  `---'
839  */
840 private void YCrCB_to_BGR24_1x1(jdec_private *priv)
841 {
842   ubyte* Y, Cb, Cr;
843   ubyte *p;
844   int i,j;
845   int offset_to_next_row;
846
847   enum {
848     SCALEBITS = 10,
849     ONE_HALF = (1U << (SCALEBITS-1))
850   }
851   static int FIX(float x) {
852     return cast(int)(x * (1U<<SCALEBITS) + 0.5);
853   }
854
855   p = priv.plane[0];
856   Y = priv.Y.ptr;
857   Cb = priv.Cb.ptr;
858   Cr = priv.Cr.ptr;
859   offset_to_next_row = priv.width*3 - 8*3;
860   for (i=0; i<8; i++) {
861
862     for (j=0; j<8; j++) {
863
864        int y, cb, cr;
865        int add_r, add_g, add_b;
866        int r, g , b;
867
868        y  = (*Y++) << SCALEBITS;
869        cb = *Cb++ - 128;
870        cr = *Cr++ - 128;
871        add_r = FIX(1.40200) * cr + ONE_HALF;
872        add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
873        add_b = FIX(1.77200) * cb + ONE_HALF;
874
875        b = (y + add_b) >> SCALEBITS;
876        *p++ = clamp(b);
877        g = (y + add_g) >> SCALEBITS;
878        *p++ = clamp(g);
879        r = (y + add_r) >> SCALEBITS;
880        *p++ = clamp(r);
881
882     }
883
884     p += offset_to_next_row;
885   }
886
887 }
888
889
890 /**
891  *  YCrCb . RGB24 (2x1)
892  *  .-------.
893  *  | 1 | 2 |
894  *  `-------'
895  */
896 private void YCrCB_to_RGB24_2x1(jdec_private *priv)
897 {
898   ubyte* Y, Cb, Cr;
899   ubyte *p;
900   int i,j;
901   int offset_to_next_row;
902
903   enum {
904     SCALEBITS = 10,
905     ONE_HALF = (1U << (SCALEBITS-1))
906   }
907   static int FIX(float x) {
908     return cast(int)(x * (1U<<SCALEBITS) + 0.5);
909   }
910
911   p = priv.plane[0];
912   Y = priv.Y.ptr;
913   Cb = priv.Cb.ptr;
914   Cr = priv.Cr.ptr;
915   offset_to_next_row = priv.width*3 - 16*3;
916   for (i=0; i<8; i++) {
917
918     for (j=0; j<8; j++) {
919
920        int y, cb, cr;
921        int add_r, add_g, add_b;
922        int r, g , b;
923
924        y  = (*Y++) << SCALEBITS;
925        cb = *Cb++ - 128;
926        cr = *Cr++ - 128;
927        add_r = FIX(1.40200) * cr + ONE_HALF;
928        add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
929        add_b = FIX(1.77200) * cb + ONE_HALF;
930
931        r = (y + add_r) >> SCALEBITS;
932        *p++ = clamp(r);
933        g = (y + add_g) >> SCALEBITS;
934        *p++ = clamp(g);
935        b = (y + add_b) >> SCALEBITS;
936        *p++ = clamp(b);
937
938        y  = (*Y++) << SCALEBITS;
939        r = (y + add_r) >> SCALEBITS;
940        *p++ = clamp(r);
941        g = (y + add_g) >> SCALEBITS;
942        *p++ = clamp(g);
943        b = (y + add_b) >> SCALEBITS;
944        *p++ = clamp(b);
945
946     }
947
948     p += offset_to_next_row;
949   }
950
951 }
952
953 /*
954  *  YCrCb . BGR24 (2x1)
955  *  .-------.
956  *  | 1 | 2 |
957  *  `-------'
958  */
959 private void YCrCB_to_BGR24_2x1(jdec_private *priv)
960 {
961   ubyte* Y, Cb, Cr;
962   ubyte *p;
963   int i,j;
964   int offset_to_next_row;
965
966   enum {
967     SCALEBITS = 10,
968     ONE_HALF = (1U << (SCALEBITS-1))
969   }
970   static int FIX(float x) {
971     return cast(int)(x * (1U<<SCALEBITS) + 0.5);
972   }
973
974   p = priv.plane[0];
975   Y = priv.Y.ptr;
976   Cb = priv.Cb.ptr;
977   Cr = priv.Cr.ptr;
978   offset_to_next_row = priv.width*3 - 16*3;
979   for (i=0; i<8; i++) {
980
981     for (j=0; j<8; j++) {
982
983        int y, cb, cr;
984        int add_r, add_g, add_b;
985        int r, g , b;
986
987        cb = *Cb++ - 128;
988        cr = *Cr++ - 128;
989        add_r = FIX(1.40200) * cr + ONE_HALF;
990        add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
991        add_b = FIX(1.77200) * cb + ONE_HALF;
992
993        y  = (*Y++) << SCALEBITS;
994        b = (y + add_b) >> SCALEBITS;
995        *p++ = clamp(b);
996        g = (y + add_g) >> SCALEBITS;
997        *p++ = clamp(g);
998        r = (y + add_r) >> SCALEBITS;
999        *p++ = clamp(r);
1000
1001        y  = (*Y++) << SCALEBITS;
1002        b = (y + add_b) >> SCALEBITS;
1003        *p++ = clamp(b);
1004        g = (y + add_g) >> SCALEBITS;
1005        *p++ = clamp(g);
1006        r = (y + add_r) >> SCALEBITS;
1007        *p++ = clamp(r);
1008
1009     }
1010
1011     p += offset_to_next_row;
1012   }
1013
1014 }
1015
1016 /**
1017  *  YCrCb . RGB24 (1x2)
1018  *  .---.
1019  *  | 1 |
1020  *  |---|
1021  *  | 2 |
1022  *  `---'
1023  */
1024 private void YCrCB_to_RGB24_1x2(jdec_private *priv)
1025 {
1026   ubyte* Y, Cb, Cr;
1027   ubyte*p, p2;
1028   int i,j;
1029   int offset_to_next_row;
1030
1031   enum {
1032     SCALEBITS = 10,
1033     ONE_HALF = (1U << (SCALEBITS-1))
1034   }
1035   static int FIX(float x) {
1036     return cast(int)(x * (1U<<SCALEBITS) + 0.5);
1037   }
1038
1039   p = priv.plane[0];
1040   p2 = priv.plane[0] + priv.width*3;
1041   Y = priv.Y.ptr;
1042   Cb = priv.Cb.ptr;
1043   Cr = priv.Cr.ptr;
1044   offset_to_next_row = 2*priv.width*3 - 8*3;
1045   for (i=0; i<8; i++) {
1046
1047     for (j=0; j<8; j++) {
1048
1049        int y, cb, cr;
1050        int add_r, add_g, add_b;
1051        int r, g , b;
1052
1053        cb = *Cb++ - 128;
1054        cr = *Cr++ - 128;
1055        add_r = FIX(1.40200) * cr + ONE_HALF;
1056        add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
1057        add_b = FIX(1.77200) * cb + ONE_HALF;
1058
1059        y  = (*Y++) << SCALEBITS;
1060        r = (y + add_r) >> SCALEBITS;
1061        *p++ = clamp(r);
1062        g = (y + add_g) >> SCALEBITS;
1063        *p++ = clamp(g);
1064        b = (y + add_b) >> SCALEBITS;
1065        *p++ = clamp(b);
1066
1067        y  = (Y[8-1]) << SCALEBITS;
1068        r = (y + add_r) >> SCALEBITS;
1069        *p2++ = clamp(r);
1070        g = (y + add_g) >> SCALEBITS;
1071        *p2++ = clamp(g);
1072        b = (y + add_b) >> SCALEBITS;
1073        *p2++ = clamp(b);
1074
1075     }
1076     Y += 8;
1077     p += offset_to_next_row;
1078     p2 += offset_to_next_row;
1079   }
1080
1081 }
1082
1083 /*
1084  *  YCrCb . BGR24 (1x2)
1085  *  .---.
1086  *  | 1 |
1087  *  |---|
1088  *  | 2 |
1089  *  `---'
1090  */
1091 private void YCrCB_to_BGR24_1x2(jdec_private *priv)
1092 {
1093   ubyte* Y, Cb, Cr;
1094   ubyte* p, p2;
1095   int i,j;
1096   int offset_to_next_row;
1097
1098   enum {
1099     SCALEBITS = 10,
1100     ONE_HALF = (1U << (SCALEBITS-1))
1101   }
1102   static int FIX(float x) {
1103     return cast(int)(x * (1U<<SCALEBITS) + 0.5);
1104   }
1105
1106   p = priv.plane[0];
1107   p2 = priv.plane[0] + priv.width*3;
1108   Y = priv.Y.ptr;
1109   Cb = priv.Cb.ptr;
1110   Cr = priv.Cr.ptr;
1111   offset_to_next_row = 2*priv.width*3 - 8*3;
1112   for (i=0; i<8; i++) {
1113
1114     for (j=0; j<8; j++) {
1115
1116        int y, cb, cr;
1117        int add_r, add_g, add_b;
1118        int r, g , b;
1119
1120        cb = *Cb++ - 128;
1121        cr = *Cr++ - 128;
1122        add_r = FIX(1.40200) * cr + ONE_HALF;
1123        add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
1124        add_b = FIX(1.77200) * cb + ONE_HALF;
1125
1126        y  = (*Y++) << SCALEBITS;
1127        b = (y + add_b) >> SCALEBITS;
1128        *p++ = clamp(b);
1129        g = (y + add_g) >> SCALEBITS;
1130        *p++ = clamp(g);
1131        r = (y + add_r) >> SCALEBITS;
1132        *p++ = clamp(r);
1133
1134        y  = (Y[8-1]) << SCALEBITS;
1135        b = (y + add_b) >> SCALEBITS;
1136        *p2++ = clamp(b);
1137        g = (y + add_g) >> SCALEBITS;
1138        *p2++ = clamp(g);
1139        r = (y + add_r) >> SCALEBITS;
1140        *p2++ = clamp(r);
1141
1142     }
1143     Y += 8;
1144     p += offset_to_next_row;
1145     p2 += offset_to_next_row;
1146   }
1147
1148 }
1149
1150
1151 /**
1152  *  YCrCb . RGB24 (2x2)
1153  *  .-------.
1154  *  | 1 | 2 |
1155  *  |---+---|
1156  *  | 3 | 4 |
1157  *  `-------'
1158  */
1159 private void YCrCB_to_RGB24_2x2(jdec_private *priv)
1160 {
1161   ubyte* Y, Cb, Cr;
1162   ubyte* p, p2;
1163   int i,j;
1164   int offset_to_next_row;
1165
1166   enum {
1167     SCALEBITS = 10,
1168     ONE_HALF = (1U << (SCALEBITS-1))
1169   }
1170   static int FIX(float x) {
1171     return cast(int)(x * (1U<<SCALEBITS) + 0.5);
1172   }
1173
1174   p = priv.plane[0];
1175   p2 = priv.plane[0] + priv.width*3;
1176   Y = priv.Y.ptr;
1177   Cb = priv.Cb.ptr;
1178   Cr = priv.Cr.ptr;
1179   offset_to_next_row = (priv.width*3*2) - 16*3;
1180   for (i=0; i<8; i++) {
1181
1182     for (j=0; j<8; j++) {
1183
1184        int y, cb, cr;
1185        int add_r, add_g, add_b;
1186        int r, g , b;
1187
1188        cb = *Cb++ - 128;
1189        cr = *Cr++ - 128;
1190        add_r = FIX(1.40200) * cr + ONE_HALF;
1191        add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
1192        add_b = FIX(1.77200) * cb + ONE_HALF;
1193
1194        y  = (*Y++) << SCALEBITS;
1195        r = (y + add_r) >> SCALEBITS;
1196        *p++ = clamp(r);
1197        g = (y + add_g) >> SCALEBITS;
1198        *p++ = clamp(g);
1199        b = (y + add_b) >> SCALEBITS;
1200        *p++ = clamp(b);
1201
1202        y  = (*Y++) << SCALEBITS;
1203        r = (y + add_r) >> SCALEBITS;
1204        *p++ = clamp(r);
1205        g = (y + add_g) >> SCALEBITS;
1206        *p++ = clamp(g);
1207        b = (y + add_b) >> SCALEBITS;
1208        *p++ = clamp(b);
1209
1210        y  = (Y[16-2]) << SCALEBITS;
1211        r = (y + add_r) >> SCALEBITS;
1212        *p2++ = clamp(r);
1213        g = (y + add_g) >> SCALEBITS;
1214        *p2++ = clamp(g);
1215        b = (y + add_b) >> SCALEBITS;
1216        *p2++ = clamp(b);
1217
1218        y  = (Y[16-1]) << SCALEBITS;
1219        r = (y + add_r) >> SCALEBITS;
1220        *p2++ = clamp(r);
1221        g = (y + add_g) >> SCALEBITS;
1222        *p2++ = clamp(g);
1223        b = (y + add_b) >> SCALEBITS;
1224        *p2++ = clamp(b);
1225     }
1226     Y  += 16;
1227     p  += offset_to_next_row;
1228     p2 += offset_to_next_row;
1229   }
1230
1231 }
1232
1233
1234 /*
1235  *  YCrCb . BGR24 (2x2)
1236  *  .-------.
1237  *  | 1 | 2 |
1238  *  |---+---|
1239  *  | 3 | 4 |
1240  *  `-------'
1241  */
1242 private void YCrCB_to_BGR24_2x2(jdec_private *priv)
1243 {
1244   ubyte* Y, Cb, Cr;
1245   ubyte* p, p2;
1246   int i,j;
1247   int offset_to_next_row;
1248
1249   enum {
1250     SCALEBITS = 10,
1251     ONE_HALF = (1U << (SCALEBITS-1))
1252   }
1253   static int FIX(float x) {
1254     return cast(int)(x * (1U<<SCALEBITS) + 0.5);
1255   }
1256
1257   p = priv.plane[0];
1258   p2 = priv.plane[0] + priv.width*3;
1259   Y = priv.Y.ptr;
1260   Cb = priv.Cb.ptr;
1261   Cr = priv.Cr.ptr;
1262   offset_to_next_row = (priv.width*3*2) - 16*3;
1263   for (i=0; i<8; i++) {
1264
1265     for (j=0; j<8; j++) {
1266
1267        int y, cb, cr;
1268        int add_r, add_g, add_b;
1269        int r, g , b;
1270
1271        cb = *Cb++ - 128;
1272        cr = *Cr++ - 128;
1273        add_r = FIX(1.40200) * cr + ONE_HALF;
1274        add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;
1275        add_b = FIX(1.77200) * cb + ONE_HALF;
1276
1277        y  = (*Y++) << SCALEBITS;
1278        b = (y + add_b) >> SCALEBITS;
1279        *p++ = clamp(b);
1280        g = (y + add_g) >> SCALEBITS;
1281        *p++ = clamp(g);
1282        r = (y + add_r) >> SCALEBITS;
1283        *p++ = clamp(r);
1284
1285        y  = (*Y++) << SCALEBITS;
1286        b = (y + add_b) >> SCALEBITS;
1287        *p++ = clamp(b);
1288        g = (y + add_g) >> SCALEBITS;
1289        *p++ = clamp(g);
1290        r = (y + add_r) >> SCALEBITS;
1291        *p++ = clamp(r);
1292
1293        y  = (Y[16-2]) << SCALEBITS;
1294        b = (y + add_b) >> SCALEBITS;
1295        *p2++ = clamp(b);
1296        g = (y + add_g) >> SCALEBITS;
1297        *p2++ = clamp(g);
1298        r = (y + add_r) >> SCALEBITS;
1299        *p2++ = clamp(r);
1300
1301        y  = (Y[16-1]) << SCALEBITS;
1302        b = (y + add_b) >> SCALEBITS;
1303        *p2++ = clamp(b);
1304        g = (y + add_g) >> SCALEBITS;
1305        *p2++ = clamp(g);
1306        r = (y + add_r) >> SCALEBITS;
1307        *p2++ = clamp(r);
1308     }
1309     Y  += 16;
1310     p  += offset_to_next_row;
1311     p2 += offset_to_next_row;
1312   }
1313
1314 }
1315
1316
1317
1318 /**
1319  *  YCrCb . Grey (1x1)
1320  *  .---.
1321  *  | 1 |
1322  *  `---'
1323  */
1324 private void YCrCB_to_Grey_1x1(jdec_private *priv)
1325 {
1326   ubyte *y;
1327   ubyte *p;
1328   uint i;
1329   int offset_to_next_row;
1330
1331   p = priv.plane[0];
1332   y = priv.Y.ptr;
1333   offset_to_next_row = priv.width;
1334
1335   for (i=0; i<8; i++) {
1336      memcpy(p, y, 8);
1337      y+=8;
1338      p += offset_to_next_row;
1339   }
1340 }
1341
1342 /**
1343  *  YCrCb . Grey (2x1)
1344  *  .-------.
1345  *  | 1 | 2 |
1346  *  `-------'
1347  */
1348 private void YCrCB_to_Grey_2x1(jdec_private *priv)
1349 {
1350   ubyte *y;
1351   ubyte *p;
1352   uint i;
1353
1354   p = priv.plane[0];
1355   y = priv.Y.ptr;
1356
1357   for (i=0; i<8; i++) {
1358      memcpy(p, y, 16);
1359      y += 16;
1360      p += priv.width;
1361   }
1362 }
1363
1364
1365 /**
1366  *  YCrCb . Grey (1x2)
1367  *  .---.
1368  *  | 1 |
1369  *  |---|
1370  *  | 2 |
1371  *  `---'
1372  */
1373 private void YCrCB_to_Grey_1x2(jdec_private *priv)
1374 {
1375   ubyte *y;
1376   ubyte *p;
1377   uint i;
1378
1379   p = priv.plane[0];
1380   y = priv.Y.ptr;
1381
1382   for (i=0; i<16; i++) {
1383      memcpy(p, y, 8);
1384      y += 8;
1385      p += priv.width;
1386   }
1387 }
1388
1389 /**
1390  *  YCrCb . Grey (2x2)
1391  *  .-------.
1392  *  | 1 | 2 |
1393  *  |---+---|
1394  *  | 3 | 4 |
1395  *  `-------'
1396  */
1397 private void YCrCB_to_Grey_2x2(jdec_private *priv)
1398 {
1399   ubyte *y;
1400   ubyte *p;
1401   uint i;
1402
1403   p = priv.plane[0];
1404   y = priv.Y.ptr;
1405
1406   for (i=0; i<16; i++) {
1407      memcpy(p, y, 16);
1408      y += 16;
1409      p += priv.width;
1410   }
1411 }
1412
1413
1414 /*
1415  * Decode all the 3 components for 1x1
1416  */
1417 private void decode_MCU_1x1_3planes(jdec_private *priv)
1418 {
1419   // Y
1420   process_Huffman_data_unit(priv, cY);
1421   IDCT(&priv.component_infos[cY], priv.Y.ptr, 8);
1422
1423   // Cb
1424   process_Huffman_data_unit(priv, cCb);
1425   IDCT(&priv.component_infos[cCb], priv.Cb.ptr, 8);
1426
1427   // Cr
1428   process_Huffman_data_unit(priv, cCr);
1429   IDCT(&priv.component_infos[cCr], priv.Cr.ptr, 8);
1430 }
1431
1432 /*
1433  * Decode a 1x1 directly in 1 color
1434  */
1435 private void decode_MCU_1x1_1plane(jdec_private *priv)
1436 {
1437   // Y
1438   process_Huffman_data_unit(priv, cY);
1439   IDCT(&priv.component_infos[cY], priv.Y.ptr, 8);
1440
1441   // Cb
1442   process_Huffman_data_unit(priv, cCb);
1443   IDCT(&priv.component_infos[cCb], priv.Cb.ptr, 8);
1444
1445   // Cr
1446   process_Huffman_data_unit(priv, cCr);
1447   IDCT(&priv.component_infos[cCr], priv.Cr.ptr, 8);
1448 }
1449
1450
1451 /*
1452  * Decode a 2x1
1453  *  .-------.
1454  *  | 1 | 2 |
1455  *  `-------'
1456  */
1457 private void decode_MCU_2x1_3planes(jdec_private *priv)
1458 {
1459   // Y
1460   process_Huffman_data_unit(priv, cY);
1461   IDCT(&priv.component_infos[cY], priv.Y.ptr, 16);
1462   process_Huffman_data_unit(priv, cY);
1463   IDCT(&priv.component_infos[cY], priv.Y.ptr+8, 16);
1464
1465   // Cb
1466   process_Huffman_data_unit(priv, cCb);
1467   IDCT(&priv.component_infos[cCb], priv.Cb.ptr, 8);
1468
1469   // Cr
1470   process_Huffman_data_unit(priv, cCr);
1471   IDCT(&priv.component_infos[cCr], priv.Cr.ptr, 8);
1472 }
1473
1474 /*
1475  * Decode a 2x1
1476  *  .-------.
1477  *  | 1 | 2 |
1478  *  `-------'
1479  */
1480 private void decode_MCU_2x1_1plane(jdec_private *priv)
1481 {
1482   // Y
1483   process_Huffman_data_unit(priv, cY);
1484   IDCT(&priv.component_infos[cY], priv.Y.ptr, 16);
1485   process_Huffman_data_unit(priv, cY);
1486   IDCT(&priv.component_infos[cY], priv.Y.ptr+8, 16);
1487
1488   // Cb
1489   process_Huffman_data_unit(priv, cCb);
1490
1491   // Cr
1492   process_Huffman_data_unit(priv, cCr);
1493 }
1494
1495
1496 /*
1497  * Decode a 2x2
1498  *  .-------.
1499  *  | 1 | 2 |
1500  *  |---+---|
1501  *  | 3 | 4 |
1502  *  `-------'
1503  */
1504 private void decode_MCU_2x2_3planes(jdec_private *priv)
1505 {
1506   // Y
1507   process_Huffman_data_unit(priv, cY);
1508   IDCT(&priv.component_infos[cY], priv.Y.ptr, 16);
1509   process_Huffman_data_unit(priv, cY);
1510   IDCT(&priv.component_infos[cY], priv.Y.ptr+8, 16);
1511   process_Huffman_data_unit(priv, cY);
1512   IDCT(&priv.component_infos[cY], priv.Y.ptr+64*2, 16);
1513   process_Huffman_data_unit(priv, cY);
1514   IDCT(&priv.component_infos[cY], priv.Y.ptr+64*2+8, 16);
1515
1516   // Cb
1517   process_Huffman_data_unit(priv, cCb);
1518   IDCT(&priv.component_infos[cCb], priv.Cb.ptr, 8);
1519
1520   // Cr
1521   process_Huffman_data_unit(priv, cCr);
1522   IDCT(&priv.component_infos[cCr], priv.Cr.ptr, 8);
1523 }
1524
1525 /*
1526  * Decode a 2x2 directly in GREY format (8bits)
1527  *  .-------.
1528  *  | 1 | 2 |
1529  *  |---+---|
1530  *  | 3 | 4 |
1531  *  `-------'
1532  */
1533 private void decode_MCU_2x2_1plane(jdec_private *priv)
1534 {
1535   // Y
1536   process_Huffman_data_unit(priv, cY);
1537   IDCT(&priv.component_infos[cY], priv.Y.ptr, 16);
1538   process_Huffman_data_unit(priv, cY);
1539   IDCT(&priv.component_infos[cY], priv.Y.ptr+8, 16);
1540   process_Huffman_data_unit(priv, cY);
1541   IDCT(&priv.component_infos[cY], priv.Y.ptr+64*2, 16);
1542   process_Huffman_data_unit(priv, cY);
1543   IDCT(&priv.component_infos[cY], priv.Y.ptr+64*2+8, 16);
1544
1545   // Cb
1546   process_Huffman_data_unit(priv, cCb);
1547
1548   // Cr
1549   process_Huffman_data_unit(priv, cCr);
1550 }
1551
1552 /*
1553  * Decode a 1x2 mcu
1554  *  .---.
1555  *  | 1 |
1556  *  |---|
1557  *  | 2 |
1558  *  `---'
1559  */
1560 private void decode_MCU_1x2_3planes(jdec_private *priv)
1561 {
1562   // Y
1563   process_Huffman_data_unit(priv, cY);
1564   IDCT(&priv.component_infos[cY], priv.Y.ptr, 8);
1565   process_Huffman_data_unit(priv, cY);
1566   IDCT(&priv.component_infos[cY], priv.Y.ptr+64, 8);
1567
1568   // Cb
1569   process_Huffman_data_unit(priv, cCb);
1570   IDCT(&priv.component_infos[cCb], priv.Cb.ptr, 8);
1571
1572   // Cr
1573   process_Huffman_data_unit(priv, cCr);
1574   IDCT(&priv.component_infos[cCr], priv.Cr.ptr, 8);
1575 }
1576
1577 /*
1578  * Decode a 1x2 mcu
1579  *  .---.
1580  *  | 1 |
1581  *  |---|
1582  *  | 2 |
1583  *  `---'
1584  */
1585 private void decode_MCU_1x2_1plane(jdec_private *priv)
1586 {
1587   // Y
1588   process_Huffman_data_unit(priv, cY);
1589   IDCT(&priv.component_infos[cY], priv.Y.ptr, 8);
1590   process_Huffman_data_unit(priv, cY);
1591   IDCT(&priv.component_infos[cY], priv.Y.ptr+64, 8);
1592
1593   // Cb
1594   process_Huffman_data_unit(priv, cCb);
1595
1596   // Cr
1597   process_Huffman_data_unit(priv, cCr);
1598 }
1599
1600 private void print_SOF(ubyte *stream)
1601 {
1602   int width, height, nr_components, precision;
1603 /*#if DEBUG
1604   const char *nr_components_to_string[] = {
1605      "????",
1606      "Grayscale",
1607      "????",
1608      "YCbCr",
1609      "CYMK"
1610   };
1611 #endif*/
1612
1613   precision = stream[2];
1614   height = mixin(be16_to_cpu!("stream+3"));
1615   width  = mixin(be16_to_cpu!("stream+5"));
1616   nr_components = stream[7];
1617
1618   trace("> SOF marker\n");
1619   /*trace("Size:%dx%d nr_components:%d (%s)  precision:%d\n",
1620       width, height,
1621       nr_components, nr_components_to_string[nr_components],
1622       precision);*/
1623 }
1624
1625 /*******************************************************************************
1626  *
1627  * JPEG/JFIF Parsing functions
1628  *
1629  * Note: only a small subset of the jpeg file format is supported. No markers,
1630  * nor progressive stream is supported.
1631  *
1632  ******************************************************************************/
1633
1634 private void build_quantization_table(float *qtable, ubyte *ref_table)
1635 {
1636   /* Taken from libjpeg. Copyright Independent JPEG Group's LLM idct.
1637    * For float AA&N IDCT method, divisors are equal to quantization
1638    * coefficients scaled by scalefactor[row]*scalefactor[col], where
1639    *   scalefactor[0] = 1
1640    *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7
1641    * We apply a further scale factor of 8.
1642    * What's actually stored is 1/divisor so that the inner loop can
1643    * use a multiplication rather than a division.
1644    */
1645   int i, j;
1646   static const double aanscalefactor[8] = [
1647      1.0, 1.387039845, 1.306562965, 1.175875602,
1648      1.0, 0.785694958, 0.541196100, 0.275899379
1649   ];
1650   ubyte *zz = zigzag.ptr;
1651
1652   for (i=0; i<8; i++) {
1653      for (j=0; j<8; j++) {
1654        *qtable++ = ref_table[*zz++] * aanscalefactor[i] * aanscalefactor[j];
1655      }
1656    }
1657
1658 }
1659
1660 private int parse_DQT(jdec_private *priv, ubyte *stream)
1661 {
1662   int qi;
1663   float *table;
1664   ubyte *dqt_block_end;
1665
1666   trace("> DQT marker\n");
1667   dqt_block_end = stream + mixin(be16_to_cpu!("stream"));
1668   stream += 2;  /* Skip length */
1669
1670   while (stream < dqt_block_end)
1671    {
1672      qi = *stream++;
1673 static if (SANITY_CHECK) {
1674      if (qi>>>4)
1675        return error(priv,"16 bits quantization table is not supported\n");
1676      if (qi>4)
1677        return error(priv,format("No more 4 quantization table is supported (got ",qi,")\n"));
1678 }
1679      table = priv.Q_tables[qi].ptr;
1680      build_quantization_table(table, stream);
1681      stream += 64;
1682    }
1683   trace("< DQT marker\n");
1684   return 0;
1685 }
1686
1687 private int parse_SOF(jdec_private *priv, ubyte *stream)
1688 {
1689   int i, width, height, nr_components, cid, sampling_factor;
1690   int Q_table;
1691   component *c;
1692
1693   trace("> SOF marker\n");
1694   print_SOF(stream);
1695
1696   height = mixin(be16_to_cpu!("stream+3"));
1697   width  = mixin(be16_to_cpu!("stream+5"));
1698   nr_components = stream[7];
1699
1700 static if (SANITY_CHECK) {
1701   if (stream[2] != 8)
1702     return error(priv,"Precision other than 8 is not supported\n");
1703   if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT)
1704     return error(priv,format("Width and Height (%dx%d) seems suspicious\n", width, height));
1705   if (nr_components != 3)
1706     return error(priv,"We only support YUV images\n");
1707   if (height%16)
1708     return error(priv,format("Height need to be a multiple of 16 (current height is ",height," )\n"));
1709   if (width%16)
1710     return error(priv,format("Width need to be a multiple of 16 (current Width is ",width,")\n"));
1711 }
1712   stream += 8;
1713   for (i=0; i<nr_components; i++) {
1714      cid = *stream++;
1715      sampling_factor = *stream++;
1716      Q_table = *stream++;
1717      c = &priv.component_infos[i];
1718 static if (SANITY_CHECK) {
1719      c.cid = cid;
1720      if (Q_table >= COMPONENTS) {
1721        return error(priv,format("Bad Quantization table index (got ", Q_table, " max allowed ", COMPONENTS-1,")\n"));
1722      }
1723 }
1724      c.Vfactor = sampling_factor&0xf;
1725      c.Hfactor = sampling_factor>>>4;
1726      c.Q_table = priv.Q_tables[Q_table].ptr;
1727      trace("Component:",cid,"  factor:",c.Hfactor,"x",c.Hfactor,"  Quantization table:",Q_table,"\n");
1728   }
1729   priv.width = width;
1730   priv.height = height;
1731
1732   trace("< SOF marker\n");
1733
1734   return 0;
1735 }
1736
1737 private int parse_SOS(jdec_private *priv, ubyte *stream)
1738 {
1739   uint i, cid, table;
1740   uint nr_components = stream[2];
1741
1742   trace("> SOS marker\n");
1743
1744 static if (SANITY_CHECK) {
1745   if (nr_components != 3)
1746     return error(priv,"We only support YCbCr image\n");
1747 }
1748
1749   stream += 3;
1750   for (i=0;i<nr_components;i++) {
1751      cid = *stream++;
1752      table = *stream++;
1753 static if (SANITY_CHECK) {
1754      if ((table&0xf)>=4)
1755        return error(priv,"We do not support more than 2 AC Huffman table\n");
1756      if ((table>>>4)>=4)
1757        return error(priv,"We do not support more than 2 DC Huffman table\n");
1758      if (cid != priv.component_infos[i].cid)
1759        return error(priv,format("SOS cid order (",i,":",cid,") isn't compatible with the SOF marker (",i,":",priv.component_infos[i].cid,")\n"));
1760      trace("ComponentId:",cid,"  tableAC:",table&0xf," tableDC:",table>>>4,"\n");
1761 }
1762      priv.component_infos[i].AC_table = &priv.HTAC[table&0xf];
1763      priv.component_infos[i].DC_table = &priv.HTDC[table>>>4];
1764   }
1765   priv.stream = stream+3;
1766   trace("< SOS marker\n");
1767   return 0;
1768 }
1769
1770 private int parse_DHT(jdec_private *priv, ubyte *stream)
1771 {
1772   uint count, i;
1773   ubyte huff_bits[17];
1774   int length, index;
1775
1776   length = mixin(be16_to_cpu!("stream")) - 2;
1777   stream += 2;  /* Skip length */
1778
1779   trace("> DHT marker (length=",length,")\n");
1780
1781   while (length>0) {
1782      index = *stream++;
1783
1784      /* We need to calculate the number of bytes 'vals' will takes */
1785      huff_bits[0] = 0;
1786      count = 0;
1787      for (i=1; i<17; i++) {
1788     huff_bits[i] = *stream++;
1789     count += huff_bits[i];
1790      }
1791 static if (SANITY_CHECK) {
1792      if (count >= HUFFMAN_BITS_SIZE)
1793        return error(priv,format("No more than ",HUFFMAN_BITS_SIZE," bytes is allowed to describe a huffman table\n"));
1794      if ( (index &0xf) >= HUFFMAN_TABLES)
1795        return error(priv,format("No more than ",HUFFMAN_TABLES," Huffman tables is supported (got ",index%0xf,")\n"));
1796      trace("Huffman table ",(index&0xf0)?"AC":"DC","[",index&0xf,"] length=",count,"\n");
1797 }
1798
1799      if (index & 0xf0 )
1800        build_huffman_table(huff_bits.ptr, stream, &priv.HTAC[index&0xf]);
1801      else
1802        build_huffman_table(huff_bits.ptr, stream, &priv.HTDC[index&0xf]);
1803
1804      length -= 1;
1805      length -= 16;
1806      length -= count;
1807      stream += count;
1808   }
1809   trace("< DHT marker\n");
1810   return 0;
1811 }
1812
1813 private int parse_DRI(jdec_private *priv, ubyte *stream)
1814 {
1815   uint length;
1816
1817   trace("> DRI marker\n");
1818
1819   length = mixin(be16_to_cpu!("stream"));
1820
1821 static if (SANITY_CHECK) {
1822   if (length != 4)
1823     return error(priv,"Length of DRI marker need to be 4\n");
1824 }
1825
1826   priv.restart_interval = mixin(be16_to_cpu!("stream+2"));
1827
1828 debug {
1829   trace("Restart interval = ",priv.restart_interval,"\n");
1830 }
1831
1832   trace("< DRI marker\n");
1833
1834   return 0;
1835 }
1836
1837
1838
1839 private void resync(jdec_private *priv)
1840 {
1841   int i;
1842
1843   /* Init DC coefficients */
1844   for (i=0; i<COMPONENTS; i++)
1845      priv.component_infos[i].previous_DC = 0;
1846
1847   priv.reservoir = 0;
1848   priv.nbits_in_reservoir = 0;
1849   if (priv.restart_interval > 0)
1850     priv.restarts_to_go = priv.restart_interval;
1851   else
1852     priv.restarts_to_go = -1;
1853 }
1854
1855 private int find_next_rst_marker(jdec_private *priv)
1856 {
1857   int rst_marker_found = 0;
1858   int marker;
1859   ubyte *stream = priv.stream;
1860
1861   /* Parse marker */
1862   while (!rst_marker_found)
1863    {
1864      while (*stream++ != 0xff)
1865       {
1866     if (stream >= priv.stream_end)
1867       return error(priv,"EOF while search for a RST marker.");
1868       }
1869      /* Skip any padding ff byte (this is normal) */
1870      while (*stream == 0xff)
1871        stream++;
1872
1873      marker = *stream++;
1874      if ((RST+priv.last_rst_marker_seen) == marker)
1875        rst_marker_found = 1;
1876      else if (marker >= RST && marker <= RST7)
1877        return error(priv,"Wrong Reset marker found, aborting");
1878      else if (marker == EOI)
1879        return 0;
1880    }
1881   trace("RST Marker ",priv.last_rst_marker_seen," found at offset ",stream - priv.stream_begin,"\n");
1882
1883   priv.stream = stream;
1884   priv.last_rst_marker_seen++;
1885   priv.last_rst_marker_seen &= 7;
1886
1887   return 0;
1888 }
1889
1890 private int parse_JFIF(jdec_private *priv, ubyte *stream)
1891 {
1892   int chuck_len;
1893   int marker;
1894   int sos_marker_found = 0;
1895   int dht_marker_found = 0;
1896   ubyte *next_chunck;
1897
1898   /* Parse marker */
1899   while (!sos_marker_found)
1900    {
1901      if (*stream++ != 0xff)
1902        goto bogus_jpeg_format;
1903      /* Skip any padding ff byte (this is normal) */
1904      while (*stream == 0xff)
1905        stream++;
1906
1907      marker = *stream++;
1908      chuck_len = mixin(be16_to_cpu!("stream"));
1909      next_chunck = stream + chuck_len;
1910      switch (marker)
1911       {
1912        case SOF:
1913      if (parse_SOF(priv, stream) < 0)
1914        return -1;
1915      break;
1916        case DQT:
1917      if (parse_DQT(priv, stream) < 0)
1918        return -1;
1919      break;
1920        case SOS:
1921      if (parse_SOS(priv, stream) < 0)
1922        return -1;
1923      sos_marker_found = 1;
1924      break;
1925        case DHT:
1926      if (parse_DHT(priv, stream) < 0)
1927        return -1;
1928      dht_marker_found = 1;
1929      break;
1930        case DRI:
1931      if (parse_DRI(priv, stream) < 0)
1932        return -1;
1933      break;
1934        default:
1935      trace("> Unknown marker ",marker,"\n");
1936      break;
1937       }
1938
1939      stream = next_chunck;
1940    }
1941
1942   if (!dht_marker_found) {
1943     trace("No Huffman table loaded, using the default one\n");
1944     build_default_huffman_tables(priv);
1945   }
1946
1947 static if (SANITY_CHECK) {
1948   if (   (priv.component_infos[cY].Hfactor < priv.component_infos[cCb].Hfactor)
1949       || (priv.component_infos[cY].Hfactor < priv.component_infos[cCr].Hfactor))
1950     return error(priv,"Horizontal sampling factor for Y should be greater than horitontal sampling factor for Cb or Cr\n");
1951   if (   (priv.component_infos[cY].Vfactor < priv.component_infos[cCb].Vfactor)
1952       || (priv.component_infos[cY].Vfactor < priv.component_infos[cCr].Vfactor))
1953     return error(priv,"Vertical sampling factor for Y should be greater than vertical sampling factor for Cb or Cr\n");
1954   if (   (priv.component_infos[cCb].Hfactor!=1)
1955       || (priv.component_infos[cCr].Hfactor!=1)
1956       || (priv.component_infos[cCb].Vfactor!=1)
1957       || (priv.component_infos[cCr].Vfactor!=1))
1958     return error(priv,"Sampling other than 1x1 for Cr and Cb is not supported");
1959 }
1960
1961   return 0;
1962 bogus_jpeg_format:
1963   trace("Bogus jpeg format\n");
1964   return -1;
1965 }
1966
1967 /*******************************************************************************
1968  *
1969  * Functions exported of the library.
1970  *
1971  * Note: Some applications can access directly to internal pointer of the
1972  * structure. It's is not recommended, but if you have many images to
1973  * uncompress with the same parameters, some functions can be called to speedup
1974  * the decoding.
1975  *
1976  ******************************************************************************/
1977
1978 /**
1979  * Allocate a new tinyjpeg decoder object.
1980  *
1981  * Before calling any other functions, an object need to be called.
1982  */
1983 jdec_private *tinyjpeg_init()
1984 {
1985   jdec_private *priv;
1986
1987   priv = cast(jdec_private *)calloc(1, jdec_private.sizeof);
1988   if (priv is null)
1989     return null;
1990   return priv;
1991 }
1992
1993 /**
1994  * Free a tinyjpeg object.
1995  *
1996  * No others function can be called after this one.
1997  */
1998 void tinyjpeg_free(jdec_private *priv)
1999 {
2000   int i;
2001   for (i=0; i<COMPONENTS; i++) {
2002      if (priv.components[i])
2003        free(priv.components[i]);
2004      priv.components[i] = null;
2005   }
2006   free(priv);
2007 }
2008
2009 /**
2010  * Initialize the tinyjpeg object and prepare the decoding of the stream.
2011  *
2012  * Check if the jpeg can be decoded with this jpeg decoder.
2013  * Fill some table used for preprocessing.
2014  */
2015 int tinyjpeg_parse_header(jdec_private *priv, ubyte *buf, uint size)
2016 {
2017   int ret;
2018
2019   /* Identify the file */
2020   if ((buf[0] != 0xFF) || (buf[1] != SOI))
2021     return error(priv,"Not a JPG file ?\n");
2022
2023   priv.stream_begin = buf+2;
2024   priv.stream_length = size-2;
2025   priv.stream_end = priv.stream_begin + priv.stream_length;
2026
2027   ret = parse_JFIF(priv, priv.stream_begin);
2028
2029   return ret;
2030 }
2031
2032 private const decode_MCU_fct decode_mcu_3comp_table[4] = [
2033    &decode_MCU_1x1_3planes,
2034    &decode_MCU_1x2_3planes,
2035    &decode_MCU_2x1_3planes,
2036    &decode_MCU_2x2_3planes,
2037 ];
2038
2039 private const decode_MCU_fct decode_mcu_1comp_table[4] = [
2040    &decode_MCU_1x1_1plane,
2041    &decode_MCU_1x2_1plane,
2042    &decode_MCU_2x1_1plane,
2043    &decode_MCU_2x2_1plane,
2044 ];
2045
2046 private const convert_colorspace_fct convert_colorspace_yuv420p[4] = [
2047    &YCrCB_to_YUV420P_1x1,
2048    &YCrCB_to_YUV420P_1x2,
2049    &YCrCB_to_YUV420P_2x1,
2050    &YCrCB_to_YUV420P_2x2,
2051 ];
2052
2053 private const convert_colorspace_fct convert_colorspace_rgb24[4] = [
2054    &YCrCB_to_RGB24_1x1,
2055    &YCrCB_to_RGB24_1x2,
2056    &YCrCB_to_RGB24_2x1,
2057    &YCrCB_to_RGB24_2x2,
2058 ];
2059
2060 private const convert_colorspace_fct convert_colorspace_bgr24[4] = [
2061    &YCrCB_to_BGR24_1x1,
2062    &YCrCB_to_BGR24_1x2,
2063    &YCrCB_to_BGR24_2x1,
2064    &YCrCB_to_BGR24_2x2,
2065 ];
2066
2067 private const convert_colorspace_fct convert_colorspace_grey[4] = [
2068    &YCrCB_to_Grey_1x1,
2069    &YCrCB_to_Grey_1x2,
2070    &YCrCB_to_Grey_2x1,
2071    &YCrCB_to_Grey_2x2,
2072 ];
2073
2074 /**
2075  * Decode and convert the jpeg image into @pixfmt@ image
2076  *
2077  * Note: components will be automaticaly allocated if no memory is attached.
2078  */
2079 int tinyjpeg_decode(jdec_private *priv, int pixfmt)
2080 {
2081   uint x, y, xstride_by_mcu, ystride_by_mcu;
2082   uint[3] bytes_per_blocklines, bytes_per_mcu;
2083   decode_MCU_fct decode_MCU;
2084   decode_MCU_fct *decode_mcu_table;
2085   convert_colorspace_fct *colorspace_array_conv;
2086   convert_colorspace_fct convert_to_pixfmt;
2087
2088   /*if (setjmp(priv.jump_state))
2089     return -1;*/
2090   try {
2091
2092   /* To keep gcc happy initialize some array */
2093   bytes_per_mcu[1] = 0;
2094   bytes_per_mcu[2] = 0;
2095   bytes_per_blocklines[1] = 0;
2096   bytes_per_blocklines[2] = 0;
2097
2098   decode_mcu_table = decode_mcu_3comp_table.ptr;
2099   switch (pixfmt) {
2100      case TINYJPEG_FMT_YUV420P:
2101        colorspace_array_conv = convert_colorspace_yuv420p.ptr;
2102        if (priv.components[0] is null)
2103      priv.components[0] = cast(uint8_t *)malloc(priv.width * priv.height);
2104        if (priv.components[1] is null)
2105      priv.components[1] = cast(uint8_t *)malloc(priv.width * priv.height/4);
2106        if (priv.components[2] is null)
2107      priv.components[2] = cast(uint8_t *)malloc(priv.width * priv.height/4);
2108        bytes_per_blocklines[0] = priv.width;
2109        bytes_per_blocklines[1] = priv.width/4;
2110        bytes_per_blocklines[2] = priv.width/4;
2111        bytes_per_mcu[0] = 8;
2112        bytes_per_mcu[1] = 4;
2113        bytes_per_mcu[2] = 4;
2114        break;
2115
2116      case TINYJPEG_FMT_RGB24:
2117        colorspace_array_conv = convert_colorspace_rgb24.ptr;
2118        if (priv.components[0] is null)
2119      priv.components[0] = cast(uint8_t *)malloc(priv.width * priv.height * 3);
2120        bytes_per_blocklines[0] = priv.width * 3;
2121        bytes_per_mcu[0] = 3*8;
2122        break;
2123
2124      case TINYJPEG_FMT_BGR24:
2125        colorspace_array_conv = convert_colorspace_bgr24.ptr;
2126        if (priv.components[0] is null)
2127      priv.components[0] = cast(uint8_t *)malloc(priv.width * priv.height * 3);
2128        bytes_per_blocklines[0] = priv.width * 3;
2129        bytes_per_mcu[0] = 3*8;
2130        break;
2131
2132      case TINYJPEG_FMT_GREY:
2133        decode_mcu_table = decode_mcu_1comp_table.ptr;
2134        colorspace_array_conv = convert_colorspace_grey.ptr;
2135        if (priv.components[0] is null)
2136      priv.components[0] = cast(uint8_t *)malloc(priv.width * priv.height);
2137        bytes_per_blocklines[0] = priv.width;
2138        bytes_per_mcu[0] = 8;
2139        break;
2140
2141      default:
2142        trace("Bad pixel format\n");
2143        return -1;
2144   }
2145
2146   xstride_by_mcu = ystride_by_mcu = 8;
2147   if ((priv.component_infos[cY].Hfactor | priv.component_infos[cY].Vfactor) == 1) {
2148      decode_MCU = decode_mcu_table[0];
2149      convert_to_pixfmt = colorspace_array_conv[0];
2150      trace("Use decode 1x1 sampling\n");
2151   } else if (priv.component_infos[cY].Hfactor == 1) {
2152      decode_MCU = decode_mcu_table[1];
2153      convert_to_pixfmt = colorspace_array_conv[1];
2154      ystride_by_mcu = 16;
2155      trace("Use decode 1x2 sampling (not supported)\n");
2156   } else if (priv.component_infos[cY].Vfactor == 2) {
2157      decode_MCU = decode_mcu_table[3];
2158      convert_to_pixfmt = colorspace_array_conv[3];
2159      xstride_by_mcu = 16;
2160      ystride_by_mcu = 16;
2161      trace("Use decode 2x2 sampling\n");
2162   } else {
2163      decode_MCU = decode_mcu_table[2];
2164      convert_to_pixfmt = colorspace_array_conv[2];
2165      xstride_by_mcu = 16;
2166      trace("Use decode 2x1 sampling\n");
2167   }
2168
2169   resync(priv);
2170
2171   /* Don't forget to that block can be either 8 or 16 lines */
2172   bytes_per_blocklines[0] *= ystride_by_mcu;
2173   bytes_per_blocklines[1] *= ystride_by_mcu;
2174   bytes_per_blocklines[2] *= ystride_by_mcu;
2175
2176   bytes_per_mcu[0] *= xstride_by_mcu/8;
2177   bytes_per_mcu[1] *= xstride_by_mcu/8;
2178   bytes_per_mcu[2] *= xstride_by_mcu/8;
2179
2180   /* Just the decode the image by macroblock (size is 8x8, 8x16, or 16x16) */
2181   for (y=0; y < priv.height/ystride_by_mcu; y++)
2182    {
2183      //trace("Decoding row %d\n", y);
2184      priv.plane[0] = priv.components[0] + (y * bytes_per_blocklines[0]);
2185      priv.plane[1] = priv.components[1] + (y * bytes_per_blocklines[1]);
2186      priv.plane[2] = priv.components[2] + (y * bytes_per_blocklines[2]);
2187      for (x=0; x < priv.width; x+=xstride_by_mcu)
2188       {
2189     decode_MCU(priv);
2190     convert_to_pixfmt(priv);
2191     priv.plane[0] += bytes_per_mcu[0];
2192     priv.plane[1] += bytes_per_mcu[1];
2193     priv.plane[2] += bytes_per_mcu[2];
2194     if (priv.restarts_to_go>0)
2195      {
2196        priv.restarts_to_go--;
2197        if (priv.restarts_to_go == 0)
2198         {
2199           priv.stream -= (priv.nbits_in_reservoir/8);
2200           resync(priv);
2201           if (find_next_rst_marker(priv) < 0)
2202         return -1;
2203         }
2204      }
2205       }
2206    }
2207   }
2208   catch(TinyJpegException e)
2209   {
2210     return -1;
2211   }
2212
2213   trace("Input file size: ",priv.stream_length+2,"\n");
2214   trace("Input bytes actually read: ",priv.stream - priv.stream_begin + 2,"\n");
2215   return 0;
2216 }
2217
2218 char[] tinyjpeg_get_errorstring(jdec_private *priv)
2219 {
2220   return priv.error_string;
2221 }
2222
2223 void tinyjpeg_get_size(jdec_private *priv, uint *width, uint *height)
2224 {
2225   *width = priv.width;
2226   *height = priv.height;
2227 }
2228
2229 int tinyjpeg_get_components(jdec_private *priv, ubyte **components)
2230 {
2231   int i;
2232   for (i=0; priv.components[i] && i<COMPONENTS; i++)
2233     components[i] = priv.components[i];
2234   return 0;
2235 }
2236
2237 int tinyjpeg_set_components(jdec_private *priv, ubyte **components, uint ncomponents)
2238 {
2239   uint i;
2240   if (ncomponents > COMPONENTS)
2241     ncomponents = COMPONENTS;
2242   for (i=0; i<ncomponents; i++)
2243     priv.components[i] = components[i];
2244   return 0;
2245 }
2246
2247 int tinyjpeg_set_flags(jdec_private *priv, int flags)
2248 {
2249   int oldflags = priv.flags;
2250   priv.flags = flags;
2251   return oldflags;
2252 }
Note: See TracBrowser for help on using the browser.