| // 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_HtrdProc.h" | |
| #include <algorithm> | |
| #include <utility> | |
| #include "core/fxcodec/jbig2/JBig2_BitStream.h" | |
| #include "core/fxcodec/jbig2/JBig2_GrdProc.h" | |
| #include "core/fxcodec/jbig2/JBig2_Image.h" | |
| std::unique_ptr<CJBig2_Image> CJBig2_HTRDProc::DecodeArith( | |
| CJBig2_ArithDecoder* pArithDecoder, | |
| JBig2ArithCtx* gbContext, | |
| PauseIndicatorIface* pPause) { | |
| std::unique_ptr<CJBig2_Image> HSKIP; | |
| if (HENABLESKIP == 1) { | |
| HSKIP = std::make_unique<CJBig2_Image>(HGW, HGH); | |
| for (uint32_t mg = 0; mg < HGH; ++mg) { | |
| for (uint32_t ng = 0; ng < HGW; ++ng) { | |
| int32_t x = (HGX + mg * HRY + ng * HRX) >> 8; | |
| int32_t y = (HGY + mg * HRX - ng * HRY) >> 8; | |
| if ((x + HPW <= 0) | (x >= static_cast<int32_t>(HBW)) | (y + HPH <= 0) | | |
| (y >= static_cast<int32_t>(HPH))) { | |
| HSKIP->SetPixel(ng, mg, 1); | |
| } else { | |
| HSKIP->SetPixel(ng, mg, 0); | |
| } | |
| } | |
| } | |
| } | |
| uint32_t HBPP = 1; | |
| while (static_cast<uint32_t>(1 << HBPP) < HNUMPATS) | |
| ++HBPP; | |
| CJBig2_GRDProc GRD; | |
| GRD.MMR = HMMR; | |
| GRD.GBW = HGW; | |
| GRD.GBH = HGH; | |
| GRD.GBTEMPLATE = HTEMPLATE; | |
| GRD.TPGDON = false; | |
| GRD.USESKIP = HENABLESKIP; | |
| GRD.SKIP = HSKIP.get(); | |
| if (HTEMPLATE <= 1) | |
| GRD.GBAT[0] = 3; | |
| else | |
| GRD.GBAT[0] = 2; | |
| GRD.GBAT[1] = -1; | |
| if (GRD.GBTEMPLATE == 0) { | |
| GRD.GBAT[2] = -3; | |
| GRD.GBAT[3] = -1; | |
| GRD.GBAT[4] = 2; | |
| GRD.GBAT[5] = -2; | |
| GRD.GBAT[6] = -2; | |
| GRD.GBAT[7] = -2; | |
| } | |
| uint8_t GSBPP = static_cast<uint8_t>(HBPP); | |
| std::vector<std::unique_ptr<CJBig2_Image>> GSPLANES(GSBPP); | |
| for (int32_t i = GSBPP - 1; i >= 0; --i) { | |
| std::unique_ptr<CJBig2_Image> pImage; | |
| CJBig2_GRDProc::ProgressiveArithDecodeState state; | |
| state.pImage = &pImage; | |
| state.pArithDecoder = pArithDecoder; | |
| state.gbContext = gbContext; | |
| state.pPause = nullptr; | |
| FXCODEC_STATUS status = GRD.StartDecodeArith(&state); | |
| state.pPause = pPause; | |
| while (status == FXCODEC_STATUS::kDecodeToBeContinued) | |
| status = GRD.ContinueDecode(&state); | |
| if (!pImage) | |
| return nullptr; | |
| GSPLANES[i] = std::move(pImage); | |
| if (i < GSBPP - 1) | |
| GSPLANES[i]->ComposeFrom(0, 0, GSPLANES[i + 1].get(), JBIG2_COMPOSE_XOR); | |
| } | |
| return DecodeImage(GSPLANES); | |
| } | |
| std::unique_ptr<CJBig2_Image> CJBig2_HTRDProc::DecodeMMR( | |
| CJBig2_BitStream* pStream) { | |
| uint32_t HBPP = 1; | |
| while (static_cast<uint32_t>(1 << HBPP) < HNUMPATS) | |
| ++HBPP; | |
| CJBig2_GRDProc GRD; | |
| GRD.MMR = HMMR; | |
| GRD.GBW = HGW; | |
| GRD.GBH = HGH; | |
| uint8_t GSBPP = static_cast<uint8_t>(HBPP); | |
| std::vector<std::unique_ptr<CJBig2_Image>> GSPLANES(GSBPP); | |
| GRD.StartDecodeMMR(&GSPLANES[GSBPP - 1], pStream); | |
| if (!GSPLANES[GSBPP - 1]) | |
| return nullptr; | |
| pStream->alignByte(); | |
| pStream->offset(3); | |
| for (int32_t J = GSBPP - 2; J >= 0; --J) { | |
| GRD.StartDecodeMMR(&GSPLANES[J], pStream); | |
| if (!GSPLANES[J]) | |
| return nullptr; | |
| pStream->alignByte(); | |
| pStream->offset(3); | |
| GSPLANES[J]->ComposeFrom(0, 0, GSPLANES[J + 1].get(), JBIG2_COMPOSE_XOR); | |
| } | |
| return DecodeImage(GSPLANES); | |
| } | |
| std::unique_ptr<CJBig2_Image> CJBig2_HTRDProc::DecodeImage( | |
| const std::vector<std::unique_ptr<CJBig2_Image>>& GSPLANES) { | |
| auto HTREG = std::make_unique<CJBig2_Image>(HBW, HBH); | |
| if (!HTREG->data()) | |
| return nullptr; | |
| HTREG->Fill(HDEFPIXEL); | |
| for (uint32_t y = 0; y < HGH; ++y) { | |
| for (uint32_t x = 0; x < HGW; ++x) { | |
| uint32_t gsval = 0; | |
| for (uint8_t i = 0; i < GSPLANES.size(); ++i) | |
| gsval |= GSPLANES[i]->GetPixel(x, y) << i; | |
| uint32_t pat_index = std::min(gsval, HNUMPATS - 1); | |
| int32_t out_x = (HGX + y * HRY + x * HRX) >> 8; | |
| int32_t out_y = (HGY + y * HRX - x * HRY) >> 8; | |
| (*HPATS)[pat_index]->ComposeTo(HTREG.get(), out_x, out_y, HCOMBOP); | |
| } | |
| } | |
| return HTREG; | |
| } |