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