61#include <boost/format.hpp>
63#include <libopenraw/consts.h>
64#include <libopenraw/debug.h>
67#include "exception.hpp"
68#include "io/stream.hpp"
70#include "ljpegdecompressor.hpp"
71#include "ljpegdecompressor_priv.hpp"
80static void SkipVariable(IO::Stream *s);
81static uint16_t Get2bytes (IO::Stream * s);
82static int32_t NextMarker(IO::Stream * );
83static void GetSoi(DecompressInfo *dcPtr);
84static void GetApp0(IO::Stream *);
86LJpegDecompressor::LJpegDecompressor(IO::Stream *stream,
87 RawContainer *container)
88 : Decompressor(stream, container),
90 m_mcuROW1(NULL), m_mcuROW2(NULL),
91 m_buf1(NULL), m_buf2(NULL),
98LJpegDecompressor::~LJpegDecompressor()
115void LJpegDecompressor::setSlices(
const std::vector<uint16_t> & slices)
117 uint16_t n = slices[0];
118 m_slices.resize(n + 1);
119 for(uint16_t i = 0; i < n; i++) {
120 m_slices[i] = slices[1];
122 m_slices[n] = slices[2];
128static uint32_t bitMask[] = { 0xffffffff, 0x7fffffff,
129 0x3fffffff, 0x1fffffff,
130 0x0fffffff, 0x07ffffff,
131 0x03ffffff, 0x01ffffff,
132 0x00ffffff, 0x007fffff,
133 0x003fffff, 0x001fffff,
134 0x000fffff, 0x0007ffff,
135 0x0003ffff, 0x0001ffff,
136 0x0000ffff, 0x00007fff,
137 0x00003fff, 0x00001fff,
138 0x00000fff, 0x000007ff,
139 0x000003ff, 0x000001ff,
140 0x000000ff, 0x0000007f,
141 0x0000003f, 0x0000001f,
142 0x0000000f, 0x00000007,
143 0x00000003, 0x00000001};
145void FixHuffTbl (HuffmanTable *htbl);
166FixHuffTbl (HuffmanTable *htbl)
168 int32_t p, i, l, lastp, si;
170 uint16_t huffcode[257];
173 int32_t value, ll, ul;
180 for (l = 1; l <= 16; l++) {
181 for (i = 1; i <= (int)htbl->bits[l]; i++)
182 huffsize[p++] = (char)l;
195 while (huffsize[p]) {
196 while (((
int)huffsize[p]) == si) {
197 huffcode[p++] = code;
210 memset(htbl->ehufsi, 0,
sizeof(htbl->ehufsi));
212 for (p = 0; p < lastp; p++) {
213 htbl->ehufco[htbl->huffval[p]] = huffcode[p];
214 htbl->ehufsi[htbl->huffval[p]] = huffsize[p];
221 for (l = 1; l <= 16; l++) {
224 htbl->mincode[l] = huffcode[p];
226 htbl->maxcode[l] = huffcode[p - 1];
228 htbl->maxcode[l] = -1;
235 htbl->maxcode[17] = 0xFFFFFL;
244 bzero (htbl->numbits,
sizeof(htbl->numbits));
245 for (p=0; p<lastp; p++) {
248 value = htbl->huffval[p];
250 ll = code << (8-size);
252 ul = ll | bitMask[24+size];
256 for (i=ll; i<=ul; i++) {
257 htbl->numbits[i] = size;
258 htbl->value[i] = value;
273uint8_t inputBuffer[JPEG_BUF_SIZE];
276int inputBufferOffset;
297#define BITS_PER_LONG (8*sizeof(int32_t))
298#define MIN_GET_BITS (BITS_PER_LONG-7)
303static int32_t bmask[] = {0x0000,
304 0x0001, 0x0003, 0x0007, 0x000F,
305 0x001F, 0x003F, 0x007F, 0x00FF,
306 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
307 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
313#define MinPrecisionBits 2
314#define MaxPrecisionBits 16
334LJpegDecompressor::DecoderStructInit (DecompressInfo *dcPtr)
338 JpegComponentInfo *compPtr;
344 for (ci = 0; ci < dcPtr->numComponents; ci++) {
345 compPtr = &dcPtr->compInfo[ci];
346 if ((compPtr->hSampFactor != 1) || (compPtr->vSampFactor != 1)) {
347 throw DecodingException(
"Error: Downsampling is not supported.\n");
354 if (dcPtr->compsInScan == 1) {
355 dcPtr->MCUmembership[0] = 0;
357 if (dcPtr->compsInScan > 4) {
358 throw DecodingException(
"Too many components for interleaved scan");
361 for (ci = 0; ci < dcPtr->compsInScan; ci++) {
362 dcPtr->MCUmembership[ci] = ci;
371 if ((m_mcuROW1 = (MCU *)malloc(dcPtr->imageWidth*
sizeof(MCU)))==NULL) {
372 throw DecodingException(
"Not enough memory for mcuROW1\n");
374 if ((m_mcuROW2 = (MCU *)malloc(dcPtr->imageWidth*
sizeof(MCU)))==NULL) {
375 throw DecodingException(
"Not enough memory for mcuROW2\n");
378 mcuSize=dcPtr->compsInScan *
sizeof(ComponentType);
379 if ((m_buf1 = (
char *)malloc(dcPtr->imageWidth*mcuSize))==NULL) {
380 throw DecodingException(
"Not enough memory for buf1\n");
382 if ((m_buf2 = (
char *)malloc(dcPtr->imageWidth*mcuSize))==NULL) {
383 throw DecodingException(
"Not enough memory for buf2\n");
386 for (i=0;i<dcPtr->imageWidth;i++) {
387 m_mcuROW1[i]=(MCU)(m_buf1+i*mcuSize);
388 m_mcuROW2[i]=(MCU)(m_buf2+i*mcuSize);
410LJpegDecompressor::fillBitBuffer (IO::Stream * s,uint16_t nbits)
414 while (m_bitsLeft < MIN_GET_BITS) {
429 s->seek(-2, SEEK_CUR);
435 if (m_bitsLeft >= nbits)
450 m_getBuffer = (m_getBuffer << 8) | c;
457inline int32_t LJpegDecompressor::QuickPredict(int32_t col, int16_t curComp,
462 int32_t left,upper,diag,leftcol;
466 upper=prevRowBuf[col][curComp];
467 left=curRowBuf[leftcol][curComp];
468 diag=prevRowBuf[leftcol][curComp];
487 predictor = left+upper-diag;
490 predictor = left+((upper-diag)>>1);
493 predictor = upper+((left-diag)>>1);
496 predictor = (left+upper)>>1;
499 LOGWARN(
"Warning: Undefined PSV\n");
506int32_t LJpegDecompressor::show_bits8(IO::Stream * s)
508 if (m_bitsLeft < 8) {
511 return (m_getBuffer >> (m_bitsLeft-8)) & 0xff;
515void LJpegDecompressor::flush_bits(uint16_t nbits)
517 m_bitsLeft -= (nbits);
521int32_t LJpegDecompressor::get_bits(uint16_t nbits)
523 if (m_bitsLeft < nbits)
524 fillBitBuffer(m_stream, nbits);
525 return ((m_getBuffer >> (m_bitsLeft -= (nbits)))) & bmask[nbits];
529int32_t LJpegDecompressor::get_bit()
532 fillBitBuffer(m_stream, 1);
533 return (m_getBuffer >> (--m_bitsLeft)) & 1;
538int32_t LJpegDecompressor::readBits(IO::Stream * s, uint16_t nbits)
540 if (m_bitsLeft < nbits) {
541 fillBitBuffer(s, nbits);
543 return ((m_getBuffer >> (m_bitsLeft -= (nbits)))) & bmask[nbits];
564LJpegDecompressor::PmPutRow(MCU* RowBuf, int32_t numComp, int32_t numCol, int32_t Pt)
573 for (col = 0; col < numCol; col++) {
574 for (comp = 0; comp < numComp; comp++) {
575 v = RowBuf[col][comp]<<Pt;
599LJpegDecompressor::HuffDecode(HuffmanTable *htbl)
610 code = show_bits8(m_stream);
611 if (htbl->numbits[code]) {
612 flush_bits(htbl->numbits[code]);
613 rv=htbl->value[code];
617 while (code > htbl->maxcode[l]) {
619 code = (code << 1) | temp;
631 rv = htbl->huffval[htbl->valptr[l] +
632 ((int)(code - htbl->mincode[l]))];
653static const int32_t extendTest[16] =
654{0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
655 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000};
659#define EXTEND(n) (int32_t)(0xffffffff << n) + 1
660static const int32_t extendOffset[16] =
662 0, EXTEND(1), EXTEND(2), EXTEND(3),
663 EXTEND(4), EXTEND(5), EXTEND(6), EXTEND(7),
664 EXTEND(8), EXTEND(9), EXTEND(10), EXTEND(11),
665 EXTEND(12), EXTEND(13), EXTEND(14), EXTEND(15)
669void HuffExtend(int32_t & x, int32_t s)
noexcept
671 if ((x) < extendTest[s]) {
672 (x) += extendOffset[s];
693LJpegDecompressor::HuffDecoderInit (DecompressInfo *dcPtr)
697 JpegComponentInfo *compptr;
704 for (ci = 0; ci < dcPtr->compsInScan; ci++) {
705 compptr = dcPtr->curCompInfo[ci];
709 if (dcPtr->dcHuffTblPtrs[compptr->dcTblNo] == NULL) {
710 throw DecodingException(
"Error: Use of undefined Huffman table\n");
718 FixHuffTbl (dcPtr->dcHuffTblPtrs[compptr->dcTblNo]);
724 dcPtr->restartInRows = (dcPtr->restartInterval)/(dcPtr->imageWidth);
725 dcPtr->restartRowsToGo = dcPtr->restartInRows;
726 dcPtr->nextRestartNum = 0;
745LJpegDecompressor::ProcessRestart (DecompressInfo *dcPtr)
753 nbytes = m_bitsLeft / 8;
762 c = m_stream->readByte();
768 c = m_stream->readByte();
772 if (c != (RST0 + dcPtr->nextRestartNum)) {
778 throw DecodingException(
"Error: Corrupt JPEG data. "
779 "Aborting decoding...\n");
785 dcPtr->restartRowsToGo = dcPtr->restartInRows;
786 dcPtr->nextRestartNum = (dcPtr->nextRestartNum + 1) & 7;
807void LJpegDecompressor::DecodeFirstRow(DecompressInfo *dcPtr,
811 int32_t s,col,compsInScan,numCOL;
812 JpegComponentInfo *compptr;
816 Pr=dcPtr->dataPrecision;
818 compsInScan=dcPtr->compsInScan;
819 numCOL=dcPtr->imageWidth;
824 for (curComp = 0; curComp < compsInScan; curComp++) {
825 ci = dcPtr->MCUmembership[curComp];
826 compptr = dcPtr->curCompInfo[ci];
827 dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo];
832 s = HuffDecode (dctbl);
843 curRowBuf[0][curComp]=d+(1<<(Pr-Pt-1));
849 for (col=1; col<numCOL; col++) {
850 for (curComp = 0; curComp < compsInScan; curComp++) {
851 ci = dcPtr->MCUmembership[curComp];
852 compptr = dcPtr->curCompInfo[ci];
853 dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo];
858 s = HuffDecode (dctbl);
869 curRowBuf[col][curComp]=d+curRowBuf[col-1][curComp];
873 if (dcPtr->restartInRows) {
874 (dcPtr->restartRowsToGo)--;
896LJpegDecompressor::DecodeImage(DecompressInfo *dcPtr)
901 JpegComponentInfo *compptr;
903 int32_t numCOL,numROW,compsInScan;
904 MCU *prevRowBuf,*curRowBuf;
905 int32_t imagewidth,Pt,psv;
907 numCOL=imagewidth=dcPtr->imageWidth;
908 numROW=dcPtr->imageHeight;
909 compsInScan=dcPtr->compsInScan;
912 prevRowBuf=m_mcuROW2;
920 DecodeFirstRow(dcPtr,curRowBuf);
921 PmPutRow(curRowBuf,compsInScan,numCOL,Pt);
922 std::swap(prevRowBuf,curRowBuf);
924 for (row=1; row<numROW; row++) {
929 if (dcPtr->restartInRows) {
930 if (dcPtr->restartRowsToGo == 0) {
931 ProcessRestart (dcPtr);
936 DecodeFirstRow(dcPtr,curRowBuf);
937 PmPutRow(curRowBuf,compsInScan,numCOL,Pt);
938 std::swap(prevRowBuf,curRowBuf);
941 dcPtr->restartRowsToGo--;
947 for (curComp = 0; curComp < compsInScan; curComp++) {
948 ci = dcPtr->MCUmembership[curComp];
949 compptr = dcPtr->curCompInfo[ci];
950 dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo];
955 s = HuffDecode (dctbl);
963 curRowBuf[0][curComp]=d+prevRowBuf[0][curComp];
970 for (col=1; col<numCOL; col++) {
971 for (curComp = 0; curComp < compsInScan; curComp++) {
972 ci = dcPtr->MCUmembership[curComp];
973 compptr = dcPtr->curCompInfo[ci];
974 dctbl = dcPtr->dcHuffTblPtrs[compptr->dcTblNo];
979 s = HuffDecode (dctbl);
986 predictor = QuickPredict(col,curComp,curRowBuf,prevRowBuf,
989 curRowBuf[col][curComp]=d+predictor;
992 PmPutRow(curRowBuf,compsInScan,numCOL,Pt);
993 std::swap(prevRowBuf,curRowBuf);
1016static inline uint16_t
1017Get2bytes (IO::Stream * s)
1022 return (a << 8) | s->readByte();
1041static inline void SkipVariable(IO::Stream * s)
1045 length = Get2bytes(s) - 2;
1047 s->seek(length, SEEK_CUR);
1067LJpegDecompressor::GetDht (DecompressInfo *dcPtr)
1071 int32_t i, index, count;
1073 length = Get2bytes(m_stream) - 2;
1076 index = m_stream->readByte();
1078 if (index < 0 || index >= 4) {
1079 throw DecodingException(str(boost::format(
"Bogus DHT index %1%")
1083 HuffmanTable *& htblptr = dcPtr->dcHuffTblPtrs[index];
1084 if (htblptr == NULL) {
1085 htblptr = (HuffmanTable *) malloc(
sizeof (HuffmanTable));
1086 if (htblptr==NULL) {
1087 throw DecodingException(
"Can't malloc HuffmanTable");
1091 htblptr->bits[0] = 0;
1093 for (i = 1; i <= 16; i++) {
1094 htblptr->bits[i] = m_stream->readByte();
1095 count += htblptr->bits[i];
1099 throw DecodingException(
"Bogus DHT counts");
1102 for (i = 0; i < count; i++)
1103 htblptr->huffval[i] = m_stream->readByte();
1105 length -= 1 + 16 + count;
1126LJpegDecompressor::GetDri(DecompressInfo *dcPtr)
1129 if (Get2bytes(m_stream) != 4) {
1130 throw DecodingException(
"Bogus length in DRI");
1133 dcPtr->restartInterval = Get2bytes(m_stream);
1151static void GetApp0(IO::Stream *s)
1155 length = Get2bytes(s) - 2;
1156 s->seek(length, SEEK_CUR);
1177LJpegDecompressor::GetSof(DecompressInfo *dcPtr)
1183 JpegComponentInfo *compptr;
1185 length = Get2bytes(m_stream);
1187 dcPtr->dataPrecision = m_stream->readByte();
1188 dcPtr->imageHeight = Get2bytes(m_stream);
1189 dcPtr->imageWidth = Get2bytes(m_stream);
1190 dcPtr->numComponents = m_stream->readByte();
1197 if ((dcPtr->imageHeight <= 0 ) ||
1198 (dcPtr->imageWidth <= 0) ||
1199 (dcPtr->numComponents <= 0)) {
1200 throw DecodingException(
"Empty JPEG image (DNL not supported)");
1203 if ((dcPtr->dataPrecision<MinPrecisionBits) ||
1204 (dcPtr->dataPrecision>MaxPrecisionBits)) {
1205 throw DecodingException(
"Unsupported JPEG data precision");
1208 if (length != (dcPtr->numComponents * 3 + 8)) {
1209 throw DecodingException(
"Bogus SOF length");
1212 dcPtr->compInfo = (JpegComponentInfo *) malloc
1213 (dcPtr->numComponents * sizeof (JpegComponentInfo));
1215 for (ci = 0; ci < dcPtr->numComponents; ci++) {
1216 compptr = &dcPtr->compInfo[ci];
1217 compptr->componentIndex = ci;
1218 compptr->componentId = m_stream->readByte();
1219 c = m_stream->readByte();
1220 compptr->hSampFactor = (int16_t)((c >> 4) & 15);
1221 compptr->vSampFactor = (int16_t)((c) & 15);
1222 (void) m_stream->readByte();
1243LJpegDecompressor::GetSos (DecompressInfo *dcPtr)
1248 uint16_t n, ci, c, cc;
1249 JpegComponentInfo *compptr;
1251 length = Get2bytes (m_stream);
1256 n = m_stream->readByte();
1257 dcPtr->compsInScan = n;
1260 if (length != (n * 2 + 3) || n < 1 || n > 4) {
1261 throw DecodingException(
"Bogus SOS length");
1265 for (i = 0; i < n; i++) {
1266 cc = m_stream->readByte();
1267 c = m_stream->readByte();
1270 for (ci = 0; ci < dcPtr->numComponents; ci++)
1271 if (cc == dcPtr->compInfo[ci].componentId) {
1275 if (ci >= dcPtr->numComponents) {
1276 throw DecodingException(
"Invalid component number in SOS");
1279 compptr = &dcPtr->compInfo[ci];
1280 dcPtr->curCompInfo[i] = compptr;
1281 compptr->dcTblNo = (c >> 4) & 15;
1287 dcPtr->Ss = m_stream->readByte();
1288 (void)m_stream->readByte();
1289 c = m_stream->readByte();
1290 dcPtr->Pt = c & 0x0F;
1310GetSoi (DecompressInfo *dcPtr)
1316 dcPtr->restartInterval = 0;
1336NextMarker(IO::Stream *s)
1346 }
while (c != 0xFF);
1353 }
while (c == 0xFF);
1375LJpegDecompressor::JpegMarker
1376LJpegDecompressor::ProcessTables (DecompressInfo *dcPtr)
1381 c = NextMarker (m_stream);
1401 return ((JpegMarker)c);
1408 LOGWARN(
"Not a lossless JPEG file.\n");
1428 LOGWARN(
"Warning: unexpected marker 0x%x", c);
1433 SkipVariable (m_stream);
1456LJpegDecompressor::ReadFileHeader (DecompressInfo *dcPtr)
1465 c = m_stream->readByte();
1466 c2 = m_stream->readByte();
1467 if ((c != 0xFF) || (c2 != M_SOI)) {
1468 throw DecodingException(str(boost::format(
"Not a JPEG file. "
1469 "marker is %1% %2%\n")
1478 c = ProcessTables (dcPtr);
1488 LOGWARN(
"Unsupported SOF marker type 0x%x\n", c);
1509LJpegDecompressor::ReadScanHeader (DecompressInfo *dcPtr)
1516 c = ProcessTables (dcPtr);
1527 LOGWARN(
"Unexpected marker 0x%x\n", c);
1534RawDataPtr LJpegDecompressor::decompress()
1538 ReadFileHeader(&dcInfo);
1539 ReadScanHeader (&dcInfo);
1541 m_output = RawDataPtr(
new RawData);
1542 m_output->setDataType(OR_DATA_TYPE_RAW);
1543 uint32_t bpc = dcInfo.dataPrecision;
1545 m_output->setBpc(bpc);
1546 m_output->setWhiteLevel((1 << bpc) - 1);
1548 m_output->allocData(dcInfo.imageWidth
1550 * dcInfo.imageHeight
1551 * dcInfo.numComponents);
1553 LOGDBG1(
"dc width = %d dc height = %d\n", dcInfo.imageWidth,
1554 dcInfo.imageHeight);
1559 uint32_t width = dcInfo.imageWidth * dcInfo.numComponents;
1560 m_output->setDimensions(width, dcInfo.imageHeight);
1561 m_output->setSlices(m_slices);
1562 DecoderStructInit(&dcInfo);
1563 HuffDecoderInit(&dcInfo);
1564 DecodeImage(&dcInfo);
1569 LOGERR(
"Decompression error\n");
1571 return std::move(m_output);
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard....