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