1 31 package org.pdfbox.filter; 32 33 import java.io.ByteArrayOutputStream ; 34 import java.io.IOException ; 35 import java.io.InputStream ; 36 import java.io.OutputStream ; 37 import java.text.SimpleDateFormat ; 38 import java.util.Date ; 39 40 import org.pdfbox.cos.COSDictionary; 41 import org.pdfbox.cos.COSName; 42 43 51 public class CCITTFaxDecodeFilter implements Filter 52 { 53 private static final int TAG_COUNT = 15; 56 57 private int offset = 8; 59 60 private int tailingBytesCount = 0; 62 63 private final ByteArrayOutputStream tailer = new ByteArrayOutputStream (); 65 66 69 public CCITTFaxDecodeFilter() 70 { 71 } 72 73 86 public void decode(InputStream compressedData, OutputStream result, COSDictionary options) throws IOException 87 { 88 91 92 COSDictionary dict = (COSDictionary) options.getDictionaryObject("DecodeParms"); 94 int width = options.getInt("Width"); 95 int height = options.getInt("Height"); 96 int length = options.getInt(COSName.LENGTH); 97 int compressionType = dict.getInt("K"); 98 boolean blackIs1 = dict.getBoolean("BlackIs1", false); 99 100 101 writeTagHeader(result, length); 103 104 int i = 0; 106 byte[] buffer = new byte[32768]; 108 int lentoread = length; 109 110 while ((lentoread > 0) && ((i = compressedData.read(buffer, 0, Math.min(lentoread, 32768))) != -1)) 111 { 112 result.write(buffer, 0, i); 114 lentoread = lentoread - i; 115 } 116 117 while (lentoread > 0) 120 { 121 result.write(buffer, 0, Math.min(lentoread, 32768)); 122 lentoread = lentoread - Math.min(lentoread, 32738); 123 } 124 126 writeTagCount(result); 128 129 writeTagWidth(result, width); 131 132 writeTagHeight(result, height); 134 135 writeTagBitsPerSample(result, 1); 138 139 writeTagCompression(result, compressionType); 141 142 writeTagPhotometric(result, blackIs1); 144 145 writeTagStripOffset(result, 8); 148 149 writeTagOrientation(result, 1); 151 152 writeTagSamplesPerPixel(result, 1); 154 155 writeTagRowsPerStrip(result, height); 157 158 writeTagStripByteCount(result, length); 160 161 writeTagXRes(result, 200, 1); 164 165 writeTagYRes(result, 200, 1); 168 169 writeTagResolutionUnit(result, 2); 172 173 writeTagSoftware(result, "pdfbox".getBytes()); 176 177 writeTagDateTime(result, new Date ()); 179 180 writeTagTailer(result); 182 } 183 184 private void writeTagHeader(OutputStream result, int length) throws IOException 185 { 186 byte[] header = { 'M', 'M', 0, '*' }; result.write(header); 188 189 190 offset += length; 192 193 int i1 = offset/16777216; int i2 = (offset-i1*16777216)/65536; 196 int i3 = (offset-i1*16777216-i2*65536)/256; 197 int i4 = offset % 256; 198 result.write(i1); 199 result.write(i2); 200 result.write(i3); 201 result.write(i4); 202 } 203 204 private void writeTagCount(OutputStream result) throws IOException 205 { 206 result.write(TAG_COUNT / 256); 207 result.write(TAG_COUNT % 256); } 209 210 private void writeTagWidth(OutputStream result, int width) throws IOException 211 { 212 214 result.write(1); 216 result.write(0); 217 218 219 result.write(0); 221 result.write(3); 222 223 224 result.write(0); 226 result.write(0); 227 result.write(0); 228 result.write(1); 229 230 231 result.write(width/256); 233 result.write(width%256); 234 result.write(0); result.write(0); 237 } 238 239 private void writeTagHeight(OutputStream result, int height) throws IOException 240 { 241 result.write(1); 244 result.write(1); 245 246 247 result.write(0); 249 result.write(3); 250 251 252 result.write(0); 254 result.write(0); 255 result.write(0); 256 result.write(1); 257 258 259 result.write(height/256); 261 result.write(height%256); 262 result.write(0); result.write(0); 265 } 266 267 private void writeTagBitsPerSample(OutputStream result, int value) throws IOException 268 { 269 result.write(1); 271 result.write(2); 272 273 274 result.write(0); 276 result.write(3); 277 278 result.write(0); 280 result.write(0); 281 result.write(0); 282 result.write(1); 283 284 285 result.write(value/256); 287 result.write(value%256); 288 result.write(0); result.write(0); 291 } 292 293 300 public void writeTagCompression(OutputStream result, int type) throws IOException 301 { 302 result.write(1); 304 result.write(3); 305 306 result.write(0); 308 result.write(3); 309 310 311 result.write(0); 313 result.write(0); 314 result.write(0); 315 result.write(1); 316 317 result.write(0); 320 if (type < 0) 321 { 322 result.write(4); } 324 else if (type == 0) 325 { 326 result.write(3); } 328 else 329 { 330 result.write(2); } 332 result.write(0); 333 result.write(0); 334 335 } 336 337 private void writeTagPhotometric(OutputStream result, boolean blackIs1) throws IOException 338 { 339 result.write(1); 341 result.write(6); 342 343 344 result.write(0); 346 result.write(3); 347 348 349 result.write(0); 351 result.write(0); 352 result.write(0); 353 result.write(1); 354 355 356 result.write(0); 358 if (blackIs1) 359 { 360 result.write(1); 361 } 362 else 363 { 364 result.write(0); 365 } 366 result.write(0); result.write(0); 369 } 370 371 private void writeTagStripOffset(OutputStream result, int value) throws IOException 372 { 373 result.write(1); 375 result.write(17); 376 377 result.write(0); 379 result.write(4); 380 381 382 result.write(0); 384 result.write(0); 385 result.write(0); 386 result.write(1); 387 388 389 int i1 = value/16777216; int i2 = (value-i1*16777216)/65536; 392 int i3 = (value-i1*16777216-i2*65536)/256; 393 int i4 = value % 256; 394 result.write(i1); 395 result.write(i2); 396 result.write(i3); 397 result.write(i4); 398 399 } 400 401 private void writeTagSamplesPerPixel(OutputStream result, int value) throws IOException 402 { 403 result.write(1); 405 result.write(21); 406 407 408 result.write(0); 410 result.write(3); 411 412 413 result.write(0); 415 result.write(0); 416 result.write(0); 417 result.write(1); 418 419 420 result.write(value / 256); 422 result.write(value % 256); 423 result.write(0); result.write(0); 426 } 427 428 private void writeTagRowsPerStrip(OutputStream result, int value) throws IOException 429 { 430 result.write(1); 432 result.write(22); 433 434 435 result.write(0); 437 result.write(3); 438 439 440 result.write(0); 442 result.write(0); 443 result.write(0); 444 result.write(1); 445 446 447 result.write(value / 256); 449 result.write(value % 256); 450 result.write(0); result.write(0); 453 } 454 455 private void writeTagStripByteCount(OutputStream result, int value) throws IOException 456 { 457 result.write(1); 460 result.write(23); 461 462 result.write(0); 464 result.write(4); 465 466 467 result.write(0); 469 result.write(0); 470 result.write(0); 471 result.write(1); 472 473 int i1 = value/16777216; int i2 = (value-i1*16777216)/65536; 476 int i3 = (value-i1*16777216-i2*65536)/256; 477 int i4 = value % 256; 478 result.write(i1); 479 result.write(i2); 480 result.write(i3); 481 result.write(i4); 482 483 } 484 485 private void writeTagXRes(OutputStream result, int value1, int value2) throws IOException 486 { 487 result.write(1); 489 result.write(26); 490 491 result.write(0); 493 result.write(5); 494 495 result.write(0); 497 result.write(0); 498 result.write(0); 499 result.write(1); 500 501 502 int valueOffset = offset + 6 + 12 * TAG_COUNT + tailer.size(); 504 int i1 = valueOffset/16777216; int i2 = (valueOffset-i1*16777216)/65536; 506 int i3 = (valueOffset-i1*16777216-i2*65536)/256; 507 int i4 = valueOffset % 256; 508 result.write(i1); 509 result.write(i2); 510 result.write(i3); 511 result.write(i4); 512 513 i1 = value1 /16777216; 514 i2 = (value1-i1*16777216)/65536; 515 i3 = (value1-i1*16777216 - i2*65536)/256; 516 i4 = value1 % 256; 517 tailer.write(i1); 518 tailer.write(i2); 519 tailer.write(i3); 520 tailer.write(i4); 521 522 i1 = value2 /16777216; 523 i2 = (value2-i1*16777216)/65536; 524 i3 = (value2-i1*16777216 - i2*65536)/256; 525 i4 = value2 % 256; 526 tailer.write(i1); 527 tailer.write(i2); 528 tailer.write(i3); 529 tailer.write(i4); 530 531 tailingBytesCount += 8; 532 } 533 534 private void writeTagYRes(OutputStream result, int value1, int value2) throws IOException 535 { 536 result.write(1); 538 result.write(27); 539 540 541 result.write(0); 543 result.write(5); 544 545 result.write(0); 547 result.write(0); 548 result.write(0); 549 result.write(1); 550 551 552 int valueOffset = offset + 6 + 12 * TAG_COUNT + tailer.size(); 554 int i1 = valueOffset/16777216; int i2 = (valueOffset-i1*16777216)/65536; 556 int i3 = (valueOffset-i1*16777216-i2*65536)/256; 557 int i4 = valueOffset % 256; 558 result.write(i1); 559 result.write(i2); 560 result.write(i3); 561 result.write(i4); 562 563 i1 = value1 /16777216; 564 i2 = (value1-i1*16777216)/65536; 565 i3 = (value1-i1*16777216 - i2*65536)/256; 566 i4 = value1 % 256; 567 tailer.write(i1); 568 tailer.write(i2); 569 tailer.write(i3); 570 tailer.write(i4); 571 572 i1 = value2 /16777216; 573 i2 = (value2-i1*16777216)/65536; 574 i3 = (value2-i1*16777216 - i2*65536)/256; 575 i4 = value2 % 256; 576 tailer.write(i1); 577 tailer.write(i2); 578 tailer.write(i3); 579 tailer.write(i4); 580 581 tailingBytesCount += 8; 582 } 583 584 private void writeTagResolutionUnit(OutputStream result, int value) throws IOException 585 { 586 result.write(1); 588 result.write(40); 589 590 result.write(0); 592 result.write(3); 593 594 result.write(0); 596 result.write(0); 597 result.write(0); 598 result.write(1); 599 600 result.write(value/256); 602 result.write(value%256); 603 result.write(0); result.write(0); 606 } 607 608 private void writeTagOrientation(OutputStream result, int value) throws IOException 609 { 610 result.write(1); 612 result.write(18); 613 614 result.write(0); 616 result.write(3); 617 618 619 result.write(0); 621 result.write(0); 622 result.write(0); 623 result.write(1); 624 625 result.write(value / 256); 627 result.write(value % 256); 628 result.write(0); result.write(0); 631 } 632 633 private void writeTagTailer(OutputStream result) throws IOException 634 { 635 result.write(0); 637 result.write(0); 638 result.write(0); 639 result.write(0); 640 641 result.write(tailer.toByteArray()); 643 } 644 645 private void writeTagSoftware(OutputStream result, byte[] text) throws IOException 646 { 647 result.write(1); 649 result.write(49); 650 651 result.write(0); 653 result.write(2); 654 655 656 result.write(0); 658 result.write(0); 659 result.write((text.length + 1) / 256); 660 result.write((text.length + 1) % 256); 661 662 int valueOffset = offset + 6 + 12 * TAG_COUNT + tailer.size(); 664 int i1 = valueOffset/16777216; int i2 = (valueOffset-i1*16777216)/65536; 666 int i3 = (valueOffset-i1*16777216-i2*65536)/256; 667 int i4 = valueOffset % 256; 668 result.write(i1); 669 result.write(i2); 670 result.write(i3); 671 result.write(i4); 672 673 674 tailer.write(text); 675 tailer.write(0); 676 tailingBytesCount += text.length + 1; 677 } 678 679 private void writeTagDateTime(OutputStream result, Date date) throws IOException 680 { 681 result.write(1); 683 result.write(50); 684 685 686 result.write(0); 688 result.write(2); 689 690 691 result.write(0); 693 result.write(0); 694 result.write(0); 695 result.write(20); 696 697 698 int valueOffset = offset + 6 + 12 * TAG_COUNT + tailer.size(); 700 int i1 = valueOffset/16777216; int i2 = (valueOffset-i1*16777216)/65536; 702 int i3 = (valueOffset-i1*16777216-i2*65536)/256; 703 int i4 = valueOffset % 256; 704 result.write(i1); 705 result.write(i2); 706 result.write(i3); 707 result.write(i4); 708 709 SimpleDateFormat sdf = new SimpleDateFormat ("yyyy:MM:dd HH:mm:ss"); 710 String datetime = sdf.format(date); 711 tailer.write(datetime.getBytes()); 712 tailer.write(0); 713 714 tailingBytesCount += 20; 715 } 716 717 730 public void encode(InputStream rawData, OutputStream result, COSDictionary options) throws IOException 731 { 732 System.err.println("Warning: CCITTFaxDecode.encode is not implemented yet, skipping this stream."); 733 } 734 } | Popular Tags |