1 // Copyright 2014 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 "../../../include/fxcodec/fx_codec.h" 8 #include "codec_int.h" 9 extern const FX_BYTE OneLeadPos[256]; 10 extern const FX_BYTE ZeroLeadPos[256]; 11 int _FindBit(const FX_BYTE* data_buf, int max_pos, int start_pos, int bit) 12 { 13 if (start_pos >= max_pos) { 14 return max_pos; 15 } 16 FX_LPCBYTE leading_pos = bit ? OneLeadPos : ZeroLeadPos; 17 if (start_pos % 8) { 18 FX_BYTE data = data_buf[start_pos / 8]; 19 if (bit) { 20 data &= 0xff >> (start_pos % 8); 21 } else { 22 data |= 0xff << (8 - start_pos % 8); 23 } 24 if (leading_pos[data] < 8) { 25 return start_pos / 8 * 8 + leading_pos[data]; 26 } 27 start_pos += 7; 28 } 29 FX_BYTE skip = bit ? 0x00 : 0xff; 30 int byte_pos = start_pos / 8; 31 int max_byte = (max_pos + 7) / 8; 32 while (byte_pos < max_byte) { 33 if (data_buf[byte_pos] != skip) { 34 break; 35 } 36 byte_pos ++; 37 } 38 if (byte_pos == max_byte) { 39 return max_pos; 40 } 41 int pos = leading_pos[data_buf[byte_pos]] + byte_pos * 8; 42 if (pos > max_pos) { 43 pos = max_pos; 44 } 45 return pos; 46 } 47 void _FaxG4FindB1B2(const FX_BYTE* ref_buf, int columns, int a0, FX_BOOL a0color, int& b1, int& b2) 48 { 49 if (a0color) { 50 a0color = 1; 51 } 52 FX_BYTE first_bit = (a0 < 0) ? 1 : ((ref_buf[a0 / 8] & (1 << (7 - a0 % 8))) != 0); 53 b1 = _FindBit(ref_buf, columns, a0 + 1, !first_bit); 54 if (b1 >= columns) { 55 b1 = b2 = columns; 56 return; 57 } 58 if (first_bit == !a0color) { 59 b1 = _FindBit(ref_buf, columns, b1 + 1, first_bit); 60 first_bit = !first_bit; 61 } 62 if (b1 >= columns) { 63 b1 = b2 = columns; 64 return; 65 } 66 b2 = _FindBit(ref_buf, columns, b1 + 1, first_bit); 67 } 68 void _FaxFillBits(FX_LPBYTE dest_buf, int columns, int startpos, int endpos) 69 { 70 if (startpos < 0) { 71 startpos = 0; 72 } 73 if (endpos < 0) { 74 endpos = 0; 75 } 76 if (endpos >= columns) { 77 endpos = columns; 78 } 79 if (startpos >= endpos) { 80 return; 81 } 82 int first_byte = startpos / 8; 83 int last_byte = (endpos - 1) / 8; 84 if (first_byte == last_byte) { 85 for (int i = startpos % 8; i <= (endpos - 1) % 8; i ++) { 86 dest_buf[first_byte] -= 1 << (7 - i); 87 } 88 return; 89 } 90 int i; 91 for (i = startpos % 8; i < 8; i ++) { 92 dest_buf[first_byte] -= 1 << (7 - i); 93 } 94 for (i = 0; i <= (endpos - 1) % 8; i ++) { 95 dest_buf[last_byte] -= 1 << (7 - i); 96 } 97 if (last_byte > first_byte + 1) { 98 FXSYS_memset32(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1); 99 } 100 } 101 #define NEXTBIT src_buf[bitpos/8] & (1 << (7-bitpos%8)); bitpos ++; 102 #define ADDBIT(code, bit) code = code << 1; if (bit) code ++; 103 #define GETBIT(bitpos) src_buf[bitpos/8] & (1 << (7-bitpos%8)) 104 static const FX_BYTE FaxBlackRunIns[] = { 105 0, 106 2, 107 0x02, 3, 0, 108 0x03, 2, 0, 109 2, 110 0x02, 1, 0, 111 0x03, 4, 0, 112 2, 113 0x02, 6, 0, 114 0x03, 5, 0, 115 1, 116 0x03, 7, 0, 117 2, 118 0x04, 9, 0, 119 0x05, 8, 0, 120 3, 121 0x04, 10, 0, 122 0x05, 11, 0, 123 0x07, 12, 0, 124 2, 125 0x04, 13, 0, 126 0x07, 14, 0, 127 1, 128 0x18, 15, 0, 129 5, 130 0x08, 18, 0, 131 0x0f, 64, 0, 132 0x17, 16, 0, 133 0x18, 17, 0, 134 0x37, 0, 0, 135 10, 136 0x08, 0x00, 0x07, 137 0x0c, 0x40, 0x07, 138 0x0d, 0x80, 0x07, 139 0x17, 24, 0, 140 0x18, 25, 0, 141 0x28, 23, 0, 142 0x37, 22, 0, 143 0x67, 19, 0, 144 0x68, 20, 0, 145 0x6c, 21, 0, 146 54, 147 0x12, 1984 % 256, 1984 / 256, 148 0x13, 2048 % 256, 2048 / 256, 149 0x14, 2112 % 256, 2112 / 256, 150 0x15, 2176 % 256, 2176 / 256, 151 0x16, 2240 % 256, 2240 / 256, 152 0x17, 2304 % 256, 2304 / 256, 153 0x1c, 2368 % 256, 2368 / 256, 154 0x1d, 2432 % 256, 2432 / 256, 155 0x1e, 2496 % 256, 2496 / 256, 156 0x1f, 2560 % 256, 2560 / 256, 157 0x24, 52, 0, 158 0x27, 55, 0, 159 0x28, 56, 0, 160 0x2b, 59, 0, 161 0x2c, 60, 0, 162 0x33, 320 % 256, 320 / 256, 163 0x34, 384 % 256, 384 / 256, 164 0x35, 448 % 256, 448 / 256, 165 0x37, 53, 0, 166 0x38, 54, 0, 167 0x52, 50, 0, 168 0x53, 51, 0, 169 0x54, 44, 0, 170 0x55, 45, 0, 171 0x56, 46, 0, 172 0x57, 47, 0, 173 0x58, 57, 0, 174 0x59, 58, 0, 175 0x5a, 61, 0, 176 0x5b, 256 % 256, 256 / 256, 177 0x64, 48, 0, 178 0x65, 49, 0, 179 0x66, 62, 0, 180 0x67, 63, 0, 181 0x68, 30, 0, 182 0x69, 31, 0, 183 0x6a, 32, 0, 184 0x6b, 33, 0, 185 0x6c, 40, 0, 186 0x6d, 41, 0, 187 0xc8, 128, 0, 188 0xc9, 192, 0, 189 0xca, 26, 0, 190 0xcb, 27, 0, 191 0xcc, 28, 0, 192 0xcd, 29, 0, 193 0xd2, 34, 0, 194 0xd3, 35, 0, 195 0xd4, 36, 0, 196 0xd5, 37, 0, 197 0xd6, 38, 0, 198 0xd7, 39, 0, 199 0xda, 42, 0, 200 0xdb, 43, 0, 201 20, 202 0x4a, 640 % 256, 640 / 256, 203 0x4b, 704 % 256, 704 / 256, 204 0x4c, 768 % 256, 768 / 256, 205 0x4d, 832 % 256, 832 / 256, 206 0x52, 1280 % 256, 1280 / 256, 207 0x53, 1344 % 256, 1344 / 256, 208 0x54, 1408 % 256, 1408 / 256, 209 0x55, 1472 % 256, 1472 / 256, 210 0x5a, 1536 % 256, 1536 / 256, 211 0x5b, 1600 % 256, 1600 / 256, 212 0x64, 1664 % 256, 1664 / 256, 213 0x65, 1728 % 256, 1728 / 256, 214 0x6c, 512 % 256, 512 / 256, 215 0x6d, 576 % 256, 576 / 256, 216 0x72, 896 % 256, 896 / 256, 217 0x73, 960 % 256, 960 / 256, 218 0x74, 1024 % 256, 1024 / 256, 219 0x75, 1088 % 256, 1088 / 256, 220 0x76, 1152 % 256, 1152 / 256, 221 0x77, 1216 % 256, 1216 / 256, 222 0xff 223 }; 224 static const FX_BYTE FaxWhiteRunIns[] = { 225 0, 226 0, 227 0, 228 6, 229 0x07, 2, 0, 230 0x08, 3, 0, 231 0x0B, 4, 0, 232 0x0C, 5, 0, 233 0x0E, 6, 0, 234 0x0F, 7, 0, 235 6, 236 0x07, 10, 0, 237 0x08, 11, 0, 238 0x12, 128, 0, 239 0x13, 8, 0, 240 0x14, 9, 0, 241 0x1b, 64, 0, 242 9, 243 0x03, 13, 0, 244 0x07, 1, 0, 245 0x08, 12, 0, 246 0x17, 192, 0, 247 0x18, 1664 % 256, 1664 / 256, 248 0x2a, 16, 0, 249 0x2B, 17, 0, 250 0x34, 14, 0, 251 0x35, 15, 0, 252 12, 253 0x03, 22, 0, 254 0x04, 23, 0, 255 0x08, 20, 0, 256 0x0c, 19, 0, 257 0x13, 26, 0, 258 0x17, 21, 0, 259 0x18, 28, 0, 260 0x24, 27, 0, 261 0x27, 18, 0, 262 0x28, 24, 0, 263 0x2B, 25, 0, 264 0x37, 256 % 256, 256 / 256, 265 42, 266 0x02, 29, 0, 267 0x03, 30, 0, 268 0x04, 45, 0, 269 0x05, 46, 0, 270 0x0a, 47, 0, 271 0x0b, 48, 0, 272 0x12, 33, 0, 273 0x13, 34, 0, 274 0x14, 35, 0, 275 0x15, 36, 0, 276 0x16, 37, 0, 277 0x17, 38, 0, 278 0x1a, 31, 0, 279 0x1b, 32, 0, 280 0x24, 53, 0, 281 0x25, 54, 0, 282 0x28, 39, 0, 283 0x29, 40, 0, 284 0x2a, 41, 0, 285 0x2b, 42, 0, 286 0x2c, 43, 0, 287 0x2d, 44, 0, 288 0x32, 61, 0, 289 0x33, 62, 0, 290 0x34, 63, 0, 291 0x35, 0, 0, 292 0x36, 320 % 256, 320 / 256, 293 0x37, 384 % 256, 384 / 256, 294 0x4a, 59, 0, 295 0x4b, 60, 0, 296 0x52, 49, 0, 297 0x53, 50, 0, 298 0x54, 51, 0, 299 0x55, 52, 0, 300 0x58, 55, 0, 301 0x59, 56, 0, 302 0x5a, 57, 0, 303 0x5b, 58, 0, 304 0x64, 448 % 256, 448 / 256, 305 0x65, 512 % 256, 512 / 256, 306 0x67, 640 % 256, 640 / 256, 307 0x68, 576 % 256, 576 / 256, 308 16, 309 0x98, 1472 % 256, 1472 / 256, 310 0x99, 1536 % 256, 1536 / 256, 311 0x9a, 1600 % 256, 1600 / 256, 312 0x9b, 1728 % 256, 1728 / 256, 313 0xcc, 704 % 256, 704 / 256, 314 0xcd, 768 % 256, 768 / 256, 315 0xd2, 832 % 256, 832 / 256, 316 0xd3, 896 % 256, 896 / 256, 317 0xd4, 960 % 256, 960 / 256, 318 0xd5, 1024 % 256, 1024 / 256, 319 0xd6, 1088 % 256, 1088 / 256, 320 0xd7, 1152 % 256, 1152 / 256, 321 0xd8, 1216 % 256, 1216 / 256, 322 0xd9, 1280 % 256, 1280 / 256, 323 0xda, 1344 % 256, 1344 / 256, 324 0xdb, 1408 % 256, 1408 / 256, 325 0, 326 3, 327 0x08, 1792 % 256, 1792 / 256, 328 0x0c, 1856 % 256, 1856 / 256, 329 0x0d, 1920 % 256, 1920 / 256, 330 10, 331 0x12, 1984 % 256, 1984 / 256, 332 0x13, 2048 % 256, 2048 / 256, 333 0x14, 2112 % 256, 2112 / 256, 334 0x15, 2176 % 256, 2176 / 256, 335 0x16, 2240 % 256, 2240 / 256, 336 0x17, 2304 % 256, 2304 / 256, 337 0x1c, 2368 % 256, 2368 / 256, 338 0x1d, 2432 % 256, 2432 / 256, 339 0x1e, 2496 % 256, 2496 / 256, 340 0x1f, 2560 % 256, 2560 / 256, 341 0xff, 342 }; 343 int _FaxGetRun(FX_LPCBYTE ins_array, const FX_BYTE* src_buf, int& bitpos, int bitsize) 344 { 345 FX_DWORD code = 0; 346 int ins_off = 0; 347 while (1) { 348 FX_BYTE ins = ins_array[ins_off++]; 349 if (ins == 0xff) { 350 return -1; 351 } 352 if (bitpos >= bitsize) { 353 return -1; 354 } 355 code <<= 1; 356 if (src_buf[bitpos / 8] & (1 << (7 - bitpos % 8))) { 357 code ++; 358 } 359 bitpos ++; 360 int next_off = ins_off + ins * 3; 361 for (; ins_off < next_off; ins_off += 3) { 362 if (ins_array[ins_off] == code) { 363 return ins_array[ins_off + 1] + ins_array[ins_off + 2] * 256; 364 } 365 } 366 } 367 } 368 FX_BOOL _FaxG4GetRow(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, const FX_BYTE* ref_buf, int columns) 369 { 370 int a0 = -1, a0color = 1; 371 while (1) { 372 if (bitpos >= bitsize) { 373 return FALSE; 374 } 375 int a1, a2, b1, b2; 376 _FaxG4FindB1B2(ref_buf, columns, a0, a0color, b1, b2); 377 FX_BOOL bit = NEXTBIT; 378 int v_delta = 0; 379 if (bit) { 380 } else { 381 if (bitpos >= bitsize) { 382 return FALSE; 383 } 384 FX_BOOL bit1 = NEXTBIT; 385 if (bitpos >= bitsize) { 386 return FALSE; 387 } 388 FX_BOOL bit2 = NEXTBIT; 389 if (bit1 && bit2) { 390 v_delta = 1; 391 } else if (bit1) { 392 v_delta = -1; 393 } else if (bit2) { 394 int run_len1 = 0; 395 while (1) { 396 int run = _FaxGetRun(a0color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf, bitpos, bitsize); 397 run_len1 += run; 398 if (run < 64) { 399 break; 400 } 401 } 402 if (a0 < 0) { 403 run_len1 ++; 404 } 405 a1 = a0 + run_len1; 406 if (!a0color) { 407 _FaxFillBits(dest_buf, columns, a0, a1); 408 } 409 int run_len2 = 0; 410 while (1) { 411 int run = _FaxGetRun(a0color ? FaxBlackRunIns : FaxWhiteRunIns, src_buf, bitpos, bitsize); 412 run_len2 += run; 413 if (run < 64) { 414 break; 415 } 416 } 417 a2 = a1 + run_len2; 418 if (a0color) { 419 _FaxFillBits(dest_buf, columns, a1, a2); 420 } 421 a0 = a2; 422 if (a0 < columns) { 423 continue; 424 } 425 return TRUE; 426 } else { 427 if (bitpos >= bitsize) { 428 return FALSE; 429 } 430 bit = NEXTBIT; 431 if (bit) { 432 if (!a0color) { 433 _FaxFillBits(dest_buf, columns, a0, b2); 434 } 435 if (b2 >= columns) { 436 return TRUE; 437 } 438 a0 = b2; 439 continue; 440 } else { 441 if (bitpos >= bitsize) { 442 return FALSE; 443 } 444 FX_BOOL bit1 = NEXTBIT; 445 if (bitpos >= bitsize) { 446 return FALSE; 447 } 448 FX_BOOL bit2 = NEXTBIT; 449 if (bit1 && bit2) { 450 v_delta = 2; 451 } else if (bit1) { 452 v_delta = -2; 453 } else if (bit2) { 454 if (bitpos >= bitsize) { 455 return FALSE; 456 } 457 bit = NEXTBIT; 458 if (bit) { 459 v_delta = 3; 460 } else { 461 v_delta = -3; 462 } 463 } else { 464 if (bitpos >= bitsize) { 465 return FALSE; 466 } 467 bit = NEXTBIT; 468 if (bit) { 469 bitpos += 3; 470 continue; 471 } else { 472 bitpos += 5; 473 return TRUE; 474 } 475 } 476 } 477 } 478 } 479 a1 = b1 + v_delta; 480 if (!a0color) { 481 _FaxFillBits(dest_buf, columns, a0, a1); 482 } 483 if (a1 >= columns) { 484 return TRUE; 485 } 486 a0 = a1; 487 a0color = !a0color; 488 } 489 } 490 FX_BOOL _FaxSkipEOL(const FX_BYTE* src_buf, int bitsize, int& bitpos) 491 { 492 int startbit = bitpos; 493 while (bitpos < bitsize) { 494 int bit = NEXTBIT; 495 if (bit) { 496 if (bitpos - startbit <= 11) { 497 bitpos = startbit; 498 } 499 return TRUE; 500 } 501 } 502 return FALSE; 503 } 504 FX_BOOL _FaxGet1DLine(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, int columns) 505 { 506 int color = TRUE; 507 int startpos = 0; 508 while (1) { 509 if (bitpos >= bitsize) { 510 return FALSE; 511 } 512 int run_len = 0; 513 while (1) { 514 int run = _FaxGetRun(color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf, bitpos, bitsize); 515 if (run < 0) { 516 while (bitpos < bitsize) { 517 int bit = NEXTBIT; 518 if (bit) { 519 return TRUE; 520 } 521 } 522 return FALSE; 523 } 524 run_len += run; 525 if (run < 64) { 526 break; 527 } 528 } 529 if (!color) { 530 _FaxFillBits(dest_buf, columns, startpos, startpos + run_len); 531 } 532 startpos += run_len; 533 if (startpos >= columns) { 534 break; 535 } 536 color = !color; 537 } 538 return TRUE; 539 } 540 class CCodec_FaxDecoder : public CCodec_ScanlineDecoder 541 { 542 public: 543 CCodec_FaxDecoder(); 544 virtual ~CCodec_FaxDecoder(); 545 FX_BOOL Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, 546 int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows); 547 virtual void v_DownScale(int dest_width, int dest_height) {} 548 virtual FX_BOOL v_Rewind(); 549 virtual FX_LPBYTE v_GetNextLine(); 550 virtual FX_DWORD GetSrcOffset(); 551 int m_Encoding, m_bEndOfLine, m_bByteAlign, m_bBlack; 552 int bitpos; 553 FX_LPCBYTE m_pSrcBuf; 554 FX_DWORD m_SrcSize; 555 FX_LPBYTE m_pScanlineBuf, m_pRefBuf; 556 }; 557 CCodec_FaxDecoder::CCodec_FaxDecoder() 558 { 559 m_pScanlineBuf = NULL; 560 m_pRefBuf = NULL; 561 } 562 CCodec_FaxDecoder::~CCodec_FaxDecoder() 563 { 564 if (m_pScanlineBuf) { 565 FX_Free(m_pScanlineBuf); 566 } 567 if (m_pRefBuf) { 568 FX_Free(m_pRefBuf); 569 } 570 } 571 FX_BOOL CCodec_FaxDecoder::Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, 572 int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows) 573 { 574 m_Encoding = K; 575 m_bEndOfLine = EndOfLine; 576 m_bByteAlign = EncodedByteAlign; 577 m_bBlack = BlackIs1; 578 m_OrigWidth = Columns; 579 m_OrigHeight = Rows; 580 if (m_OrigWidth == 0) { 581 m_OrigWidth = width; 582 } 583 if (m_OrigHeight == 0) { 584 m_OrigHeight = height; 585 } 586 m_Pitch = (m_OrigWidth + 31) / 32 * 4; 587 m_OutputWidth = m_OrigWidth; 588 m_OutputHeight = m_OrigHeight; 589 m_pScanlineBuf = FX_Alloc(FX_BYTE, m_Pitch); 590 if (m_pScanlineBuf == NULL) { 591 return FALSE; 592 } 593 m_pRefBuf = FX_Alloc(FX_BYTE, m_Pitch); 594 if (m_pRefBuf == NULL) { 595 return FALSE; 596 } 597 m_pSrcBuf = src_buf; 598 m_SrcSize = src_size; 599 m_nComps = 1; 600 m_bpc = 1; 601 m_bColorTransformed = FALSE; 602 return TRUE; 603 } 604 FX_BOOL CCodec_FaxDecoder::v_Rewind() 605 { 606 FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch); 607 bitpos = 0; 608 return TRUE; 609 } 610 FX_LPBYTE CCodec_FaxDecoder::v_GetNextLine() 611 { 612 int bitsize = m_SrcSize * 8; 613 _FaxSkipEOL(m_pSrcBuf, bitsize, bitpos); 614 if (bitpos >= bitsize) { 615 return NULL; 616 } 617 FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch); 618 if (m_Encoding < 0) { 619 _FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_OrigWidth); 620 FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch); 621 } else if (m_Encoding == 0) { 622 _FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth); 623 } else { 624 FX_BOOL bNext1D = m_pSrcBuf[bitpos / 8] & (1 << (7 - bitpos % 8)); 625 bitpos ++; 626 if (bNext1D) { 627 _FaxGet1DLine(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_OrigWidth); 628 } else { 629 _FaxG4GetRow(m_pSrcBuf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_OrigWidth); 630 } 631 FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch); 632 } 633 if (m_bEndOfLine) { 634 _FaxSkipEOL(m_pSrcBuf, bitsize, bitpos); 635 } 636 if (m_bByteAlign && bitpos < bitsize) { 637 int bitpos0 = bitpos; 638 int bitpos1 = (bitpos + 7) / 8 * 8; 639 while (m_bByteAlign && bitpos0 < bitpos1) { 640 int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8)); 641 if (bit != 0) { 642 m_bByteAlign = FALSE; 643 } else { 644 bitpos0 ++; 645 } 646 } 647 if (m_bByteAlign) { 648 bitpos = bitpos1; 649 } 650 } 651 if (m_bBlack) { 652 for (int i = 0; i < m_Pitch; i ++) { 653 m_pScanlineBuf[i] = ~m_pScanlineBuf[i]; 654 } 655 } 656 return m_pScanlineBuf; 657 } 658 FX_DWORD CCodec_FaxDecoder::GetSrcOffset() 659 { 660 FX_DWORD ret = (bitpos + 7) / 8; 661 if (ret > m_SrcSize) { 662 ret = m_SrcSize; 663 } 664 return ret; 665 } 666 extern "C" { 667 void _FaxG4Decode(void*, FX_LPCBYTE src_buf, FX_DWORD src_size, int* pbitpos, FX_LPBYTE dest_buf, int width, int height, int pitch) 668 { 669 if (pitch == 0) { 670 pitch = (width + 7) / 8; 671 } 672 FX_LPBYTE ref_buf = FX_Alloc(FX_BYTE, pitch); 673 if (ref_buf == NULL) { 674 return; 675 } 676 FXSYS_memset8(ref_buf, 0xff, pitch); 677 int bitpos = *pbitpos; 678 for (int iRow = 0; iRow < height; iRow ++) { 679 FX_LPBYTE line_buf = dest_buf + iRow * pitch; 680 FXSYS_memset8(line_buf, 0xff, pitch); 681 _FaxG4GetRow(src_buf, src_size << 3, bitpos, line_buf, ref_buf, width); 682 FXSYS_memcpy32(ref_buf, line_buf, pitch); 683 } 684 FX_Free(ref_buf); 685 *pbitpos = bitpos; 686 } 687 }; 688 static const FX_BYTE BlackRunTerminator[128] = { 689 0x37, 10, 0x02, 3, 0x03, 2, 0x02, 2, 0x03, 3, 0x03, 4, 0x02, 4, 0x03, 5, 690 0x05, 6, 0x04, 6, 0x04, 7, 0x05, 7, 0x07, 7, 0x04, 8, 0x07, 8, 0x18, 9, 691 0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11, 0x6c, 11, 0x37, 11, 0x28, 11, 692 0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12, 0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12, 693 0x6a, 12, 0x6b, 12, 0xd2, 12, 0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12, 694 0x6c, 12, 0x6d, 12, 0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12, 695 0x64, 12, 0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12, 696 0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12, 0x67, 12, 697 }; 698 static const FX_BYTE BlackRunMarkup[80] = { 699 0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12, 0x6c, 13, 700 0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13, 0x73, 13, 0x74, 13, 701 0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13, 0x54, 13, 0x55, 13, 0x5a, 13, 702 0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11, 0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 703 0x14, 12, 0x15, 12, 0x16, 12, 0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12, 704 }; 705 static const FX_BYTE WhiteRunTerminator[128] = { 706 0x35, 8, 707 0x07, 6, 708 0x07, 4, 709 0x08, 4, 710 0x0B, 4, 711 0x0C, 4, 712 0x0E, 4, 713 0x0F, 4, 714 0x13, 5, 715 0x14, 5, 716 0x07, 5, 717 0x08, 5, 718 0x08, 6, 719 0x03, 6, 720 0x34, 6, 721 0x35, 6, 722 0x2a, 6, 723 0x2B, 6, 724 0x27, 7, 725 0x0c, 7, 726 0x08, 7, 727 0x17, 7, 728 0x03, 7, 729 0x04, 7, 730 0x28, 7, 731 0x2B, 7, 732 0x13, 7, 733 0x24, 7, 734 0x18, 7, 735 0x02, 8, 736 0x03, 8, 737 0x1a, 8, 738 0x1b, 8, 739 0x12, 8, 740 0x13, 8, 741 0x14, 8, 742 0x15, 8, 743 0x16, 8, 744 0x17, 8, 745 0x28, 8, 746 0x29, 8, 747 0x2a, 8, 748 0x2b, 8, 749 0x2c, 8, 750 0x2d, 8, 751 0x04, 8, 752 0x05, 8, 753 0x0a, 8, 754 0x0b, 8, 755 0x52, 8, 756 0x53, 8, 757 0x54, 8, 758 0x55, 8, 759 0x24, 8, 760 0x25, 8, 761 0x58, 8, 762 0x59, 8, 763 0x5a, 8, 764 0x5b, 8, 765 0x4a, 8, 766 0x4b, 8, 767 0x32, 8, 768 0x33, 8, 769 0x34, 8, 770 }; 771 static const FX_BYTE WhiteRunMarkup[80] = { 772 0x1b, 5, 773 0x12, 5, 774 0x17, 6, 775 0x37, 7, 776 0x36, 8, 777 0x37, 8, 778 0x64, 8, 779 0x65, 8, 780 0x68, 8, 781 0x67, 8, 782 0xcc, 9, 783 0xcd, 9, 784 0xd2, 9, 785 0xd3, 9, 786 0xd4, 9, 787 0xd5, 9, 788 0xd6, 9, 789 0xd7, 9, 790 0xd8, 9, 791 0xd9, 9, 792 0xda, 9, 793 0xdb, 9, 794 0x98, 9, 795 0x99, 9, 796 0x9a, 9, 797 0x18, 6, 798 0x9b, 9, 799 0x08, 11, 800 0x0c, 11, 801 0x0d, 11, 802 0x12, 12, 803 0x13, 12, 804 0x14, 12, 805 0x15, 12, 806 0x16, 12, 807 0x17, 12, 808 0x1c, 12, 809 0x1d, 12, 810 0x1e, 12, 811 0x1f, 12, 812 }; 813 static void _AddBitStream(FX_LPBYTE dest_buf, int& dest_bitpos, int data, int bitlen) 814 { 815 for (int i = bitlen - 1; i >= 0; i --) { 816 if (data & (1 << i)) { 817 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8); 818 } 819 dest_bitpos ++; 820 } 821 } 822 static void _FaxEncodeRun(FX_LPBYTE dest_buf, int& dest_bitpos, int run, FX_BOOL bWhite) 823 { 824 while (run >= 2560) { 825 _AddBitStream(dest_buf, dest_bitpos, 0x1f, 12); 826 run -= 2560; 827 } 828 if (run >= 64) { 829 int markup = run - run % 64; 830 FX_LPCBYTE p = bWhite ? WhiteRunMarkup : BlackRunMarkup; 831 p += (markup / 64 - 1) * 2; 832 _AddBitStream(dest_buf, dest_bitpos, *p, p[1]); 833 } 834 run %= 64; 835 FX_LPCBYTE p = bWhite ? WhiteRunTerminator : BlackRunTerminator; 836 p += run * 2; 837 _AddBitStream(dest_buf, dest_bitpos, *p, p[1]); 838 } 839 static void _FaxEncode2DLine(FX_LPBYTE dest_buf, int& dest_bitpos, FX_LPCBYTE src_buf, FX_LPCBYTE ref_buf, int cols) 840 { 841 int a0 = -1, a0color = 1; 842 while (1) { 843 int a1 = _FindBit(src_buf, cols, a0 + 1, 1 - a0color); 844 int b1, b2; 845 _FaxG4FindB1B2(ref_buf, cols, a0, a0color, b1, b2); 846 if (b2 < a1) { 847 dest_bitpos += 3; 848 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8); 849 dest_bitpos ++; 850 a0 = b2; 851 } else if (a1 - b1 <= 3 && b1 - a1 <= 3) { 852 int delta = a1 - b1; 853 switch (delta) { 854 case 0: 855 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8); 856 break; 857 case 1: 858 case 2: 859 case 3: 860 dest_bitpos += delta == 1 ? 1 : delta + 2; 861 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8); 862 dest_bitpos ++; 863 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8); 864 break; 865 case -1: 866 case -2: 867 case -3: 868 dest_bitpos += delta == -1 ? 1 : -delta + 2; 869 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8); 870 dest_bitpos ++; 871 break; 872 } 873 dest_bitpos ++; 874 a0 = a1; 875 a0color = 1 - a0color; 876 } else { 877 int a2 = _FindBit(src_buf, cols, a1 + 1, a0color); 878 dest_bitpos ++; 879 dest_bitpos ++; 880 dest_buf[dest_bitpos / 8] |= 1 << (7 - dest_bitpos % 8); 881 dest_bitpos ++; 882 if (a0 < 0) { 883 a0 = 0; 884 } 885 _FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color); 886 _FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, 1 - a0color); 887 a0 = a2; 888 } 889 if (a0 >= cols) { 890 return; 891 } 892 } 893 } 894 class CCodec_FaxEncoder : public CFX_Object 895 { 896 public: 897 CCodec_FaxEncoder(FX_LPCBYTE src_buf, int width, int height, int pitch); 898 ~CCodec_FaxEncoder(); 899 void Encode(FX_LPBYTE& dest_buf, FX_DWORD& dest_size); 900 void Encode2DLine(FX_LPCBYTE scan_line); 901 CFX_BinaryBuf m_DestBuf; 902 FX_LPBYTE m_pRefLine, m_pLineBuf; 903 int m_Cols, m_Rows, m_Pitch; 904 FX_LPCBYTE m_pSrcBuf; 905 }; 906 CCodec_FaxEncoder::CCodec_FaxEncoder(FX_LPCBYTE src_buf, int width, int height, int pitch) 907 { 908 m_pSrcBuf = src_buf; 909 m_Cols = width; 910 m_Rows = height; 911 m_Pitch = pitch; 912 m_pRefLine = FX_Alloc(FX_BYTE, m_Pitch); 913 if (m_pRefLine == NULL) { 914 return; 915 } 916 FXSYS_memset8(m_pRefLine, 0xff, m_Pitch); 917 m_pLineBuf = FX_Alloc(FX_BYTE, m_Pitch * 8); 918 if (m_pLineBuf == NULL) { 919 return; 920 } 921 m_DestBuf.EstimateSize(0, 10240); 922 } 923 CCodec_FaxEncoder::~CCodec_FaxEncoder() 924 { 925 if (m_pRefLine) { 926 FX_Free(m_pRefLine); 927 } 928 if (m_pLineBuf) { 929 FX_Free(m_pLineBuf); 930 } 931 } 932 void CCodec_FaxEncoder::Encode(FX_LPBYTE& dest_buf, FX_DWORD& dest_size) 933 { 934 int dest_bitpos = 0; 935 FX_BYTE last_byte = 0; 936 for (int i = 0; i < m_Rows; i ++) { 937 FX_LPCBYTE scan_line = m_pSrcBuf + i * m_Pitch; 938 FXSYS_memset32(m_pLineBuf, 0, m_Pitch * 8); 939 m_pLineBuf[0] = last_byte; 940 _FaxEncode2DLine(m_pLineBuf, dest_bitpos, scan_line, m_pRefLine, m_Cols); 941 m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8); 942 last_byte = m_pLineBuf[dest_bitpos / 8]; 943 dest_bitpos %= 8; 944 FXSYS_memcpy32(m_pRefLine, scan_line, m_Pitch); 945 } 946 if (dest_bitpos) { 947 m_DestBuf.AppendByte(last_byte); 948 } 949 dest_buf = m_DestBuf.GetBuffer(); 950 dest_size = m_DestBuf.GetSize(); 951 m_DestBuf.DetachBuffer(); 952 } 953 FX_BOOL CCodec_FaxModule::Encode(FX_LPCBYTE src_buf, int width, int height, int pitch, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) 954 { 955 CCodec_FaxEncoder encoder(src_buf, width, height, pitch); 956 encoder.Encode(dest_buf, dest_size); 957 return TRUE; 958 } 959 ICodec_ScanlineDecoder* CCodec_FaxModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, 960 int K, FX_BOOL EndOfLine, FX_BOOL EncodedByteAlign, FX_BOOL BlackIs1, int Columns, int Rows) 961 { 962 CCodec_FaxDecoder* pDecoder = FX_NEW CCodec_FaxDecoder; 963 if (pDecoder == NULL) { 964 return NULL; 965 } 966 pDecoder->Create(src_buf, src_size, width, height, K, EndOfLine, EncodedByteAlign, BlackIs1, Columns, Rows); 967 return pDecoder; 968 } 969