2
#include "LJpegDecompressor.h"
3
#include "ByteStreamSwap.h"
6
RawSpeed - RAW file decoder.
8
Copyright (C) 2009 Klaus Post
10
This library is free software; you can redistribute it and/or
11
modify it under the terms of the GNU Lesser General Public
12
License as published by the Free Software Foundation; either
13
version 2 of the License, or (at your option) any later version.
15
This library is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
Lesser General Public License for more details.
20
You should have received a copy of the GNU Lesser General Public
21
License along with this library; if not, write to the Free Software
22
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
http://www.klauspost.com
28
* Huffman table generation:
29
* LJpegDecompressor::HuffDecode,
30
* LJpegDecompressor::createHuffmanTable
31
* and used data structures are originally grabbed from the IJG software,
32
* and adapted by Hubert Figuiere.
34
* Copyright (C) 1991, 1992, Thomas G. Lane.
35
* Part of the Independent JPEG Group's software.
36
* See the file Copyright for more details.
38
* Copyright (c) 1993 Brian C. Smith, The Regents of the University
40
* All rights reserved.
42
* Copyright (c) 1994 Kongji Huang and Brian C. Smith.
44
* All rights reserved.
46
* Permission to use, copy, modify, and distribute this software and its
47
* documentation for any purpose, without fee, and without written agreement is
48
* hereby granted, provided that the above copyright notice and the following
49
* two paragraphs appear in all copies of this software.
51
* IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
52
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
53
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
54
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56
* CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
57
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
58
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
59
* ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
60
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
65
const uint32 bitMask[] = { 0xffffffff, 0x7fffffff,
66
0x3fffffff, 0x1fffffff,
67
0x0fffffff, 0x07ffffff,
68
0x03ffffff, 0x01ffffff,
69
0x00ffffff, 0x007fffff,
70
0x003fffff, 0x001fffff,
71
0x000fffff, 0x0007ffff,
72
0x0003ffff, 0x0001ffff,
73
0x0000ffff, 0x00007fff,
74
0x00003fff, 0x00001fff,
75
0x00000fff, 0x000007ff,
76
0x000003ff, 0x000001ff,
77
0x000000ff, 0x0000007f,
78
0x0000003f, 0x0000001f,
79
0x0000000f, 0x00000007,
80
0x00000003, 0x00000001
83
LJpegDecompressor::LJpegDecompressor(FileMap* file, RawImage img):
84
mFile(file), mRaw(img) {
87
for (int i = 0; i < 4; i++) {
88
huff[i].initialized = false;
91
mDNGCompatible = false;
96
LJpegDecompressor::~LJpegDecompressor(void) {
100
for (int i = 0; i < 4; i++) {
101
if (huff[i].bigTable)
102
_aligned_free(huff[i].bigTable);
107
void LJpegDecompressor::getSOF(SOFInfo* sof, uint32 offset, uint32 size) {
108
if (!mFile->isValid(offset + size - 1))
109
ThrowRDE("LJpegDecompressor::getSOF: Start offset plus size is longer than file. Truncated file.");
111
Endianness host_endian = getHostEndianness();
112
// JPEG is big endian
113
if (host_endian == big)
114
input = new ByteStream(mFile->getData(offset), size);
116
input = new ByteStreamSwap(mFile->getData(offset), size);
118
if (getNextMarker(false) != M_SOI)
119
ThrowRDE("LJpegDecompressor::getSOF: Image did not start with SOI. Probably not an LJPEG");
122
JpegMarker m = getNextMarker(true);
128
ThrowRDE("LJpegDecompressor: Could not locate Start of Frame.");
132
} catch (IOException) {
133
ThrowRDE("LJpegDecompressor: IO exception, read outside file. Corrupt File.");
137
void LJpegDecompressor::startDecoder(uint32 offset, uint32 size, uint32 offsetX, uint32 offsetY) {
138
if (!mFile->isValid(offset + size - 1))
139
ThrowRDE("LJpegDecompressor::startDecoder: Start offset plus size is longer than file. Truncated file.");
140
if ((int)offsetX >= mRaw->dim.x)
141
ThrowRDE("LJpegDecompressor::startDecoder: X offset outside of image");
142
if ((int)offsetY >= mRaw->dim.y)
143
ThrowRDE("LJpegDecompressor::startDecoder: Y offset outside of image");
148
Endianness host_endian = getHostEndianness();
149
// JPEG is big endian
150
if (host_endian == big)
151
input = new ByteStream(mFile->getData(offset), size);
153
input = new ByteStreamSwap(mFile->getData(offset), size);
155
if (getNextMarker(false) != M_SOI)
156
ThrowRDE("LJpegDecompressor::startDecoder: Image did not start with SOI. Probably not an LJPEG");
157
// _RPT0(0,"Found SOI marker\n");
159
bool moreImage = true;
161
JpegMarker m = getNextMarker(true);
165
// _RPT0(0,"Found SOS marker\n");
169
// _RPT0(0,"Found EOI marker\n");
174
// _RPT0(0,"Found DHT marker\n");
179
ThrowRDE("LJpegDecompressor: Not a valid RAW file.");
183
// _RPT0(0,"Found DRI marker\n");
187
// _RPT0(0,"Found APP0 marker\n");
191
// _RPT0(0,"Found SOF 3 marker:\n");
195
default: // Just let it skip to next marker
196
_RPT1(0, "Found marker:0x%x. Skipping\n", (int)m);
201
} catch (IOException) {
206
void LJpegDecompressor::parseSOF(SOFInfo* sof) {
207
uint32 headerLength = input->getShort();
208
sof->prec = input->getByte();
209
sof->h = input->getShort();
210
sof->w = input->getShort();
212
sof->cps = input->getByte();
215
ThrowRDE("LJpegDecompressor: More than 16 bits per channel is not supported.");
217
if (sof->cps > 4 || sof->cps < 2)
218
ThrowRDE("LJpegDecompressor: Only from 2 to 4 components are supported.");
220
if (headerLength != 8 + sof->cps*3)
221
ThrowRDE("LJpegDecompressor: Header size mismatch.");
223
for (uint32 i = 0; i < sof->cps; i++) {
224
sof->compInfo[i].componentId = input->getByte();
225
uint32 subs = input->getByte();
226
frame.compInfo[i].superV = subs & 0xf;
227
frame.compInfo[i].superH = subs >> 4;
228
uint32 Tq = input->getByte();
230
ThrowRDE("LJpegDecompressor: Quantized components not supported.");
232
sof->initialized = true;
235
void LJpegDecompressor::parseSOS() {
236
if (!frame.initialized)
237
ThrowRDE("LJpegDecompressor::parseSOS: Frame not yet initialized (SOF Marker not parsed)");
239
uint32 headerLength = input->getShort();
240
uint32 soscps = input->getByte();
241
if (frame.cps != soscps)
242
ThrowRDE("LJpegDecompressor::parseSOS: Component number mismatch.");
244
for (uint32 i = 0;i < frame.cps;i++) {
245
uint32 cs = input->getByte();
247
uint32 count = 0; // Find the correct component
248
while (frame.compInfo[count].componentId != cs) {
249
if (count >= frame.cps)
250
ThrowRDE("LJpegDecompressor::parseSOS: Invalid Component Selector");
254
uint32 b = input->getByte();
257
ThrowRDE("LJpegDecompressor::parseSOS: Invalid Huffman table selection");
258
if (!huff[td].initialized)
259
ThrowRDE("LJpegDecompressor::parseSOS: Invalid Huffman table selection, not defined.");
262
ThrowRDE("LJpegDecompressor::parseSOS: Component count out of range");
264
frame.compInfo[count].dcTblNo = td;
268
pred = input->getByte();
270
ThrowRDE("LJpegDecompressor::parseSOS: Invalid predictor mode.");
272
input->skipBytes(1); // Se + Ah Not used in LJPEG
273
uint32 b = input->getByte();
274
Pt = b & 0xf; // Point Transform
276
uint32 cheadersize = 3 + frame.cps * 2 + 3;
277
_ASSERTE(cheadersize == headerLength);
279
bits = new BitPumpJPEG(input);
286
input->skipBytes(bits->getOffset());
290
void LJpegDecompressor::parseDHT() {
291
uint32 headerLength = input->getShort() - 2; // Subtract myself
293
while (headerLength) {
294
uint32 b = input->getByte();
296
uint32 Tc = (b >> 4);
298
ThrowRDE("LJpegDecompressor::parseDHT: Unsupported Table class.");
302
ThrowRDE("LJpegDecompressor::parseDHT: Invalid huffman table destination id.");
305
HuffmanTable* t = &huff[Th];
308
ThrowRDE("LJpegDecompressor::parseDHT: Duplicate table definition");
310
for (uint32 i = 0; i < 16 ;i++) {
311
t->bits[i+1] = input->getByte();
315
memset(t->huffval, 0, sizeof(t->huffval));
317
ThrowRDE("LJpegDecompressor::parseDHT: Invalid DHT table.");
319
if (headerLength < 1 + 16 + acc)
320
ThrowRDE("LJpegDecompressor::parseDHT: Invalid DHT table length.");
322
for (uint32 i = 0 ; i < acc; i++) {
323
t->huffval[i] = input->getByte();
325
createHuffmanTable(t);
326
headerLength -= 1 + 16 + acc;
331
JpegMarker LJpegDecompressor::getNextMarker(bool allowskip) {
334
uchar8 id = input->getByte();
336
ThrowRDE("LJpegDecompressor::getNextMarker: (Noskip) Expected marker not found. Propably corrupt file.");
338
JpegMarker mark = (JpegMarker)input->getByte();
340
if (M_FILL == mark || M_STUFF == mark)
341
ThrowRDE("LJpegDecompressor::getNextMarker: (Noskip) Expected marker, but found stuffed 00 or ff.");
345
input->skipToMarker();
346
uchar8 id = input->getByte();
347
_ASSERTE(0xff == id);
348
JpegMarker mark = (JpegMarker)input->getByte();
352
void LJpegDecompressor::createHuffmanTable(HuffmanTable *htbl) {
353
int p, i, l, lastp, si;
355
ushort16 huffcode[257];
361
* Figure C.1: make table of Huffman code length for each symbol
362
* Note that this is in code-length order.
365
for (l = 1; l <= 16; l++) {
366
for (i = 1; i <= (int)htbl->bits[l]; i++) {
367
huffsize[p++] = (char)l;
369
ThrowRDE("LJpegDecompressor::createHuffmanTable: Code length too long. Corrupt data.");
377
* Figure C.2: generate the codes themselves
378
* Note that this is in code-length order.
383
while (huffsize[p]) {
384
while (((int)huffsize[p]) == si) {
385
huffcode[p++] = code;
391
ThrowRDE("createHuffmanTable: Code length too long. Corrupt data.");
396
* Figure F.15: generate decoding tables
398
htbl->mincode[0] = 0;
399
htbl->maxcode[0] = 0;
401
for (l = 1; l <= 16; l++) {
404
htbl->mincode[l] = huffcode[p];
406
htbl->maxcode[l] = huffcode[p - 1];
408
htbl->valptr[l] = 0xff; // This check must be present to avoid crash on junk
409
htbl->maxcode[l] = -1;
412
ThrowRDE("createHuffmanTable: Code length too long. Corrupt data.");
416
* We put in this value to ensure HuffDecode terminates.
418
htbl->maxcode[17] = 0xFFFFFL;
421
* Build the numbits, value lookup tables.
422
* These table allow us to gather 8 bits from the bits stream,
423
* and immediately lookup the size and value of the huffman codes.
424
* If size is zero, it means that more than 8 bits are in the huffman
425
* code (this happens about 3-4% of the time).
427
memset(htbl->numbits, 0, sizeof(htbl->numbits));
428
for (p = 0; p < lastp; p++) {
431
value = htbl->huffval[p];
433
ll = code << (8 - size);
435
ul = ll | bitMask[24+size];
439
if (ul > 256 || ll > ul)
440
ThrowRDE("createHuffmanTable: Code length too long. Corrupt data.");
441
for (i = ll; i <= ul; i++) {
442
htbl->numbits[i] = size | (value << 4);
447
createBigTable(htbl);
448
htbl->initialized = true;
451
/************************************
454
* This is expanding the concept of fast lookups
456
* A complete table for 14 arbitrary bits will be
457
* created that enables fast lookup of number of bits used,
458
* and final delta result.
459
* Hit rate is about 90-99% for typical LJPEGS, usually about 98%
461
************************************/
463
void LJpegDecompressor::createBigTable(HuffmanTable *htbl) {
464
const uint32 bits = 14; // HuffDecode functions must be changed, if this is modified.
465
const uint32 size = 1 << bits;
470
htbl->bigTable = (int*)_aligned_malloc(size * sizeof(int), 16);
472
ThrowRDE("Out of memory, failed to allocate %d bytes", size*sizeof(int));
473
for (uint32 i = 0; i < size; i++) {
474
ushort16 input = i << 2; // Calculate input value
475
int code = input >> 8; // Get 8 bits
476
uint32 val = htbl->numbits[code];
482
while (code > htbl->maxcode[l]) {
483
temp = input >> (15 - l) & 1;
484
code = (code << 1) | temp;
489
* With garbage input we may reach the sentinel value l = 17.
492
if (l > frame.prec || htbl->valptr[l] == 0xff) {
493
htbl->bigTable[i] = 0xff;
496
rv = htbl->huffval[htbl->valptr[l] +
497
((int)(code - htbl->mincode[l]))];
504
htbl->bigTable[i] = (-32768 << 8) | (16 + l);
506
htbl->bigTable[i] = (-32768 << 8) | l;
511
htbl->bigTable[i] = 0xff;
516
int x = input >> (16 - l - rv) & ((1 << rv) - 1);
517
if ((x & (1 << (rv - 1))) == 0)
519
htbl->bigTable[i] = (x << 8) | (l + rv);
521
htbl->bigTable[i] = l;
528
*--------------------------------------------------------------
532
* Taken from Figure F.16: extract next coded symbol from
533
* input stream. This should becode a macro.
539
* Bitstream is parsed.
541
*--------------------------------------------------------------
543
int LJpegDecompressor::HuffDecode(HuffmanTable *htbl) {
549
* First attempt to do complete decode, by using the first 14 bits
553
code = bits->peekBitsNoFill(14);
554
if (htbl->bigTable) {
555
val = htbl->bigTable[code];
556
if ((val&0xff) != 0xff) {
557
bits->skipBitsNoFill(val&0xff);
562
* If the huffman code is less than 8 bits, we can use the fast
563
* table lookup to get its value. It's more than 8 bits about
568
val = htbl->numbits[code];
571
bits->skipBitsNoFill(l);
574
bits->skipBitsNoFill(8);
576
while (code > htbl->maxcode[l]) {
577
temp = bits->getBitNoFill();
578
code = (code << 1) | temp;
583
* With garbage input we may reach the sentinel value l = 17.
586
if (l > frame.prec || htbl->valptr[l] == 0xff) {
587
ThrowRDE("Corrupt JPEG data: bad Huffman code:%u", l);
589
rv = htbl->huffval[htbl->valptr[l] +
590
((int)(code - htbl->mincode[l]))];
596
bits->skipBitsNoFill(16);
600
// Ensure we have enough bits
602
if (rv > 16) // There is no values above 16 bits.
603
ThrowRDE("Corrupt JPEG data: Too many bits requested.");
609
* Section F.2.2.1: decode the difference and
610
* Figure F.12: extend sign bit
614
int x = bits->getBitsNoFill(rv);
615
if ((x & (1 << (rv - 1))) == 0)
622
} // namespace RawSpeed