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