// 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; } } 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->width(); uint32_t HOI = IBOI->height(); 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->width(); uint32_t HI = IBI->height(); 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; if (!pIADT->decode(pArithDecoder, &STRIPT)) return nullptr; STRIPT *= SBSTRIPS; STRIPT = -STRIPT; int32_t FIRSTS = 0; uint32_t NINSTANCES = 0; while (NINSTANCES < SBNUMINSTANCES) { int32_t CURS = 0; int32_t DT; if (!pIADT->decode(pArithDecoder, &DT)) return nullptr; 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->width(); uint32_t HOI = IBOI->height(); 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->width(); uint32_t HI = pIBI->height(); 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(); }