annotate VSs_tinyjpeg/tinyjpeg.c @ 4:62350c40504f

running in sequential mode
author Nina Engelhardt <nengel@mailbox.tu-berlin.de>
date Mon, 20 Aug 2012 16:56:27 +0200
parents 7e13c9ecc89c
children
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 }