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