• 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_GrrdProc.h"
8 
9 #include <memory>
10 
11 #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
12 #include "core/fxcodec/jbig2/JBig2_BitStream.h"
13 #include "core/fxcodec/jbig2/JBig2_Image.h"
14 #include "third_party/base/ptr_util.h"
15 
decode(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * grContext)16 std::unique_ptr<CJBig2_Image> CJBig2_GRRDProc::decode(
17     CJBig2_ArithDecoder* pArithDecoder,
18     JBig2ArithCtx* grContext) {
19   if (GRW == 0 || GRW > JBIG2_MAX_IMAGE_SIZE || GRH == 0 ||
20       GRH > JBIG2_MAX_IMAGE_SIZE) {
21     return pdfium::MakeUnique<CJBig2_Image>(GRW, GRH);
22   }
23 
24   if (!GRTEMPLATE) {
25     if ((GRAT[0] == -1) && (GRAT[1] == -1) && (GRAT[2] == -1) &&
26         (GRAT[3] == -1) && (GRREFERENCEDX == 0) &&
27         (GRW == (uint32_t)GRREFERENCE->width())) {
28       return decode_Template0_opt(pArithDecoder, grContext);
29     }
30     return decode_Template0_unopt(pArithDecoder, grContext);
31   }
32 
33   if ((GRREFERENCEDX == 0) && (GRW == (uint32_t)GRREFERENCE->width()))
34     return decode_Template1_opt(pArithDecoder, grContext);
35 
36   return decode_Template1_unopt(pArithDecoder, grContext);
37 }
38 
decode_Template0_unopt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * grContext)39 std::unique_ptr<CJBig2_Image> CJBig2_GRRDProc::decode_Template0_unopt(
40     CJBig2_ArithDecoder* pArithDecoder,
41     JBig2ArithCtx* grContext) {
42   int LTP = 0;
43   auto GRREG = pdfium::MakeUnique<CJBig2_Image>(GRW, GRH);
44   GRREG->fill(0);
45   for (uint32_t h = 0; h < GRH; h++) {
46     if (TPGRON) {
47       if (pArithDecoder->IsComplete())
48         return nullptr;
49 
50       LTP = LTP ^ pArithDecoder->DECODE(&grContext[0x0010]);
51     }
52     uint32_t lines[5];
53     lines[0] = GRREG->getPixel(1, h - 1);
54     lines[0] |= GRREG->getPixel(0, h - 1) << 1;
55     lines[1] = 0;
56     lines[2] = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY - 1);
57     lines[2] |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1)
58                 << 1;
59     lines[3] = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY);
60     lines[3] |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1;
61     lines[3] |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY)
62                 << 2;
63     lines[4] = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1);
64     lines[4] |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1)
65                 << 1;
66     lines[4] |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY + 1)
67                 << 2;
68     if (!LTP) {
69       for (uint32_t w = 0; w < GRW; w++) {
70         uint32_t CONTEXT =
71             decode_Template0_unopt_CalculateContext(*GRREG, lines, w, h);
72         if (pArithDecoder->IsComplete())
73           return nullptr;
74 
75         int bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
76         decode_Template0_unopt_SetPixel(GRREG.get(), lines, w, h, bVal);
77       }
78     } else {
79       for (uint32_t w = 0; w < GRW; w++) {
80         int bVal = GRREFERENCE->getPixel(w, h);
81         if (!(TPGRON && (bVal == GRREFERENCE->getPixel(w - 1, h - 1)) &&
82               (bVal == GRREFERENCE->getPixel(w, h - 1)) &&
83               (bVal == GRREFERENCE->getPixel(w + 1, h - 1)) &&
84               (bVal == GRREFERENCE->getPixel(w - 1, h)) &&
85               (bVal == GRREFERENCE->getPixel(w + 1, h)) &&
86               (bVal == GRREFERENCE->getPixel(w - 1, h + 1)) &&
87               (bVal == GRREFERENCE->getPixel(w, h + 1)) &&
88               (bVal == GRREFERENCE->getPixel(w + 1, h + 1)))) {
89           uint32_t CONTEXT =
90               decode_Template0_unopt_CalculateContext(*GRREG, lines, w, h);
91           if (pArithDecoder->IsComplete())
92             return nullptr;
93 
94           bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
95         }
96         decode_Template0_unopt_SetPixel(GRREG.get(), lines, w, h, bVal);
97       }
98     }
99   }
100   return GRREG;
101 }
102 
decode_Template0_unopt_CalculateContext(const CJBig2_Image & GRREG,const uint32_t * lines,uint32_t w,uint32_t h) const103 uint32_t CJBig2_GRRDProc::decode_Template0_unopt_CalculateContext(
104     const CJBig2_Image& GRREG,
105     const uint32_t* lines,
106     uint32_t w,
107     uint32_t h) const {
108   uint32_t CONTEXT = lines[4];
109   CONTEXT |= lines[3] << 3;
110   CONTEXT |= lines[2] << 6;
111   CONTEXT |= GRREFERENCE->getPixel(w - GRREFERENCEDX + GRAT[2],
112                                    h - GRREFERENCEDY + GRAT[3])
113              << 8;
114   CONTEXT |= lines[1] << 9;
115   CONTEXT |= lines[0] << 10;
116   CONTEXT |= GRREG.getPixel(w + GRAT[0], h + GRAT[1]) << 12;
117   return CONTEXT;
118 }
119 
decode_Template0_unopt_SetPixel(CJBig2_Image * GRREG,uint32_t * lines,uint32_t w,uint32_t h,int bVal)120 void CJBig2_GRRDProc::decode_Template0_unopt_SetPixel(CJBig2_Image* GRREG,
121                                                       uint32_t* lines,
122                                                       uint32_t w,
123                                                       uint32_t h,
124                                                       int bVal) {
125   GRREG->setPixel(w, h, bVal);
126   lines[0] = ((lines[0] << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x03;
127   lines[1] = ((lines[1] << 1) | bVal) & 0x01;
128   lines[2] = ((lines[2] << 1) | GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
129                                                       h - GRREFERENCEDY - 1)) &
130              0x03;
131   lines[3] = ((lines[3] << 1) |
132               GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) &
133              0x07;
134   lines[4] = ((lines[4] << 1) | GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
135                                                       h - GRREFERENCEDY + 1)) &
136              0x07;
137 }
138 
decode_Template0_opt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * grContext)139 std::unique_ptr<CJBig2_Image> CJBig2_GRRDProc::decode_Template0_opt(
140     CJBig2_ArithDecoder* pArithDecoder,
141     JBig2ArithCtx* grContext) {
142   if (!GRREFERENCE->data())
143     return nullptr;
144 
145   int32_t iGRW = static_cast<int32_t>(GRW);
146   int32_t iGRH = static_cast<int32_t>(GRH);
147   auto GRREG = pdfium::MakeUnique<CJBig2_Image>(iGRW, iGRH);
148   if (!GRREG->data())
149     return nullptr;
150 
151   int LTP = 0;
152   uint8_t* pLine = GRREG->data();
153   uint8_t* pLineR = GRREFERENCE->data();
154   intptr_t nStride = GRREG->stride();
155   intptr_t nStrideR = GRREFERENCE->stride();
156   int32_t GRWR = GRREFERENCE->width();
157   int32_t GRHR = GRREFERENCE->height();
158   if (GRREFERENCEDY < -GRHR + 1 || GRREFERENCEDY > GRHR - 1)
159     GRREFERENCEDY = 0;
160   intptr_t nOffset = -GRREFERENCEDY * nStrideR;
161   for (int32_t h = 0; h < iGRH; h++) {
162     if (TPGRON) {
163       if (pArithDecoder->IsComplete())
164         return nullptr;
165 
166       LTP = LTP ^ pArithDecoder->DECODE(&grContext[0x0010]);
167     }
168     uint32_t line1 = (h > 0) ? pLine[-nStride] << 4 : 0;
169     int32_t reference_h = h - GRREFERENCEDY;
170     bool line1_r_ok = (reference_h > 0 && reference_h < GRHR + 1);
171     bool line2_r_ok = (reference_h > -1 && reference_h < GRHR);
172     bool line3_r_ok = (reference_h > -2 && reference_h < GRHR - 1);
173     uint32_t line1_r = line1_r_ok ? pLineR[nOffset - nStrideR] : 0;
174     uint32_t line2_r = line2_r_ok ? pLineR[nOffset] : 0;
175     uint32_t line3_r = line3_r_ok ? pLineR[nOffset + nStrideR] : 0;
176     if (!LTP) {
177       uint32_t CONTEXT = (line1 & 0x1c00) | (line1_r & 0x01c0) |
178                          ((line2_r >> 3) & 0x0038) | ((line3_r >> 6) & 0x0007);
179       for (int32_t w = 0; w < iGRW; w += 8) {
180         int32_t nBits = iGRW - w > 8 ? 8 : iGRW - w;
181         if (h > 0) {
182           line1 = (line1 << 8) |
183                   (w + 8 < iGRW ? pLine[-nStride + (w >> 3) + 1] << 4 : 0);
184         }
185         if (h > GRHR + GRREFERENCEDY + 1) {
186           line1_r = 0;
187           line2_r = 0;
188           line3_r = 0;
189         } else {
190           if (line1_r_ok) {
191             line1_r =
192                 (line1_r << 8) |
193                 (w + 8 < GRWR ? pLineR[nOffset - nStrideR + (w >> 3) + 1] : 0);
194           }
195           if (line2_r_ok) {
196             line2_r = (line2_r << 8) |
197                       (w + 8 < GRWR ? pLineR[nOffset + (w >> 3) + 1] : 0);
198           }
199           if (line3_r_ok) {
200             line3_r =
201                 (line3_r << 8) |
202                 (w + 8 < GRWR ? pLineR[nOffset + nStrideR + (w >> 3) + 1] : 0);
203           } else {
204             line3_r = 0;
205           }
206         }
207         uint8_t cVal = 0;
208         for (int32_t k = 0; k < nBits; k++) {
209           if (pArithDecoder->IsComplete())
210             return nullptr;
211 
212           int bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
213           cVal |= bVal << (7 - k);
214           CONTEXT = ((CONTEXT & 0x0cdb) << 1) | (bVal << 9) |
215                     ((line1 >> (7 - k)) & 0x0400) |
216                     ((line1_r >> (7 - k)) & 0x0040) |
217                     ((line2_r >> (10 - k)) & 0x0008) |
218                     ((line3_r >> (13 - k)) & 0x0001);
219         }
220         pLine[w >> 3] = cVal;
221       }
222     } else {
223       uint32_t CONTEXT = (line1 & 0x1c00) | (line1_r & 0x01c0) |
224                          ((line2_r >> 3) & 0x0038) | ((line3_r >> 6) & 0x0007);
225       for (int32_t w = 0; w < iGRW; w += 8) {
226         int32_t nBits = iGRW - w > 8 ? 8 : iGRW - w;
227         if (h > 0) {
228           line1 = (line1 << 8) |
229                   (w + 8 < iGRW ? pLine[-nStride + (w >> 3) + 1] << 4 : 0);
230         }
231         if (line1_r_ok) {
232           line1_r =
233               (line1_r << 8) |
234               (w + 8 < GRWR ? pLineR[nOffset - nStrideR + (w >> 3) + 1] : 0);
235         }
236         if (line2_r_ok) {
237           line2_r = (line2_r << 8) |
238                     (w + 8 < GRWR ? pLineR[nOffset + (w >> 3) + 1] : 0);
239         }
240         if (line3_r_ok) {
241           line3_r =
242               (line3_r << 8) |
243               (w + 8 < GRWR ? pLineR[nOffset + nStrideR + (w >> 3) + 1] : 0);
244         } else {
245           line3_r = 0;
246         }
247         uint8_t cVal = 0;
248         for (int32_t k = 0; k < nBits; k++) {
249           int bVal = GRREFERENCE->getPixel(w + k, h);
250           if (!(TPGRON && (bVal == GRREFERENCE->getPixel(w + k - 1, h - 1)) &&
251                 (bVal == GRREFERENCE->getPixel(w + k, h - 1)) &&
252                 (bVal == GRREFERENCE->getPixel(w + k + 1, h - 1)) &&
253                 (bVal == GRREFERENCE->getPixel(w + k - 1, h)) &&
254                 (bVal == GRREFERENCE->getPixel(w + k + 1, h)) &&
255                 (bVal == GRREFERENCE->getPixel(w + k - 1, h + 1)) &&
256                 (bVal == GRREFERENCE->getPixel(w + k, h + 1)) &&
257                 (bVal == GRREFERENCE->getPixel(w + k + 1, h + 1)))) {
258             if (pArithDecoder->IsComplete())
259               return nullptr;
260 
261             bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
262           }
263           cVal |= bVal << (7 - k);
264           CONTEXT = ((CONTEXT & 0x0cdb) << 1) | (bVal << 9) |
265                     ((line1 >> (7 - k)) & 0x0400) |
266                     ((line1_r >> (7 - k)) & 0x0040) |
267                     ((line2_r >> (10 - k)) & 0x0008) |
268                     ((line3_r >> (13 - k)) & 0x0001);
269         }
270         pLine[w >> 3] = cVal;
271       }
272     }
273     pLine += nStride;
274     if (h < GRHR + GRREFERENCEDY)
275       pLineR += nStrideR;
276   }
277   return GRREG;
278 }
279 
decode_Template1_unopt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * grContext)280 std::unique_ptr<CJBig2_Image> CJBig2_GRRDProc::decode_Template1_unopt(
281     CJBig2_ArithDecoder* pArithDecoder,
282     JBig2ArithCtx* grContext) {
283   int LTP = 0;
284   auto GRREG = pdfium::MakeUnique<CJBig2_Image>(GRW, GRH);
285   GRREG->fill(0);
286   for (uint32_t h = 0; h < GRH; h++) {
287     if (TPGRON) {
288       if (pArithDecoder->IsComplete())
289         return nullptr;
290 
291       LTP = LTP ^ pArithDecoder->DECODE(&grContext[0x0008]);
292     }
293     if (!LTP) {
294       uint32_t line1 = GRREG->getPixel(1, h - 1);
295       line1 |= GRREG->getPixel(0, h - 1) << 1;
296       line1 |= GRREG->getPixel(-1, h - 1) << 2;
297       uint32_t line2 = 0;
298       uint32_t line3 =
299           GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1);
300       uint32_t line4 =
301           GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY);
302       line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1;
303       line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY)
304                << 2;
305       uint32_t line5 =
306           GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1);
307       line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1)
308                << 1;
309       for (uint32_t w = 0; w < GRW; w++) {
310         uint32_t CONTEXT = line5;
311         CONTEXT |= line4 << 2;
312         CONTEXT |= line3 << 5;
313         CONTEXT |= line2 << 6;
314         CONTEXT |= line1 << 7;
315         if (pArithDecoder->IsComplete())
316           return nullptr;
317 
318         int bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
319         GRREG->setPixel(w, h, bVal);
320         line1 = ((line1 << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x07;
321         line2 = ((line2 << 1) | bVal) & 0x01;
322         line3 = ((line3 << 1) |
323                  GRREFERENCE->getPixel(w - GRREFERENCEDX + 1,
324                                        h - GRREFERENCEDY - 1)) &
325                 0x01;
326         line4 =
327             ((line4 << 1) |
328              GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) &
329             0x07;
330         line5 = ((line5 << 1) |
331                  GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
332                                        h - GRREFERENCEDY + 1)) &
333                 0x03;
334       }
335     } else {
336       uint32_t line1 = GRREG->getPixel(1, h - 1);
337       line1 |= GRREG->getPixel(0, h - 1) << 1;
338       line1 |= GRREG->getPixel(-1, h - 1) << 2;
339       uint32_t line2 = 0;
340       uint32_t line3 =
341           GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1);
342       uint32_t line4 =
343           GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY);
344       line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1;
345       line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY)
346                << 2;
347       uint32_t line5 =
348           GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1);
349       line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1)
350                << 1;
351       for (uint32_t w = 0; w < GRW; w++) {
352         int bVal = GRREFERENCE->getPixel(w, h);
353         if (!(TPGRON && (bVal == GRREFERENCE->getPixel(w - 1, h - 1)) &&
354               (bVal == GRREFERENCE->getPixel(w, h - 1)) &&
355               (bVal == GRREFERENCE->getPixel(w + 1, h - 1)) &&
356               (bVal == GRREFERENCE->getPixel(w - 1, h)) &&
357               (bVal == GRREFERENCE->getPixel(w + 1, h)) &&
358               (bVal == GRREFERENCE->getPixel(w - 1, h + 1)) &&
359               (bVal == GRREFERENCE->getPixel(w, h + 1)) &&
360               (bVal == GRREFERENCE->getPixel(w + 1, h + 1)))) {
361           uint32_t CONTEXT = line5;
362           CONTEXT |= line4 << 2;
363           CONTEXT |= line3 << 5;
364           CONTEXT |= line2 << 6;
365           CONTEXT |= line1 << 7;
366           if (pArithDecoder->IsComplete())
367             return nullptr;
368 
369           bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
370         }
371         GRREG->setPixel(w, h, bVal);
372         line1 = ((line1 << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x07;
373         line2 = ((line2 << 1) | bVal) & 0x01;
374         line3 = ((line3 << 1) |
375                  GRREFERENCE->getPixel(w - GRREFERENCEDX + 1,
376                                        h - GRREFERENCEDY - 1)) &
377                 0x01;
378         line4 =
379             ((line4 << 1) |
380              GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) &
381             0x07;
382         line5 = ((line5 << 1) |
383                  GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
384                                        h - GRREFERENCEDY + 1)) &
385                 0x03;
386       }
387     }
388   }
389   return GRREG;
390 }
391 
decode_Template1_opt(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * grContext)392 std::unique_ptr<CJBig2_Image> CJBig2_GRRDProc::decode_Template1_opt(
393     CJBig2_ArithDecoder* pArithDecoder,
394     JBig2ArithCtx* grContext) {
395   if (!GRREFERENCE->data())
396     return nullptr;
397 
398   int32_t iGRW = static_cast<int32_t>(GRW);
399   int32_t iGRH = static_cast<int32_t>(GRH);
400   auto GRREG = pdfium::MakeUnique<CJBig2_Image>(iGRW, iGRH);
401   if (!GRREG->data())
402     return nullptr;
403 
404   int LTP = 0;
405   uint8_t* pLine = GRREG->data();
406   uint8_t* pLineR = GRREFERENCE->data();
407   intptr_t nStride = GRREG->stride();
408   intptr_t nStrideR = GRREFERENCE->stride();
409   int32_t GRWR = GRREFERENCE->width();
410   int32_t GRHR = GRREFERENCE->height();
411   if (GRREFERENCEDY < -GRHR + 1 || GRREFERENCEDY > GRHR - 1) {
412     GRREFERENCEDY = 0;
413   }
414   intptr_t nOffset = -GRREFERENCEDY * nStrideR;
415   for (int32_t h = 0; h < iGRH; h++) {
416     if (TPGRON) {
417       if (pArithDecoder->IsComplete())
418         return nullptr;
419 
420       LTP = LTP ^ pArithDecoder->DECODE(&grContext[0x0008]);
421     }
422     uint32_t line1 = (h > 0) ? pLine[-nStride] << 1 : 0;
423     int32_t reference_h = h - GRREFERENCEDY;
424     bool line1_r_ok = (reference_h > 0 && reference_h < GRHR + 1);
425     bool line2_r_ok = (reference_h > -1 && reference_h < GRHR);
426     bool line3_r_ok = (reference_h > -2 && reference_h < GRHR - 1);
427     uint32_t line1_r = line1_r_ok ? pLineR[nOffset - nStrideR] : 0;
428     uint32_t line2_r = line2_r_ok ? pLineR[nOffset] : 0;
429     uint32_t line3_r = line3_r_ok ? pLineR[nOffset + nStrideR] : 0;
430     if (!LTP) {
431       uint32_t CONTEXT = (line1 & 0x0380) | ((line1_r >> 2) & 0x0020) |
432                          ((line2_r >> 4) & 0x001c) | ((line3_r >> 6) & 0x0003);
433       for (int32_t w = 0; w < iGRW; w += 8) {
434         int32_t nBits = iGRW - w > 8 ? 8 : iGRW - w;
435         if (h > 0)
436           line1 = (line1 << 8) |
437                   (w + 8 < iGRW ? pLine[-nStride + (w >> 3) + 1] << 1 : 0);
438         if (line1_r_ok)
439           line1_r =
440               (line1_r << 8) |
441               (w + 8 < GRWR ? pLineR[nOffset - nStrideR + (w >> 3) + 1] : 0);
442         if (line2_r_ok)
443           line2_r = (line2_r << 8) |
444                     (w + 8 < GRWR ? pLineR[nOffset + (w >> 3) + 1] : 0);
445         if (line3_r_ok) {
446           line3_r =
447               (line3_r << 8) |
448               (w + 8 < GRWR ? pLineR[nOffset + nStrideR + (w >> 3) + 1] : 0);
449         } else {
450           line3_r = 0;
451         }
452         uint8_t cVal = 0;
453         for (int32_t k = 0; k < nBits; k++) {
454           int bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
455           cVal |= bVal << (7 - k);
456           CONTEXT = ((CONTEXT & 0x018d) << 1) | (bVal << 6) |
457                     ((line1 >> (7 - k)) & 0x0080) |
458                     ((line1_r >> (9 - k)) & 0x0020) |
459                     ((line2_r >> (11 - k)) & 0x0004) |
460                     ((line3_r >> (13 - k)) & 0x0001);
461         }
462         pLine[w >> 3] = cVal;
463       }
464     } else {
465       uint32_t CONTEXT = (line1 & 0x0380) | ((line1_r >> 2) & 0x0020) |
466                          ((line2_r >> 4) & 0x001c) | ((line3_r >> 6) & 0x0003);
467       for (int32_t w = 0; w < iGRW; w += 8) {
468         int32_t nBits = iGRW - w > 8 ? 8 : iGRW - w;
469         if (h > 0)
470           line1 = (line1 << 8) |
471                   (w + 8 < iGRW ? pLine[-nStride + (w >> 3) + 1] << 1 : 0);
472         if (line1_r_ok)
473           line1_r =
474               (line1_r << 8) |
475               (w + 8 < GRWR ? pLineR[nOffset - nStrideR + (w >> 3) + 1] : 0);
476         if (line2_r_ok)
477           line2_r = (line2_r << 8) |
478                     (w + 8 < GRWR ? pLineR[nOffset + (w >> 3) + 1] : 0);
479         if (line3_r_ok) {
480           line3_r =
481               (line3_r << 8) |
482               (w + 8 < GRWR ? pLineR[nOffset + nStrideR + (w >> 3) + 1] : 0);
483         } else {
484           line3_r = 0;
485         }
486         uint8_t cVal = 0;
487         for (int32_t k = 0; k < nBits; k++) {
488           int bVal = GRREFERENCE->getPixel(w + k, h);
489           if (!(TPGRON && (bVal == GRREFERENCE->getPixel(w + k - 1, h - 1)) &&
490                 (bVal == GRREFERENCE->getPixel(w + k, h - 1)) &&
491                 (bVal == GRREFERENCE->getPixel(w + k + 1, h - 1)) &&
492                 (bVal == GRREFERENCE->getPixel(w + k - 1, h)) &&
493                 (bVal == GRREFERENCE->getPixel(w + k + 1, h)) &&
494                 (bVal == GRREFERENCE->getPixel(w + k - 1, h + 1)) &&
495                 (bVal == GRREFERENCE->getPixel(w + k, h + 1)) &&
496                 (bVal == GRREFERENCE->getPixel(w + k + 1, h + 1)))) {
497             if (pArithDecoder->IsComplete())
498               return nullptr;
499 
500             bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
501           }
502           cVal |= bVal << (7 - k);
503           CONTEXT = ((CONTEXT & 0x018d) << 1) | (bVal << 6) |
504                     ((line1 >> (7 - k)) & 0x0080) |
505                     ((line1_r >> (9 - k)) & 0x0020) |
506                     ((line2_r >> (11 - k)) & 0x0004) |
507                     ((line3_r >> (13 - k)) & 0x0001);
508         }
509         pLine[w >> 3] = cVal;
510       }
511     }
512     pLine += nStride;
513     if (h < GRHR + GRREFERENCEDY)
514       pLineR += nStrideR;
515   }
516   return GRREG;
517 }
518