| // 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; |
| } |