61 #include <boost/format.hpp> 63 #include <libopenraw/consts.h> 64 #include <libopenraw/debug.h> 66 #include "rawdata.hpp" 67 #include "exception.hpp" 68 #include "io/stream.hpp" 70 #include "ljpegdecompressor.hpp" 71 #include "ljpegdecompressor_priv.hpp" 75 using namespace Debug;
80 static void SkipVariable(IO::Stream *s);
81 static uint16_t Get2bytes (IO::Stream * s);
82 static int32_t NextMarker(IO::Stream * );
83 static void GetSoi(DecompressInfo *dcPtr);
84 static void GetApp0(IO::Stream *);
86 LJpegDecompressor::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),
98 LJpegDecompressor::~LJpegDecompressor()
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];
128 static 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};
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;
273 uint8_t inputBuffer[JPEG_BUF_SIZE];
276 int inputBufferOffset;
297 #define BITS_PER_LONG (8*sizeof(int32_t)) 298 #define MIN_GET_BITS (BITS_PER_LONG-7) 303 static 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 344 for (ci = 0; ci < dcPtr->numComponents; ci++) {
345 compPtr = &dcPtr->compInfo[ci];
346 if ((compPtr->hSampFactor != 1) || (compPtr->vSampFactor != 1)) {
354 if (dcPtr->compsInScan == 1) {
355 dcPtr->MCUmembership[0] = 0;
357 if (dcPtr->compsInScan > 4) {
361 for (ci = 0; ci < dcPtr->compsInScan; ci++) {
362 dcPtr->MCUmembership[ci] = ci;
371 if ((m_mcuROW1 = (MCU *)malloc(dcPtr->imageWidth*
sizeof(MCU)))==NULL) {
374 if ((m_mcuROW2 = (MCU *)malloc(dcPtr->imageWidth*
sizeof(MCU)))==NULL) {
378 mcuSize=dcPtr->compsInScan *
sizeof(ComponentType);
379 if ((m_buf1 = (
char *)malloc(dcPtr->imageWidth*mcuSize))==NULL) {
382 if ((m_buf2 = (
char *)malloc(dcPtr->imageWidth*mcuSize))==NULL) {
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);
410 LJpegDecompressor::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;
457 inline 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");
506 int32_t LJpegDecompressor::show_bits8(
IO::Stream * s)
508 if (m_bitsLeft < 8) {
511 return (m_getBuffer >> (m_bitsLeft-8)) & 0xff;
515 void LJpegDecompressor::flush_bits(uint16_t nbits)
517 m_bitsLeft -= (nbits);
521 int32_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];
529 int32_t LJpegDecompressor::get_bit()
532 fillBitBuffer(m_stream, 1);
533 return (m_getBuffer >> (--m_bitsLeft)) & 1;
538 int32_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];
564 LJpegDecompressor::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;
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]))];
653 static 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 660 static 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)
669 void HuffExtend(int32_t & x, int32_t s) noexcept
671 if ((x) < extendTest[s]) {
672 (x) += extendOffset[s];
704 for (ci = 0; ci < dcPtr->compsInScan; ci++) {
705 compptr = dcPtr->curCompInfo[ci];
709 if (dcPtr->dcHuffTblPtrs[compptr->dcTblNo] == NULL) {
718 FixHuffTbl (dcPtr->dcHuffTblPtrs[compptr->dcTblNo]);
724 dcPtr->restartInRows = (dcPtr->restartInterval)/(dcPtr->imageWidth);
725 dcPtr->restartRowsToGo = dcPtr->restartInRows;
726 dcPtr->nextRestartNum = 0;
753 nbytes = m_bitsLeft / 8;
762 c = m_stream->readByte();
768 c = m_stream->readByte();
772 if (c != (RST0 + dcPtr->nextRestartNum)) {
779 "Aborting decoding...\n");
785 dcPtr->restartRowsToGo = dcPtr->restartInRows;
786 dcPtr->nextRestartNum = (dcPtr->nextRestartNum + 1) & 7;
811 int32_t s,col,compsInScan,numCOL;
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)--;
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);
1016 static inline uint16_t
1022 return (a << 8) | s->readByte();
1041 static inline void SkipVariable(
IO::Stream * s)
1045 length = Get2bytes(s) - 2;
1047 s->
seek(length, SEEK_CUR);
1071 int32_t i, index, count;
1073 length = Get2bytes(m_stream) - 2;
1076 index = m_stream->readByte();
1078 if (index < 0 || index >= 4) {
1084 if (htblptr == NULL) {
1086 if (htblptr==NULL) {
1091 htblptr->bits[0] = 0;
1093 for (i = 1; i <= 16; i++) {
1094 htblptr->bits[i] = m_stream->readByte();
1095 count += htblptr->bits[i];
1102 for (i = 0; i < count; i++)
1103 htblptr->huffval[i] = m_stream->readByte();
1105 length -= 1 + 16 + count;
1129 if (Get2bytes(m_stream) != 4) {
1133 dcPtr->restartInterval = Get2bytes(m_stream);
1155 length = Get2bytes(s) - 2;
1156 s->
seek(length, SEEK_CUR);
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)) {
1203 if ((dcPtr->dataPrecision<MinPrecisionBits) ||
1204 (dcPtr->dataPrecision>MaxPrecisionBits)) {
1208 if (length != (dcPtr->numComponents * 3 + 8)) {
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();
1248 uint16_t n, ci, c, cc;
1251 length = Get2bytes (m_stream);
1256 n = m_stream->readByte();
1257 dcPtr->compsInScan = n;
1260 if (length != (n * 2 + 3) || n < 1 || n > 4) {
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) {
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;
1316 dcPtr->restartInterval = 0;
1346 }
while (c != 0xFF);
1353 }
while (c == 0xFF);
1375 LJpegDecompressor::JpegMarker
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);
1465 c = m_stream->readByte();
1466 c2 = m_stream->readByte();
1467 if ((c != 0xFF) || (c2 != M_SOI)) {
1469 "marker is %1% %2%\n")
1478 c = ProcessTables (dcPtr);
1488 LOGWARN(
"Unsupported SOF marker type 0x%x\n", c);
1516 c = ProcessTables (dcPtr);
1527 LOGWARN(
"Unexpected marker 0x%x\n", c);
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. I guess it failed.
virtual RawDataPtr decompress() override
virtual int seek(off_t offset, int whence)=0
void setSlices(const std::vector< uint16_t > &slices)
base virtual class for IO