// Copyright 2015 PDFium Authors. All rights reserved.
|
// Use of this source code is governed by a BSD-style license that can be
|
// found in the LICENSE file.
|
|
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
|
|
#include "core/fxcodec/jbig2/JBig2_TrdProc.h"
|
|
#include <memory>
|
|
#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
|
#include "core/fxcodec/jbig2/JBig2_ArithIntDecoder.h"
|
#include "core/fxcodec/jbig2/JBig2_GrrdProc.h"
|
#include "core/fxcodec/jbig2/JBig2_HuffmanDecoder.h"
|
|
CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream,
|
JBig2ArithCtx* grContext) {
|
std::unique_ptr<CJBig2_HuffmanDecoder> pHuffmanDecoder(
|
new CJBig2_HuffmanDecoder(pStream));
|
std::unique_ptr<CJBig2_Image> SBREG(new CJBig2_Image(SBW, SBH));
|
SBREG->fill(SBDEFPIXEL);
|
int32_t STRIPT;
|
if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &STRIPT) != 0)
|
return nullptr;
|
|
STRIPT *= SBSTRIPS;
|
STRIPT = -STRIPT;
|
uint32_t NINSTANCES = 0;
|
while (NINSTANCES < SBNUMINSTANCES) {
|
int32_t DT;
|
if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &DT) != 0)
|
return nullptr;
|
|
DT *= SBSTRIPS;
|
STRIPT = STRIPT + DT;
|
bool bFirst = true;
|
int32_t FIRSTS = 0;
|
int32_t CURS = 0;
|
for (;;) {
|
if (bFirst) {
|
int32_t DFS;
|
if (pHuffmanDecoder->decodeAValue(SBHUFFFS, &DFS) != 0)
|
return nullptr;
|
|
FIRSTS = FIRSTS + DFS;
|
CURS = FIRSTS;
|
bFirst = false;
|
} else {
|
int32_t IDS;
|
int32_t nVal = pHuffmanDecoder->decodeAValue(SBHUFFDS, &IDS);
|
if (nVal == JBIG2_OOB) {
|
break;
|
} else if (nVal != 0) {
|
return nullptr;
|
} else {
|
CURS = CURS + IDS + SBDSOFFSET;
|
}
|
}
|
uint8_t CURT = 0;
|
if (SBSTRIPS != 1) {
|
uint32_t nTmp = 1;
|
while ((uint32_t)(1 << nTmp) < SBSTRIPS) {
|
nTmp++;
|
}
|
int32_t nVal;
|
if (pStream->readNBits(nTmp, &nVal) != 0)
|
return nullptr;
|
|
CURT = nVal;
|
}
|
int32_t TI = STRIPT + CURT;
|
int32_t nVal = 0;
|
int32_t nBits = 0;
|
uint32_t IDI;
|
for (;;) {
|
uint32_t nTmp;
|
if (pStream->read1Bit(&nTmp) != 0)
|
return nullptr;
|
|
nVal = (nVal << 1) | nTmp;
|
nBits++;
|
for (IDI = 0; IDI < SBNUMSYMS; IDI++) {
|
if ((nBits == SBSYMCODES[IDI].codelen) &&
|
(nVal == SBSYMCODES[IDI].code)) {
|
break;
|
}
|
}
|
if (IDI < SBNUMSYMS) {
|
break;
|
}
|
}
|
FX_BOOL RI = 0;
|
if (SBREFINE != 0 && pStream->read1Bit(&RI) != 0) {
|
return nullptr;
|
}
|
CJBig2_Image* IBI = nullptr;
|
if (RI == 0) {
|
IBI = SBSYMS[IDI];
|
} else {
|
int32_t RDWI;
|
int32_t RDHI;
|
int32_t RDXI;
|
int32_t RDYI;
|
if ((pHuffmanDecoder->decodeAValue(SBHUFFRDW, &RDWI) != 0) ||
|
(pHuffmanDecoder->decodeAValue(SBHUFFRDH, &RDHI) != 0) ||
|
(pHuffmanDecoder->decodeAValue(SBHUFFRDX, &RDXI) != 0) ||
|
(pHuffmanDecoder->decodeAValue(SBHUFFRDY, &RDYI) != 0) ||
|
(pHuffmanDecoder->decodeAValue(SBHUFFRSIZE, &nVal) != 0)) {
|
return nullptr;
|
}
|
pStream->alignByte();
|
uint32_t nTmp = pStream->getOffset();
|
CJBig2_Image* IBOI = SBSYMS[IDI];
|
if (!IBOI)
|
return nullptr;
|
|
uint32_t WOI = IBOI->m_nWidth;
|
uint32_t HOI = IBOI->m_nHeight;
|
if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0)
|
return nullptr;
|
|
std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
|
pGRRD->GRW = WOI + RDWI;
|
pGRRD->GRH = HOI + RDHI;
|
pGRRD->GRTEMPLATE = SBRTEMPLATE;
|
pGRRD->GRREFERENCE = IBOI;
|
pGRRD->GRREFERENCEDX = (RDWI >> 2) + RDXI;
|
pGRRD->GRREFERENCEDY = (RDHI >> 2) + RDYI;
|
pGRRD->TPGRON = 0;
|
pGRRD->GRAT[0] = SBRAT[0];
|
pGRRD->GRAT[1] = SBRAT[1];
|
pGRRD->GRAT[2] = SBRAT[2];
|
pGRRD->GRAT[3] = SBRAT[3];
|
|
{
|
std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
|
new CJBig2_ArithDecoder(pStream));
|
IBI = pGRRD->decode(pArithDecoder.get(), grContext);
|
if (!IBI)
|
return nullptr;
|
}
|
|
pStream->alignByte();
|
pStream->offset(2);
|
if ((uint32_t)nVal != (pStream->getOffset() - nTmp)) {
|
delete IBI;
|
return nullptr;
|
}
|
}
|
if (!IBI) {
|
continue;
|
}
|
uint32_t WI = IBI->m_nWidth;
|
uint32_t HI = IBI->m_nHeight;
|
if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
|
(REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
|
CURS = CURS + WI - 1;
|
} else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
|
(REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
|
CURS = CURS + HI - 1;
|
}
|
int32_t SI = CURS;
|
if (TRANSPOSED == 0) {
|
switch (REFCORNER) {
|
case JBIG2_CORNER_TOPLEFT:
|
SBREG->composeFrom(SI, TI, IBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_TOPRIGHT:
|
SBREG->composeFrom(SI - WI + 1, TI, IBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_BOTTOMLEFT:
|
SBREG->composeFrom(SI, TI - HI + 1, IBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_BOTTOMRIGHT:
|
SBREG->composeFrom(SI - WI + 1, TI - HI + 1, IBI, SBCOMBOP);
|
break;
|
}
|
} else {
|
switch (REFCORNER) {
|
case JBIG2_CORNER_TOPLEFT:
|
SBREG->composeFrom(TI, SI, IBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_TOPRIGHT:
|
SBREG->composeFrom(TI - WI + 1, SI, IBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_BOTTOMLEFT:
|
SBREG->composeFrom(TI, SI - HI + 1, IBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_BOTTOMRIGHT:
|
SBREG->composeFrom(TI - WI + 1, SI - HI + 1, IBI, SBCOMBOP);
|
break;
|
}
|
}
|
if (RI != 0) {
|
delete IBI;
|
}
|
if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
|
(REFCORNER == JBIG2_CORNER_BOTTOMLEFT))) {
|
CURS = CURS + WI - 1;
|
} else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
|
(REFCORNER == JBIG2_CORNER_TOPRIGHT))) {
|
CURS = CURS + HI - 1;
|
}
|
NINSTANCES = NINSTANCES + 1;
|
}
|
}
|
return SBREG.release();
|
}
|
|
CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
|
JBig2ArithCtx* grContext,
|
JBig2IntDecoderState* pIDS) {
|
std::unique_ptr<CJBig2_ArithIntDecoder> IADT;
|
std::unique_ptr<CJBig2_ArithIntDecoder> IAFS;
|
std::unique_ptr<CJBig2_ArithIntDecoder> IADS;
|
std::unique_ptr<CJBig2_ArithIntDecoder> IAIT;
|
std::unique_ptr<CJBig2_ArithIntDecoder> IARI;
|
std::unique_ptr<CJBig2_ArithIntDecoder> IARDW;
|
std::unique_ptr<CJBig2_ArithIntDecoder> IARDH;
|
std::unique_ptr<CJBig2_ArithIntDecoder> IARDX;
|
std::unique_ptr<CJBig2_ArithIntDecoder> IARDY;
|
std::unique_ptr<CJBig2_ArithIaidDecoder> IAID;
|
CJBig2_ArithIntDecoder* pIADT;
|
CJBig2_ArithIntDecoder* pIAFS;
|
CJBig2_ArithIntDecoder* pIADS;
|
CJBig2_ArithIntDecoder* pIAIT;
|
CJBig2_ArithIntDecoder* pIARI;
|
CJBig2_ArithIntDecoder* pIARDW;
|
CJBig2_ArithIntDecoder* pIARDH;
|
CJBig2_ArithIntDecoder* pIARDX;
|
CJBig2_ArithIntDecoder* pIARDY;
|
CJBig2_ArithIaidDecoder* pIAID;
|
if (pIDS) {
|
pIADT = pIDS->IADT;
|
pIAFS = pIDS->IAFS;
|
pIADS = pIDS->IADS;
|
pIAIT = pIDS->IAIT;
|
pIARI = pIDS->IARI;
|
pIARDW = pIDS->IARDW;
|
pIARDH = pIDS->IARDH;
|
pIARDX = pIDS->IARDX;
|
pIARDY = pIDS->IARDY;
|
pIAID = pIDS->IAID;
|
} else {
|
IADT.reset(new CJBig2_ArithIntDecoder());
|
IAFS.reset(new CJBig2_ArithIntDecoder());
|
IADS.reset(new CJBig2_ArithIntDecoder());
|
IAIT.reset(new CJBig2_ArithIntDecoder());
|
IARI.reset(new CJBig2_ArithIntDecoder());
|
IARDW.reset(new CJBig2_ArithIntDecoder());
|
IARDH.reset(new CJBig2_ArithIntDecoder());
|
IARDX.reset(new CJBig2_ArithIntDecoder());
|
IARDY.reset(new CJBig2_ArithIntDecoder());
|
IAID.reset(new CJBig2_ArithIaidDecoder(SBSYMCODELEN));
|
pIADT = IADT.get();
|
pIAFS = IAFS.get();
|
pIADS = IADS.get();
|
pIAIT = IAIT.get();
|
pIARI = IARI.get();
|
pIARDW = IARDW.get();
|
pIARDH = IARDH.get();
|
pIARDX = IARDX.get();
|
pIARDY = IARDY.get();
|
pIAID = IAID.get();
|
}
|
std::unique_ptr<CJBig2_Image> SBREG(new CJBig2_Image(SBW, SBH));
|
SBREG->fill(SBDEFPIXEL);
|
int32_t STRIPT;
|
pIADT->decode(pArithDecoder, &STRIPT);
|
STRIPT *= SBSTRIPS;
|
STRIPT = -STRIPT;
|
int32_t FIRSTS = 0;
|
uint32_t NINSTANCES = 0;
|
while (NINSTANCES < SBNUMINSTANCES) {
|
int32_t CURS = 0;
|
int32_t DT;
|
pIADT->decode(pArithDecoder, &DT);
|
DT *= SBSTRIPS;
|
STRIPT += DT;
|
bool bFirst = true;
|
for (;;) {
|
if (bFirst) {
|
int32_t DFS;
|
pIAFS->decode(pArithDecoder, &DFS);
|
FIRSTS += DFS;
|
CURS = FIRSTS;
|
bFirst = false;
|
} else {
|
int32_t IDS;
|
if (!pIADS->decode(pArithDecoder, &IDS))
|
break;
|
CURS += IDS + SBDSOFFSET;
|
}
|
if (NINSTANCES >= SBNUMINSTANCES) {
|
break;
|
}
|
int CURT = 0;
|
if (SBSTRIPS != 1)
|
pIAIT->decode(pArithDecoder, &CURT);
|
|
int32_t TI = STRIPT + CURT;
|
uint32_t IDI;
|
pIAID->decode(pArithDecoder, &IDI);
|
if (IDI >= SBNUMSYMS)
|
return nullptr;
|
|
int RI;
|
if (SBREFINE == 0)
|
RI = 0;
|
else
|
pIARI->decode(pArithDecoder, &RI);
|
|
std::unique_ptr<CJBig2_Image> IBI;
|
CJBig2_Image* pIBI;
|
if (RI == 0) {
|
pIBI = SBSYMS[IDI];
|
} else {
|
int32_t RDWI;
|
int32_t RDHI;
|
int32_t RDXI;
|
int32_t RDYI;
|
pIARDW->decode(pArithDecoder, &RDWI);
|
pIARDH->decode(pArithDecoder, &RDHI);
|
pIARDX->decode(pArithDecoder, &RDXI);
|
pIARDY->decode(pArithDecoder, &RDYI);
|
CJBig2_Image* IBOI = SBSYMS[IDI];
|
if (!IBOI)
|
return nullptr;
|
|
uint32_t WOI = IBOI->m_nWidth;
|
uint32_t HOI = IBOI->m_nHeight;
|
if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0)
|
return nullptr;
|
|
std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
|
pGRRD->GRW = WOI + RDWI;
|
pGRRD->GRH = HOI + RDHI;
|
pGRRD->GRTEMPLATE = SBRTEMPLATE;
|
pGRRD->GRREFERENCE = IBOI;
|
pGRRD->GRREFERENCEDX = (RDWI >> 1) + RDXI;
|
pGRRD->GRREFERENCEDY = (RDHI >> 1) + RDYI;
|
pGRRD->TPGRON = 0;
|
pGRRD->GRAT[0] = SBRAT[0];
|
pGRRD->GRAT[1] = SBRAT[1];
|
pGRRD->GRAT[2] = SBRAT[2];
|
pGRRD->GRAT[3] = SBRAT[3];
|
IBI.reset(pGRRD->decode(pArithDecoder, grContext));
|
pIBI = IBI.get();
|
}
|
if (!pIBI)
|
return nullptr;
|
|
uint32_t WI = pIBI->m_nWidth;
|
uint32_t HI = pIBI->m_nHeight;
|
if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
|
(REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
|
CURS += WI - 1;
|
} else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
|
(REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
|
CURS += HI - 1;
|
}
|
int32_t SI = CURS;
|
if (TRANSPOSED == 0) {
|
switch (REFCORNER) {
|
case JBIG2_CORNER_TOPLEFT:
|
SBREG->composeFrom(SI, TI, pIBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_TOPRIGHT:
|
SBREG->composeFrom(SI - WI + 1, TI, pIBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_BOTTOMLEFT:
|
SBREG->composeFrom(SI, TI - HI + 1, pIBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_BOTTOMRIGHT:
|
SBREG->composeFrom(SI - WI + 1, TI - HI + 1, pIBI, SBCOMBOP);
|
break;
|
}
|
} else {
|
switch (REFCORNER) {
|
case JBIG2_CORNER_TOPLEFT:
|
SBREG->composeFrom(TI, SI, pIBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_TOPRIGHT:
|
SBREG->composeFrom(TI - WI + 1, SI, pIBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_BOTTOMLEFT:
|
SBREG->composeFrom(TI, SI - HI + 1, pIBI, SBCOMBOP);
|
break;
|
case JBIG2_CORNER_BOTTOMRIGHT:
|
SBREG->composeFrom(TI - WI + 1, SI - HI + 1, pIBI, SBCOMBOP);
|
break;
|
}
|
}
|
if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
|
(REFCORNER == JBIG2_CORNER_BOTTOMLEFT))) {
|
CURS += WI - 1;
|
} else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
|
(REFCORNER == JBIG2_CORNER_TOPRIGHT))) {
|
CURS += HI - 1;
|
}
|
++NINSTANCES;
|
}
|
}
|
return SBREG.release();
|
}
|