diff options
Diffstat (limited to 'core/fxcodec/jbig2/JBig2_TrdProc.cpp')
-rw-r--r-- | core/fxcodec/jbig2/JBig2_TrdProc.cpp | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/core/fxcodec/jbig2/JBig2_TrdProc.cpp b/core/fxcodec/jbig2/JBig2_TrdProc.cpp new file mode 100644 index 0000000000..401249e3f2 --- /dev/null +++ b/core/fxcodec/jbig2/JBig2_TrdProc.cpp @@ -0,0 +1,407 @@ +// 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) { + int32_t STRIPT, FIRSTS; + FX_DWORD NINSTANCES; + int32_t DT, DFS, CURS; + int32_t SI, TI; + CJBig2_Image* IBI; + FX_DWORD WI, HI; + int32_t IDS; + FX_BOOL RI; + int32_t RDWI, RDHI, RDXI, RDYI; + CJBig2_Image* IBOI; + FX_DWORD WOI, HOI; + FX_BOOL bFirst; + FX_DWORD nTmp; + int32_t nVal, nBits; + std::unique_ptr<CJBig2_HuffmanDecoder> pHuffmanDecoder( + new CJBig2_HuffmanDecoder(pStream)); + std::unique_ptr<CJBig2_Image> SBREG(new CJBig2_Image(SBW, SBH)); + SBREG->fill(SBDEFPIXEL); + if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &STRIPT) != 0) + return nullptr; + + STRIPT *= SBSTRIPS; + STRIPT = -STRIPT; + FIRSTS = 0; + NINSTANCES = 0; + while (NINSTANCES < SBNUMINSTANCES) { + if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &DT) != 0) + return nullptr; + + DT *= SBSTRIPS; + STRIPT = STRIPT + DT; + bFirst = TRUE; + for (;;) { + if (bFirst) { + if (pHuffmanDecoder->decodeAValue(SBHUFFFS, &DFS) != 0) + return nullptr; + + FIRSTS = FIRSTS + DFS; + CURS = FIRSTS; + bFirst = FALSE; + } else { + 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) { + nTmp = 1; + while ((FX_DWORD)(1 << nTmp) < SBSTRIPS) { + nTmp++; + } + if (pStream->readNBits(nTmp, &nVal) != 0) + return nullptr; + + CURT = nVal; + } + TI = STRIPT + CURT; + nVal = 0; + nBits = 0; + FX_DWORD IDI; + for (;;) { + 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; + } + } + if (SBREFINE == 0) { + RI = 0; + } else { + if (pStream->read1Bit(&RI) != 0) { + return nullptr; + } + } + if (RI == 0) { + IBI = SBSYMS[IDI]; + } else { + 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(); + nTmp = pStream->getOffset(); + IBOI = SBSYMS[IDI]; + if (!IBOI) + return nullptr; + + WOI = IBOI->m_nWidth; + 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 ((FX_DWORD)nVal != (pStream->getOffset() - nTmp)) { + delete IBI; + return nullptr; + } + } + if (!IBI) { + continue; + } + WI = IBI->m_nWidth; + 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; + } + 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; + FX_DWORD NINSTANCES = 0; + while (NINSTANCES < SBNUMINSTANCES) { + int32_t CURS; + 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; + FX_DWORD 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]; + FX_DWORD WOI = IBOI->m_nWidth; + FX_DWORD 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; + + FX_DWORD WI = pIBI->m_nWidth; + FX_DWORD 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(); +} |