xref: /aosp_15_r20/external/pdfium/core/fxcodec/jbig2/JBig2_GrdProc.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2015 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcodec/jbig2/JBig2_GrdProc.h"
8 
9 #include <functional>
10 #include <memory>
11 #include <utility>
12 
13 #include "core/fxcodec/fax/faxmodule.h"
14 #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
15 #include "core/fxcodec/jbig2/JBig2_BitStream.h"
16 #include "core/fxcodec/jbig2/JBig2_Image.h"
17 #include "core/fxcrt/pauseindicator_iface.h"
18 
19 namespace {
20 
21 // TODO(npm): Name this constants better or merge some together.
22 constexpr uint16_t kOptConstant1[] = {0x9b25, 0x0795, 0x00e5};
23 constexpr uint16_t kOptConstant2[] = {0x0006, 0x0004, 0x0001};
24 constexpr uint16_t kOptConstant3[] = {0xf800, 0x1e00, 0x0380};
25 constexpr uint16_t kOptConstant4[] = {0x0000, 0x0001, 0x0003};
26 constexpr uint16_t kOptConstant5[] = {0x07f0, 0x01f8, 0x007c};
27 constexpr uint16_t kOptConstant6[] = {0x7bf7, 0x0efb, 0x01bd};
28 constexpr uint16_t kOptConstant7[] = {0x0800, 0x0200, 0x0080};
29 constexpr uint16_t kOptConstant8[] = {0x0010, 0x0008, 0x0004};
30 constexpr uint16_t kOptConstant9[] = {0x000c, 0x0009, 0x0007};
31 constexpr uint16_t kOptConstant10[] = {0x0007, 0x000f, 0x0007};
32 constexpr uint16_t kOptConstant11[] = {0x001f, 0x001f, 0x000f};
33 constexpr uint16_t kOptConstant12[] = {0x000f, 0x0007, 0x0003};
34 
35 }  // namespace
36 
37 CJBig2_GRDProc::ProgressiveArithDecodeState::ProgressiveArithDecodeState() =
38     default;
39 
40 CJBig2_GRDProc::ProgressiveArithDecodeState::~ProgressiveArithDecodeState() =
41     default;
42 
43 CJBig2_GRDProc::CJBig2_GRDProc() = default;
44 
45 CJBig2_GRDProc::~CJBig2_GRDProc() = default;
46 
UseTemplate0Opt3() const47 bool CJBig2_GRDProc::UseTemplate0Opt3() const {
48   return (GBAT[0] == 3) && (GBAT[1] == -1) && (GBAT[2] == -3) &&
49          (GBAT[3] == -1) && (GBAT[4] == 2) && (GBAT[5] == -2) &&
50          (GBAT[6] == -2) && (GBAT[7] == -2);
51 }
52 
UseTemplate1Opt3() const53 bool CJBig2_GRDProc::UseTemplate1Opt3() const {
54   return (GBAT[0] == 3) && (GBAT[1] == -1);
55 }
56 
UseTemplate23Opt3() const57 bool CJBig2_GRDProc::UseTemplate23Opt3() const {
58   return (GBAT[0] == 2) && (GBAT[1] == -1);
59 }
60 
DecodeArith(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)61 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::DecodeArith(
62     CJBig2_ArithDecoder* pArithDecoder,
63     JBig2ArithCtx* gbContext) {
64   if (!CJBig2_Image::IsValidImageSize(GBW, GBH))
65     return std::make_unique<CJBig2_Image>(GBW, GBH);
66 
67   switch (GBTEMPLATE) {
68     case 0:
69       return UseTemplate0Opt3()
70                  ? DecodeArithOpt3(pArithDecoder, gbContext, 0)
71                  : DecodeArithTemplateUnopt(pArithDecoder, gbContext, 0);
72     case 1:
73       return UseTemplate1Opt3()
74                  ? DecodeArithOpt3(pArithDecoder, gbContext, 1)
75                  : DecodeArithTemplateUnopt(pArithDecoder, gbContext, 1);
76     case 2:
77       return UseTemplate23Opt3()
78                  ? DecodeArithOpt3(pArithDecoder, gbContext, 2)
79                  : DecodeArithTemplateUnopt(pArithDecoder, gbContext, 2);
80     default:
81       return UseTemplate23Opt3()
82                  ? DecodeArithTemplate3Opt3(pArithDecoder, gbContext)
83                  : DecodeArithTemplate3Unopt(pArithDecoder, gbContext);
84   }
85 }
86 
DecodeArithOpt3(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,int OPT)87 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::DecodeArithOpt3(
88     CJBig2_ArithDecoder* pArithDecoder,
89     JBig2ArithCtx* gbContext,
90     int OPT) {
91   auto GBREG = std::make_unique<CJBig2_Image>(GBW, GBH);
92   if (!GBREG->data())
93     return nullptr;
94 
95   int LTP = 0;
96   uint8_t* pLine = GBREG->data();
97   int32_t nStride = GBREG->stride();
98   int32_t nStride2 = nStride << 1;
99   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
100   int32_t nBitsLeft = GBW - (nLineBytes << 3);
101   // TODO(npm): Why is the height only trimmed when OPT is 0?
102   uint32_t height = OPT == 0 ? GBH & 0x7fffffff : GBH;
103   for (uint32_t h = 0; h < height; ++h) {
104     if (TPGDON) {
105       if (pArithDecoder->IsComplete())
106         return nullptr;
107 
108       LTP = LTP ^ pArithDecoder->Decode(&gbContext[kOptConstant1[OPT]]);
109     }
110     if (LTP) {
111       GBREG->CopyLine(h, h - 1);
112     } else {
113       if (h > 1) {
114         uint8_t* pLine1 = pLine - nStride2;
115         uint8_t* pLine2 = pLine - nStride;
116         uint32_t line1 = (*pLine1++) << kOptConstant2[OPT];
117         uint32_t line2 = *pLine2++;
118         uint32_t CONTEXT = (line1 & kOptConstant3[OPT]) |
119                            ((line2 >> kOptConstant4[OPT]) & kOptConstant5[OPT]);
120         for (int32_t cc = 0; cc < nLineBytes; ++cc) {
121           line1 = (line1 << 8) | ((*pLine1++) << kOptConstant2[OPT]);
122           line2 = (line2 << 8) | (*pLine2++);
123           uint8_t cVal = 0;
124           for (int32_t k = 7; k >= 0; --k) {
125             if (pArithDecoder->IsComplete())
126               return nullptr;
127 
128             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
129             cVal |= bVal << k;
130             CONTEXT =
131                 (((CONTEXT & kOptConstant6[OPT]) << 1) | bVal |
132                  ((line1 >> k) & kOptConstant7[OPT]) |
133                  ((line2 >> (k + kOptConstant4[OPT])) & kOptConstant8[OPT]));
134           }
135           pLine[cc] = cVal;
136         }
137         line1 <<= 8;
138         line2 <<= 8;
139         uint8_t cVal1 = 0;
140         for (int32_t k = 0; k < nBitsLeft; ++k) {
141           if (pArithDecoder->IsComplete())
142             return nullptr;
143 
144           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
145           cVal1 |= bVal << (7 - k);
146           CONTEXT =
147               (((CONTEXT & kOptConstant6[OPT]) << 1) | bVal |
148                ((line1 >> (7 - k)) & kOptConstant7[OPT]) |
149                ((line2 >> (7 + kOptConstant4[OPT] - k)) & kOptConstant8[OPT]));
150         }
151         pLine[nLineBytes] = cVal1;
152       } else {
153         uint8_t* pLine2 = pLine - nStride;
154         uint32_t line2 = (h & 1) ? (*pLine2++) : 0;
155         uint32_t CONTEXT = ((line2 >> kOptConstant4[OPT]) & kOptConstant5[OPT]);
156         for (int32_t cc = 0; cc < nLineBytes; ++cc) {
157           if (h & 1) {
158             line2 = (line2 << 8) | (*pLine2++);
159           }
160           uint8_t cVal = 0;
161           for (int32_t k = 7; k >= 0; --k) {
162             if (pArithDecoder->IsComplete())
163               return nullptr;
164 
165             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
166             cVal |= bVal << k;
167             CONTEXT =
168                 (((CONTEXT & kOptConstant6[OPT]) << 1) | bVal |
169                  ((line2 >> (k + kOptConstant4[OPT])) & kOptConstant8[OPT]));
170           }
171           pLine[cc] = cVal;
172         }
173         line2 <<= 8;
174         uint8_t cVal1 = 0;
175         for (int32_t k = 0; k < nBitsLeft; ++k) {
176           if (pArithDecoder->IsComplete())
177             return nullptr;
178 
179           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
180           cVal1 |= bVal << (7 - k);
181           CONTEXT = (((CONTEXT & kOptConstant6[OPT]) << 1) | bVal |
182                      (((line2 >> (7 + kOptConstant4[OPT] - k))) &
183                       kOptConstant8[OPT]));
184         }
185         pLine[nLineBytes] = cVal1;
186       }
187     }
188     pLine += nStride;
189   }
190   return GBREG;
191 }
192 
DecodeArithTemplateUnopt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext,int UNOPT)193 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::DecodeArithTemplateUnopt(
194     CJBig2_ArithDecoder* pArithDecoder,
195     JBig2ArithCtx* gbContext,
196     int UNOPT) {
197   auto GBREG = std::make_unique<CJBig2_Image>(GBW, GBH);
198   if (!GBREG->data())
199     return nullptr;
200 
201   GBREG->Fill(false);
202   int LTP = 0;
203   uint8_t MOD2 = UNOPT % 2;
204   uint8_t DIV2 = UNOPT / 2;
205   uint8_t SHIFT = 4 - UNOPT;
206   for (uint32_t h = 0; h < GBH; h++) {
207     if (TPGDON) {
208       if (pArithDecoder->IsComplete())
209         return nullptr;
210 
211       LTP = LTP ^ pArithDecoder->Decode(&gbContext[kOptConstant1[UNOPT]]);
212     }
213     if (LTP) {
214       GBREG->CopyLine(h, h - 1);
215       continue;
216     }
217     uint32_t line1 = GBREG->GetPixel(1 + MOD2, h - 2);
218     line1 |= GBREG->GetPixel(MOD2, h - 2) << 1;
219     if (UNOPT == 1)
220       line1 |= GBREG->GetPixel(0, h - 2) << 2;
221     uint32_t line2 = GBREG->GetPixel(2 - DIV2, h - 1);
222     line2 |= GBREG->GetPixel(1 - DIV2, h - 1) << 1;
223     if (UNOPT < 2)
224       line2 |= GBREG->GetPixel(0, h - 1) << 2;
225     uint32_t line3 = 0;
226     for (uint32_t w = 0; w < GBW; w++) {
227       int bVal = 0;
228       if (!USESKIP || !SKIP->GetPixel(w, h)) {
229         if (pArithDecoder->IsComplete())
230           return nullptr;
231 
232         uint32_t CONTEXT = line3;
233         CONTEXT |= GBREG->GetPixel(w + GBAT[0], h + GBAT[1]) << SHIFT;
234         CONTEXT |= line2 << (SHIFT + 1);
235         CONTEXT |= line1 << kOptConstant9[UNOPT];
236         if (UNOPT == 0) {
237           CONTEXT |= GBREG->GetPixel(w + GBAT[2], h + GBAT[3]) << 10;
238           CONTEXT |= GBREG->GetPixel(w + GBAT[4], h + GBAT[5]) << 11;
239           CONTEXT |= GBREG->GetPixel(w + GBAT[6], h + GBAT[7]) << 15;
240         }
241         bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
242         if (bVal)
243           GBREG->SetPixel(w, h, bVal);
244       }
245       line1 = ((line1 << 1) | GBREG->GetPixel(w + 2 + MOD2, h - 2)) &
246               kOptConstant10[UNOPT];
247       line2 = ((line2 << 1) | GBREG->GetPixel(w + 3 - DIV2, h - 1)) &
248               kOptConstant11[UNOPT];
249       line3 = ((line3 << 1) | bVal) & kOptConstant12[UNOPT];
250     }
251   }
252   return GBREG;
253 }
254 
DecodeArithTemplate3Opt3(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)255 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::DecodeArithTemplate3Opt3(
256     CJBig2_ArithDecoder* pArithDecoder,
257     JBig2ArithCtx* gbContext) {
258   auto GBREG = std::make_unique<CJBig2_Image>(GBW, GBH);
259   if (!GBREG->data())
260     return nullptr;
261 
262   int LTP = 0;
263   uint8_t* pLine = GBREG->data();
264   int32_t nStride = GBREG->stride();
265   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
266   int32_t nBitsLeft = GBW - (nLineBytes << 3);
267 
268   for (uint32_t h = 0; h < GBH; h++) {
269     if (TPGDON) {
270       if (pArithDecoder->IsComplete())
271         return nullptr;
272 
273       LTP = LTP ^ pArithDecoder->Decode(&gbContext[0x0195]);
274     }
275 
276     if (LTP) {
277       GBREG->CopyLine(h, h - 1);
278     } else {
279       if (h > 0) {
280         uint8_t* pLine1 = pLine - nStride;
281         uint32_t line1 = *pLine1++;
282         uint32_t CONTEXT = (line1 >> 1) & 0x03f0;
283         for (int32_t cc = 0; cc < nLineBytes; cc++) {
284           line1 = (line1 << 8) | (*pLine1++);
285           uint8_t cVal = 0;
286           for (int32_t k = 7; k >= 0; k--) {
287             if (pArithDecoder->IsComplete())
288               return nullptr;
289 
290             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
291             cVal |= bVal << k;
292             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal |
293                       ((line1 >> (k + 1)) & 0x0010);
294           }
295           pLine[cc] = cVal;
296         }
297         line1 <<= 8;
298         uint8_t cVal1 = 0;
299         for (int32_t k = 0; k < nBitsLeft; k++) {
300           if (pArithDecoder->IsComplete())
301             return nullptr;
302 
303           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
304           cVal1 |= bVal << (7 - k);
305           CONTEXT =
306               ((CONTEXT & 0x01f7) << 1) | bVal | ((line1 >> (8 - k)) & 0x0010);
307         }
308         pLine[nLineBytes] = cVal1;
309       } else {
310         uint32_t CONTEXT = 0;
311         for (int32_t cc = 0; cc < nLineBytes; cc++) {
312           uint8_t cVal = 0;
313           for (int32_t k = 7; k >= 0; k--) {
314             if (pArithDecoder->IsComplete())
315               return nullptr;
316 
317             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
318             cVal |= bVal << k;
319             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
320           }
321           pLine[cc] = cVal;
322         }
323         uint8_t cVal1 = 0;
324         for (int32_t k = 0; k < nBitsLeft; k++) {
325           if (pArithDecoder->IsComplete())
326             return nullptr;
327 
328           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
329           cVal1 |= bVal << (7 - k);
330           CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
331         }
332         pLine[nLineBytes] = cVal1;
333       }
334     }
335     pLine += nStride;
336   }
337   return GBREG;
338 }
339 
DecodeArithTemplate3Unopt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * gbContext)340 std::unique_ptr<CJBig2_Image> CJBig2_GRDProc::DecodeArithTemplate3Unopt(
341     CJBig2_ArithDecoder* pArithDecoder,
342     JBig2ArithCtx* gbContext) {
343   auto GBREG = std::make_unique<CJBig2_Image>(GBW, GBH);
344   if (!GBREG->data())
345     return nullptr;
346 
347   GBREG->Fill(false);
348   int LTP = 0;
349   for (uint32_t h = 0; h < GBH; h++) {
350     if (TPGDON) {
351       if (pArithDecoder->IsComplete())
352         return nullptr;
353 
354       LTP = LTP ^ pArithDecoder->Decode(&gbContext[0x0195]);
355     }
356     if (LTP == 1) {
357       GBREG->CopyLine(h, h - 1);
358     } else {
359       uint32_t line1 = GBREG->GetPixel(1, h - 1);
360       line1 |= GBREG->GetPixel(0, h - 1) << 1;
361       uint32_t line2 = 0;
362       for (uint32_t w = 0; w < GBW; w++) {
363         int bVal;
364         if (USESKIP && SKIP->GetPixel(w, h)) {
365           bVal = 0;
366         } else {
367           uint32_t CONTEXT = line2;
368           CONTEXT |= GBREG->GetPixel(w + GBAT[0], h + GBAT[1]) << 4;
369           CONTEXT |= line1 << 5;
370           if (pArithDecoder->IsComplete())
371             return nullptr;
372 
373           bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
374         }
375         if (bVal) {
376           GBREG->SetPixel(w, h, bVal);
377         }
378         line1 = ((line1 << 1) | GBREG->GetPixel(w + 2, h - 1)) & 0x1f;
379         line2 = ((line2 << 1) | bVal) & 0x0f;
380       }
381     }
382   }
383   return GBREG;
384 }
385 
StartDecodeArith(ProgressiveArithDecodeState * pState)386 FXCODEC_STATUS CJBig2_GRDProc::StartDecodeArith(
387     ProgressiveArithDecodeState* pState) {
388   if (!CJBig2_Image::IsValidImageSize(GBW, GBH)) {
389     m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
390     return FXCODEC_STATUS::kDecodeFinished;
391   }
392   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeReady;
393   std::unique_ptr<CJBig2_Image>* pImage = pState->pImage;
394   if (!*pImage)
395     *pImage = std::make_unique<CJBig2_Image>(GBW, GBH);
396   if (!(*pImage)->data()) {
397     *pImage = nullptr;
398     m_ProgressiveStatus = FXCODEC_STATUS::kError;
399     return FXCODEC_STATUS::kError;
400   }
401   pImage->get()->Fill(false);
402   m_DecodeType = 1;
403   m_LTP = 0;
404   m_pLine = nullptr;
405   m_loopIndex = 0;
406   return ProgressiveDecodeArith(pState);
407 }
408 
ProgressiveDecodeArith(ProgressiveArithDecodeState * pState)409 FXCODEC_STATUS CJBig2_GRDProc::ProgressiveDecodeArith(
410     ProgressiveArithDecodeState* pState) {
411   int iline = m_loopIndex;
412 
413   using DecodeFunction = std::function<FXCODEC_STATUS(
414       CJBig2_GRDProc&, ProgressiveArithDecodeState*)>;
415   DecodeFunction func;
416   switch (GBTEMPLATE) {
417     case 0:
418       func = UseTemplate0Opt3()
419                  ? &CJBig2_GRDProc::ProgressiveDecodeArithTemplate0Opt3
420                  : &CJBig2_GRDProc::ProgressiveDecodeArithTemplate0Unopt;
421       break;
422     case 1:
423       func = UseTemplate1Opt3()
424                  ? &CJBig2_GRDProc::ProgressiveDecodeArithTemplate1Opt3
425                  : &CJBig2_GRDProc::ProgressiveDecodeArithTemplate1Unopt;
426       break;
427     case 2:
428       func = UseTemplate23Opt3()
429                  ? &CJBig2_GRDProc::ProgressiveDecodeArithTemplate2Opt3
430                  : &CJBig2_GRDProc::ProgressiveDecodeArithTemplate2Unopt;
431       break;
432     default:
433       func = UseTemplate23Opt3()
434                  ? &CJBig2_GRDProc::ProgressiveDecodeArithTemplate3Opt3
435                  : &CJBig2_GRDProc::ProgressiveDecodeArithTemplate3Unopt;
436       break;
437   }
438   CJBig2_Image* pImage = pState->pImage->get();
439   m_ProgressiveStatus = func(*this, pState);
440   m_ReplaceRect.left = 0;
441   m_ReplaceRect.right = pImage->width();
442   m_ReplaceRect.top = iline;
443   m_ReplaceRect.bottom = m_loopIndex;
444   if (m_ProgressiveStatus == FXCODEC_STATUS::kDecodeFinished)
445     m_loopIndex = 0;
446 
447   return m_ProgressiveStatus;
448 }
449 
StartDecodeMMR(std::unique_ptr<CJBig2_Image> * pImage,CJBig2_BitStream * pStream)450 FXCODEC_STATUS CJBig2_GRDProc::StartDecodeMMR(
451     std::unique_ptr<CJBig2_Image>* pImage,
452     CJBig2_BitStream* pStream) {
453   auto image = std::make_unique<CJBig2_Image>(GBW, GBH);
454   if (!image->data()) {
455     *pImage = nullptr;
456     m_ProgressiveStatus = FXCODEC_STATUS::kError;
457     return m_ProgressiveStatus;
458   }
459   int bitpos = static_cast<int>(pStream->getBitPos());
460   bitpos =
461       FaxModule::FaxG4Decode(pStream->getBuf(), pStream->getLength(), bitpos,
462                              GBW, GBH, image->stride(), image->data());
463   pStream->setBitPos(bitpos);
464   for (uint32_t i = 0; i < image->stride() * GBH; ++i)
465     image->data()[i] = ~image->data()[i];
466   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
467   *pImage = std::move(image);
468   return m_ProgressiveStatus;
469 }
470 
ContinueDecode(ProgressiveArithDecodeState * pState)471 FXCODEC_STATUS CJBig2_GRDProc::ContinueDecode(
472     ProgressiveArithDecodeState* pState) {
473   if (m_ProgressiveStatus != FXCODEC_STATUS::kDecodeToBeContinued)
474     return m_ProgressiveStatus;
475 
476   if (m_DecodeType != 1) {
477     m_ProgressiveStatus = FXCODEC_STATUS::kError;
478     return m_ProgressiveStatus;
479   }
480   return ProgressiveDecodeArith(pState);
481 }
482 
ProgressiveDecodeArithTemplate0Opt3(ProgressiveArithDecodeState * pState)483 FXCODEC_STATUS CJBig2_GRDProc::ProgressiveDecodeArithTemplate0Opt3(
484     ProgressiveArithDecodeState* pState) {
485   CJBig2_Image* pImage = pState->pImage->get();
486   JBig2ArithCtx* gbContext = pState->gbContext;
487   CJBig2_ArithDecoder* pArithDecoder = pState->pArithDecoder;
488   if (!m_pLine)
489     m_pLine = pImage->data();
490   int32_t nStride = pImage->stride();
491   int32_t nStride2 = nStride << 1;
492   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
493   int32_t nBitsLeft = GBW - (nLineBytes << 3);
494   uint32_t height = GBH & 0x7fffffff;
495 
496   for (; m_loopIndex < height; m_loopIndex++) {
497     if (TPGDON) {
498       if (pArithDecoder->IsComplete())
499         return FXCODEC_STATUS::kError;
500 
501       m_LTP = m_LTP ^ pArithDecoder->Decode(&gbContext[0x9b25]);
502     }
503     if (m_LTP) {
504       pImage->CopyLine(m_loopIndex, m_loopIndex - 1);
505     } else {
506       if (m_loopIndex > 1) {
507         uint8_t* pLine1 = m_pLine - nStride2;
508         uint8_t* pLine2 = m_pLine - nStride;
509         uint32_t line1 = (*pLine1++) << 6;
510         uint32_t line2 = *pLine2++;
511         uint32_t CONTEXT = ((line1 & 0xf800) | (line2 & 0x07f0));
512         for (int32_t cc = 0; cc < nLineBytes; cc++) {
513           line1 = (line1 << 8) | ((*pLine1++) << 6);
514           line2 = (line2 << 8) | (*pLine2++);
515           uint8_t cVal = 0;
516           for (int32_t k = 7; k >= 0; k--) {
517             if (pArithDecoder->IsComplete())
518               return FXCODEC_STATUS::kError;
519 
520             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
521             cVal |= bVal << k;
522             CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
523                        ((line1 >> k) & 0x0800) | ((line2 >> k) & 0x0010));
524           }
525           m_pLine[cc] = cVal;
526         }
527         line1 <<= 8;
528         line2 <<= 8;
529         uint8_t cVal1 = 0;
530         for (int32_t k = 0; k < nBitsLeft; k++) {
531           if (pArithDecoder->IsComplete())
532             return FXCODEC_STATUS::kError;
533 
534           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
535           cVal1 |= bVal << (7 - k);
536           CONTEXT =
537               (((CONTEXT & 0x7bf7) << 1) | bVal |
538                ((line1 >> (7 - k)) & 0x0800) | ((line2 >> (7 - k)) & 0x0010));
539         }
540         m_pLine[nLineBytes] = cVal1;
541       } else {
542         uint8_t* pLine2 = m_pLine - nStride;
543         uint32_t line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
544         uint32_t CONTEXT = (line2 & 0x07f0);
545         for (int32_t cc = 0; cc < nLineBytes; cc++) {
546           if (m_loopIndex & 1) {
547             line2 = (line2 << 8) | (*pLine2++);
548           }
549           uint8_t cVal = 0;
550           for (int32_t k = 7; k >= 0; k--) {
551             if (pArithDecoder->IsComplete())
552               return FXCODEC_STATUS::kError;
553 
554             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
555             cVal |= bVal << k;
556             CONTEXT =
557                 (((CONTEXT & 0x7bf7) << 1) | bVal | ((line2 >> k) & 0x0010));
558           }
559           m_pLine[cc] = cVal;
560         }
561         line2 <<= 8;
562         uint8_t cVal1 = 0;
563         for (int32_t k = 0; k < nBitsLeft; k++) {
564           if (pArithDecoder->IsComplete())
565             return FXCODEC_STATUS::kError;
566 
567           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
568           cVal1 |= bVal << (7 - k);
569           CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
570                      ((line2 >> (7 - k)) & 0x0010));
571         }
572         m_pLine[nLineBytes] = cVal1;
573       }
574     }
575     m_pLine += nStride;
576     if (pState->pPause && pState->pPause->NeedToPauseNow()) {
577       m_loopIndex++;
578       m_ProgressiveStatus = FXCODEC_STATUS::kDecodeToBeContinued;
579       return FXCODEC_STATUS::kDecodeToBeContinued;
580     }
581   }
582   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
583   return FXCODEC_STATUS::kDecodeFinished;
584 }
585 
ProgressiveDecodeArithTemplate0Unopt(ProgressiveArithDecodeState * pState)586 FXCODEC_STATUS CJBig2_GRDProc::ProgressiveDecodeArithTemplate0Unopt(
587     ProgressiveArithDecodeState* pState) {
588   CJBig2_Image* pImage = pState->pImage->get();
589   JBig2ArithCtx* gbContext = pState->gbContext;
590   CJBig2_ArithDecoder* pArithDecoder = pState->pArithDecoder;
591   for (; m_loopIndex < GBH; m_loopIndex++) {
592     if (TPGDON) {
593       if (pArithDecoder->IsComplete())
594         return FXCODEC_STATUS::kError;
595 
596       m_LTP = m_LTP ^ pArithDecoder->Decode(&gbContext[0x9b25]);
597     }
598     if (m_LTP) {
599       pImage->CopyLine(m_loopIndex, m_loopIndex - 1);
600     } else {
601       uint32_t line1 = pImage->GetPixel(1, m_loopIndex - 2);
602       line1 |= pImage->GetPixel(0, m_loopIndex - 2) << 1;
603       uint32_t line2 = pImage->GetPixel(2, m_loopIndex - 1);
604       line2 |= pImage->GetPixel(1, m_loopIndex - 1) << 1;
605       line2 |= pImage->GetPixel(0, m_loopIndex - 1) << 2;
606       uint32_t line3 = 0;
607       for (uint32_t w = 0; w < GBW; w++) {
608         int bVal;
609         if (USESKIP && SKIP->GetPixel(w, m_loopIndex)) {
610           bVal = 0;
611         } else {
612           uint32_t CONTEXT = line3;
613           CONTEXT |= pImage->GetPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 4;
614           CONTEXT |= line2 << 5;
615           CONTEXT |= pImage->GetPixel(w + GBAT[2], m_loopIndex + GBAT[3]) << 10;
616           CONTEXT |= pImage->GetPixel(w + GBAT[4], m_loopIndex + GBAT[5]) << 11;
617           CONTEXT |= line1 << 12;
618           CONTEXT |= pImage->GetPixel(w + GBAT[6], m_loopIndex + GBAT[7]) << 15;
619           if (pArithDecoder->IsComplete())
620             return FXCODEC_STATUS::kError;
621 
622           bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
623         }
624         if (bVal) {
625           pImage->SetPixel(w, m_loopIndex, bVal);
626         }
627         line1 =
628             ((line1 << 1) | pImage->GetPixel(w + 2, m_loopIndex - 2)) & 0x07;
629         line2 =
630             ((line2 << 1) | pImage->GetPixel(w + 3, m_loopIndex - 1)) & 0x1f;
631         line3 = ((line3 << 1) | bVal) & 0x0f;
632       }
633     }
634     if (pState->pPause && pState->pPause->NeedToPauseNow()) {
635       m_loopIndex++;
636       m_ProgressiveStatus = FXCODEC_STATUS::kDecodeToBeContinued;
637       return FXCODEC_STATUS::kDecodeToBeContinued;
638     }
639   }
640   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
641   return FXCODEC_STATUS::kDecodeFinished;
642 }
643 
ProgressiveDecodeArithTemplate1Opt3(ProgressiveArithDecodeState * pState)644 FXCODEC_STATUS CJBig2_GRDProc::ProgressiveDecodeArithTemplate1Opt3(
645     ProgressiveArithDecodeState* pState) {
646   CJBig2_Image* pImage = pState->pImage->get();
647   JBig2ArithCtx* gbContext = pState->gbContext;
648   CJBig2_ArithDecoder* pArithDecoder = pState->pArithDecoder;
649   if (!m_pLine)
650     m_pLine = pImage->data();
651   int32_t nStride = pImage->stride();
652   int32_t nStride2 = nStride << 1;
653   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
654   int32_t nBitsLeft = GBW - (nLineBytes << 3);
655   for (; m_loopIndex < GBH; m_loopIndex++) {
656     if (TPGDON) {
657       if (pArithDecoder->IsComplete())
658         return FXCODEC_STATUS::kError;
659 
660       m_LTP = m_LTP ^ pArithDecoder->Decode(&gbContext[0x0795]);
661     }
662     if (m_LTP) {
663       pImage->CopyLine(m_loopIndex, m_loopIndex - 1);
664     } else {
665       if (m_loopIndex > 1) {
666         uint8_t* pLine1 = m_pLine - nStride2;
667         uint8_t* pLine2 = m_pLine - nStride;
668         uint32_t line1 = (*pLine1++) << 4;
669         uint32_t line2 = *pLine2++;
670         uint32_t CONTEXT = (line1 & 0x1e00) | ((line2 >> 1) & 0x01f8);
671         for (int32_t cc = 0; cc < nLineBytes; cc++) {
672           line1 = (line1 << 8) | ((*pLine1++) << 4);
673           line2 = (line2 << 8) | (*pLine2++);
674           uint8_t cVal = 0;
675           for (int32_t k = 7; k >= 0; k--) {
676             if (pArithDecoder->IsComplete())
677               return FXCODEC_STATUS::kError;
678 
679             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
680             cVal |= bVal << k;
681             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
682                       ((line1 >> k) & 0x0200) | ((line2 >> (k + 1)) & 0x0008);
683           }
684           m_pLine[cc] = cVal;
685         }
686         line1 <<= 8;
687         line2 <<= 8;
688         uint8_t cVal1 = 0;
689         for (int32_t k = 0; k < nBitsLeft; k++) {
690           if (pArithDecoder->IsComplete())
691             return FXCODEC_STATUS::kError;
692 
693           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
694           cVal1 |= bVal << (7 - k);
695           CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
696                     ((line1 >> (7 - k)) & 0x0200) |
697                     ((line2 >> (8 - k)) & 0x0008);
698         }
699         m_pLine[nLineBytes] = cVal1;
700       } else {
701         uint8_t* pLine2 = m_pLine - nStride;
702         uint32_t line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
703         uint32_t CONTEXT = (line2 >> 1) & 0x01f8;
704         for (int32_t cc = 0; cc < nLineBytes; cc++) {
705           if (m_loopIndex & 1) {
706             line2 = (line2 << 8) | (*pLine2++);
707           }
708           uint8_t cVal = 0;
709           for (int32_t k = 7; k >= 0; k--) {
710             if (pArithDecoder->IsComplete())
711               return FXCODEC_STATUS::kError;
712 
713             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
714             cVal |= bVal << k;
715             CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
716                       ((line2 >> (k + 1)) & 0x0008);
717           }
718           m_pLine[cc] = cVal;
719         }
720         line2 <<= 8;
721         uint8_t cVal1 = 0;
722         for (int32_t k = 0; k < nBitsLeft; k++) {
723           if (pArithDecoder->IsComplete())
724             return FXCODEC_STATUS::kError;
725 
726           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
727           cVal1 |= bVal << (7 - k);
728           CONTEXT =
729               ((CONTEXT & 0x0efb) << 1) | bVal | ((line2 >> (8 - k)) & 0x0008);
730         }
731         m_pLine[nLineBytes] = cVal1;
732       }
733     }
734     m_pLine += nStride;
735     if (pState->pPause && pState->pPause->NeedToPauseNow()) {
736       m_loopIndex++;
737       m_ProgressiveStatus = FXCODEC_STATUS::kDecodeToBeContinued;
738       return FXCODEC_STATUS::kDecodeToBeContinued;
739     }
740   }
741   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
742   return FXCODEC_STATUS::kDecodeFinished;
743 }
744 
ProgressiveDecodeArithTemplate1Unopt(ProgressiveArithDecodeState * pState)745 FXCODEC_STATUS CJBig2_GRDProc::ProgressiveDecodeArithTemplate1Unopt(
746     ProgressiveArithDecodeState* pState) {
747   CJBig2_Image* pImage = pState->pImage->get();
748   JBig2ArithCtx* gbContext = pState->gbContext;
749   CJBig2_ArithDecoder* pArithDecoder = pState->pArithDecoder;
750   for (uint32_t h = 0; h < GBH; h++) {
751     if (TPGDON) {
752       if (pArithDecoder->IsComplete())
753         return FXCODEC_STATUS::kError;
754 
755       m_LTP = m_LTP ^ pArithDecoder->Decode(&gbContext[0x0795]);
756     }
757     if (m_LTP) {
758       pImage->CopyLine(h, h - 1);
759     } else {
760       uint32_t line1 = pImage->GetPixel(2, h - 2);
761       line1 |= pImage->GetPixel(1, h - 2) << 1;
762       line1 |= pImage->GetPixel(0, h - 2) << 2;
763       uint32_t line2 = pImage->GetPixel(2, h - 1);
764       line2 |= pImage->GetPixel(1, h - 1) << 1;
765       line2 |= pImage->GetPixel(0, h - 1) << 2;
766       uint32_t line3 = 0;
767       for (uint32_t w = 0; w < GBW; w++) {
768         int bVal;
769         if (USESKIP && SKIP->GetPixel(w, h)) {
770           bVal = 0;
771         } else {
772           uint32_t CONTEXT = line3;
773           CONTEXT |= pImage->GetPixel(w + GBAT[0], h + GBAT[1]) << 3;
774           CONTEXT |= line2 << 4;
775           CONTEXT |= line1 << 9;
776           if (pArithDecoder->IsComplete())
777             return FXCODEC_STATUS::kError;
778 
779           bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
780         }
781         if (bVal) {
782           pImage->SetPixel(w, h, bVal);
783         }
784         line1 = ((line1 << 1) | pImage->GetPixel(w + 3, h - 2)) & 0x0f;
785         line2 = ((line2 << 1) | pImage->GetPixel(w + 3, h - 1)) & 0x1f;
786         line3 = ((line3 << 1) | bVal) & 0x07;
787       }
788     }
789     if (pState->pPause && pState->pPause->NeedToPauseNow()) {
790       m_loopIndex++;
791       m_ProgressiveStatus = FXCODEC_STATUS::kDecodeToBeContinued;
792       return FXCODEC_STATUS::kDecodeToBeContinued;
793     }
794   }
795   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
796   return FXCODEC_STATUS::kDecodeFinished;
797 }
798 
ProgressiveDecodeArithTemplate2Opt3(ProgressiveArithDecodeState * pState)799 FXCODEC_STATUS CJBig2_GRDProc::ProgressiveDecodeArithTemplate2Opt3(
800     ProgressiveArithDecodeState* pState) {
801   CJBig2_Image* pImage = pState->pImage->get();
802   JBig2ArithCtx* gbContext = pState->gbContext;
803   CJBig2_ArithDecoder* pArithDecoder = pState->pArithDecoder;
804   if (!m_pLine)
805     m_pLine = pImage->data();
806   int32_t nStride = pImage->stride();
807   int32_t nStride2 = nStride << 1;
808   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
809   int32_t nBitsLeft = GBW - (nLineBytes << 3);
810   for (; m_loopIndex < GBH; m_loopIndex++) {
811     if (TPGDON) {
812       if (pArithDecoder->IsComplete())
813         return FXCODEC_STATUS::kError;
814 
815       m_LTP = m_LTP ^ pArithDecoder->Decode(&gbContext[0x00e5]);
816     }
817     if (m_LTP) {
818       pImage->CopyLine(m_loopIndex, m_loopIndex - 1);
819     } else {
820       if (m_loopIndex > 1) {
821         uint8_t* pLine1 = m_pLine - nStride2;
822         uint8_t* pLine2 = m_pLine - nStride;
823         uint32_t line1 = (*pLine1++) << 1;
824         uint32_t line2 = *pLine2++;
825         uint32_t CONTEXT = (line1 & 0x0380) | ((line2 >> 3) & 0x007c);
826         for (int32_t cc = 0; cc < nLineBytes; cc++) {
827           line1 = (line1 << 8) | ((*pLine1++) << 1);
828           line2 = (line2 << 8) | (*pLine2++);
829           uint8_t cVal = 0;
830           for (int32_t k = 7; k >= 0; k--) {
831             if (pArithDecoder->IsComplete())
832               return FXCODEC_STATUS::kError;
833 
834             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
835             cVal |= bVal << k;
836             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
837                       ((line1 >> k) & 0x0080) | ((line2 >> (k + 3)) & 0x0004);
838           }
839           m_pLine[cc] = cVal;
840         }
841         line1 <<= 8;
842         line2 <<= 8;
843         uint8_t cVal1 = 0;
844         for (int32_t k = 0; k < nBitsLeft; k++) {
845           if (pArithDecoder->IsComplete())
846             return FXCODEC_STATUS::kError;
847 
848           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
849           cVal1 |= bVal << (7 - k);
850           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
851                     ((line1 >> (7 - k)) & 0x0080) |
852                     ((line2 >> (10 - k)) & 0x0004);
853         }
854         m_pLine[nLineBytes] = cVal1;
855       } else {
856         uint8_t* pLine2 = m_pLine - nStride;
857         uint32_t line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
858         uint32_t CONTEXT = (line2 >> 3) & 0x007c;
859         for (int32_t cc = 0; cc < nLineBytes; cc++) {
860           if (m_loopIndex & 1) {
861             line2 = (line2 << 8) | (*pLine2++);
862           }
863           uint8_t cVal = 0;
864           for (int32_t k = 7; k >= 0; k--) {
865             if (pArithDecoder->IsComplete())
866               return FXCODEC_STATUS::kError;
867 
868             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
869             cVal |= bVal << k;
870             CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
871                       ((line2 >> (k + 3)) & 0x0004);
872           }
873           m_pLine[cc] = cVal;
874         }
875         line2 <<= 8;
876         uint8_t cVal1 = 0;
877         for (int32_t k = 0; k < nBitsLeft; k++) {
878           if (pArithDecoder->IsComplete())
879             return FXCODEC_STATUS::kError;
880 
881           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
882           cVal1 |= bVal << (7 - k);
883           CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
884                     (((line2 >> (10 - k))) & 0x0004);
885         }
886         m_pLine[nLineBytes] = cVal1;
887       }
888     }
889     m_pLine += nStride;
890     if (pState->pPause && m_loopIndex % 50 == 0 &&
891         pState->pPause->NeedToPauseNow()) {
892       m_loopIndex++;
893       m_ProgressiveStatus = FXCODEC_STATUS::kDecodeToBeContinued;
894       return FXCODEC_STATUS::kDecodeToBeContinued;
895     }
896   }
897   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
898   return FXCODEC_STATUS::kDecodeFinished;
899 }
900 
ProgressiveDecodeArithTemplate2Unopt(ProgressiveArithDecodeState * pState)901 FXCODEC_STATUS CJBig2_GRDProc::ProgressiveDecodeArithTemplate2Unopt(
902     ProgressiveArithDecodeState* pState) {
903   CJBig2_Image* pImage = pState->pImage->get();
904   JBig2ArithCtx* gbContext = pState->gbContext;
905   CJBig2_ArithDecoder* pArithDecoder = pState->pArithDecoder;
906   for (; m_loopIndex < GBH; m_loopIndex++) {
907     if (TPGDON) {
908       if (pArithDecoder->IsComplete())
909         return FXCODEC_STATUS::kError;
910 
911       m_LTP = m_LTP ^ pArithDecoder->Decode(&gbContext[0x00e5]);
912     }
913     if (m_LTP) {
914       pImage->CopyLine(m_loopIndex, m_loopIndex - 1);
915     } else {
916       uint32_t line1 = pImage->GetPixel(1, m_loopIndex - 2);
917       line1 |= pImage->GetPixel(0, m_loopIndex - 2) << 1;
918       uint32_t line2 = pImage->GetPixel(1, m_loopIndex - 1);
919       line2 |= pImage->GetPixel(0, m_loopIndex - 1) << 1;
920       uint32_t line3 = 0;
921       for (uint32_t w = 0; w < GBW; w++) {
922         int bVal;
923         if (USESKIP && SKIP->GetPixel(w, m_loopIndex)) {
924           bVal = 0;
925         } else {
926           uint32_t CONTEXT = line3;
927           CONTEXT |= pImage->GetPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 2;
928           CONTEXT |= line2 << 3;
929           CONTEXT |= line1 << 7;
930           if (pArithDecoder->IsComplete())
931             return FXCODEC_STATUS::kError;
932 
933           bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
934         }
935         if (bVal) {
936           pImage->SetPixel(w, m_loopIndex, bVal);
937         }
938         line1 =
939             ((line1 << 1) | pImage->GetPixel(w + 2, m_loopIndex - 2)) & 0x07;
940         line2 =
941             ((line2 << 1) | pImage->GetPixel(w + 2, m_loopIndex - 1)) & 0x0f;
942         line3 = ((line3 << 1) | bVal) & 0x03;
943       }
944     }
945     if (pState->pPause && pState->pPause->NeedToPauseNow()) {
946       m_loopIndex++;
947       m_ProgressiveStatus = FXCODEC_STATUS::kDecodeToBeContinued;
948       return FXCODEC_STATUS::kDecodeToBeContinued;
949     }
950   }
951   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
952   return FXCODEC_STATUS::kDecodeFinished;
953 }
954 
ProgressiveDecodeArithTemplate3Opt3(ProgressiveArithDecodeState * pState)955 FXCODEC_STATUS CJBig2_GRDProc::ProgressiveDecodeArithTemplate3Opt3(
956     ProgressiveArithDecodeState* pState) {
957   CJBig2_Image* pImage = pState->pImage->get();
958   JBig2ArithCtx* gbContext = pState->gbContext;
959   CJBig2_ArithDecoder* pArithDecoder = pState->pArithDecoder;
960   if (!m_pLine)
961     m_pLine = pImage->data();
962   int32_t nStride = pImage->stride();
963   int32_t nLineBytes = ((GBW + 7) >> 3) - 1;
964   int32_t nBitsLeft = GBW - (nLineBytes << 3);
965   for (; m_loopIndex < GBH; m_loopIndex++) {
966     if (TPGDON) {
967       if (pArithDecoder->IsComplete())
968         return FXCODEC_STATUS::kError;
969 
970       m_LTP = m_LTP ^ pArithDecoder->Decode(&gbContext[0x0195]);
971     }
972     if (m_LTP) {
973       pImage->CopyLine(m_loopIndex, m_loopIndex - 1);
974     } else {
975       if (m_loopIndex > 0) {
976         uint8_t* pLine1 = m_pLine - nStride;
977         uint32_t line1 = *pLine1++;
978         uint32_t CONTEXT = (line1 >> 1) & 0x03f0;
979         for (int32_t cc = 0; cc < nLineBytes; cc++) {
980           line1 = (line1 << 8) | (*pLine1++);
981           uint8_t cVal = 0;
982           for (int32_t k = 7; k >= 0; k--) {
983             if (pArithDecoder->IsComplete())
984               return FXCODEC_STATUS::kError;
985 
986             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
987             cVal |= bVal << k;
988             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal |
989                       ((line1 >> (k + 1)) & 0x0010);
990           }
991           m_pLine[cc] = cVal;
992         }
993         line1 <<= 8;
994         uint8_t cVal1 = 0;
995         for (int32_t k = 0; k < nBitsLeft; k++) {
996           if (pArithDecoder->IsComplete())
997             return FXCODEC_STATUS::kError;
998 
999           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
1000           cVal1 |= bVal << (7 - k);
1001           CONTEXT =
1002               ((CONTEXT & 0x01f7) << 1) | bVal | ((line1 >> (8 - k)) & 0x0010);
1003         }
1004         m_pLine[nLineBytes] = cVal1;
1005       } else {
1006         uint32_t CONTEXT = 0;
1007         for (int32_t cc = 0; cc < nLineBytes; cc++) {
1008           uint8_t cVal = 0;
1009           for (int32_t k = 7; k >= 0; k--) {
1010             if (pArithDecoder->IsComplete())
1011               return FXCODEC_STATUS::kError;
1012 
1013             int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
1014             cVal |= bVal << k;
1015             CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
1016           }
1017           m_pLine[cc] = cVal;
1018         }
1019         uint8_t cVal1 = 0;
1020         for (int32_t k = 0; k < nBitsLeft; k++) {
1021           if (pArithDecoder->IsComplete())
1022             return FXCODEC_STATUS::kError;
1023 
1024           int bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
1025           cVal1 |= bVal << (7 - k);
1026           CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
1027         }
1028         m_pLine[nLineBytes] = cVal1;
1029       }
1030     }
1031     m_pLine += nStride;
1032     if (pState->pPause && pState->pPause->NeedToPauseNow()) {
1033       m_loopIndex++;
1034       m_ProgressiveStatus = FXCODEC_STATUS::kDecodeToBeContinued;
1035       return FXCODEC_STATUS::kDecodeToBeContinued;
1036     }
1037   }
1038   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
1039   return FXCODEC_STATUS::kDecodeFinished;
1040 }
1041 
ProgressiveDecodeArithTemplate3Unopt(ProgressiveArithDecodeState * pState)1042 FXCODEC_STATUS CJBig2_GRDProc::ProgressiveDecodeArithTemplate3Unopt(
1043     ProgressiveArithDecodeState* pState) {
1044   CJBig2_Image* pImage = pState->pImage->get();
1045   JBig2ArithCtx* gbContext = pState->gbContext;
1046   CJBig2_ArithDecoder* pArithDecoder = pState->pArithDecoder;
1047   for (; m_loopIndex < GBH; m_loopIndex++) {
1048     if (TPGDON) {
1049       if (pArithDecoder->IsComplete())
1050         return FXCODEC_STATUS::kError;
1051 
1052       m_LTP = m_LTP ^ pArithDecoder->Decode(&gbContext[0x0195]);
1053     }
1054     if (m_LTP) {
1055       pImage->CopyLine(m_loopIndex, m_loopIndex - 1);
1056     } else {
1057       uint32_t line1 = pImage->GetPixel(1, m_loopIndex - 1);
1058       line1 |= pImage->GetPixel(0, m_loopIndex - 1) << 1;
1059       uint32_t line2 = 0;
1060       for (uint32_t w = 0; w < GBW; w++) {
1061         int bVal;
1062         if (USESKIP && SKIP->GetPixel(w, m_loopIndex)) {
1063           bVal = 0;
1064         } else {
1065           uint32_t CONTEXT = line2;
1066           CONTEXT |= pImage->GetPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 4;
1067           CONTEXT |= line1 << 5;
1068           if (pArithDecoder->IsComplete())
1069             return FXCODEC_STATUS::kError;
1070 
1071           bVal = pArithDecoder->Decode(&gbContext[CONTEXT]);
1072         }
1073         if (bVal) {
1074           pImage->SetPixel(w, m_loopIndex, bVal);
1075         }
1076         line1 =
1077             ((line1 << 1) | pImage->GetPixel(w + 2, m_loopIndex - 1)) & 0x1f;
1078         line2 = ((line2 << 1) | bVal) & 0x0f;
1079       }
1080     }
1081     if (pState->pPause && pState->pPause->NeedToPauseNow()) {
1082       m_loopIndex++;
1083       m_ProgressiveStatus = FXCODEC_STATUS::kDecodeToBeContinued;
1084       return FXCODEC_STATUS::kDecodeToBeContinued;
1085     }
1086   }
1087   m_ProgressiveStatus = FXCODEC_STATUS::kDecodeFinished;
1088   return FXCODEC_STATUS::kDecodeFinished;
1089 }
1090