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 16std::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 39std::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 103uint32_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 120void 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 139std::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 280std::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 392std::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