From 6025b6016517c6d898d8957d1d7e03ba71431912 Mon Sep 17 00:00:00 2001 From: tknall Date: Fri, 1 Dec 2006 12:20:24 +0000 Subject: Initial import of release 2.2. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@4 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../com/lowagie/text/pdf/codec/TIFFFaxDecoder.java | 1477 ++++++++++++++++++++ 1 file changed, 1477 insertions(+) create mode 100644 src/main/java/com/lowagie/text/pdf/codec/TIFFFaxDecoder.java (limited to 'src/main/java/com/lowagie/text/pdf/codec/TIFFFaxDecoder.java') diff --git a/src/main/java/com/lowagie/text/pdf/codec/TIFFFaxDecoder.java b/src/main/java/com/lowagie/text/pdf/codec/TIFFFaxDecoder.java new file mode 100644 index 0000000..7a7b61c --- /dev/null +++ b/src/main/java/com/lowagie/text/pdf/codec/TIFFFaxDecoder.java @@ -0,0 +1,1477 @@ +/* + * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * -Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR + * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE + * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS + * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, + * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER + * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF + * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that Software is not designed,licensed or intended for use in + * the design, construction, operation or maintenance of any nuclear facility. + */ +package com.lowagie.text.pdf.codec; + +public class TIFFFaxDecoder { + + private int bitPointer, bytePointer; + private byte[] data; + private int w, h; + private int fillOrder; + + // Data structures needed to store changing elements for the previous + // and the current scanline + private int changingElemSize = 0; + private int prevChangingElems[]; + private int currChangingElems[]; + + // Element at which to start search in getNextChangingElement + private int lastChangingElement = 0; + + private int compression = 2; + + // Variables set by T4Options + private int uncompressedMode = 0; + private int fillBits = 0; + private int oneD; + + static int table1[] = { + 0x00, // 0 bits are left in first byte - SHOULD NOT HAPPEN + 0x01, // 1 bits are left in first byte + 0x03, // 2 bits are left in first byte + 0x07, // 3 bits are left in first byte + 0x0f, // 4 bits are left in first byte + 0x1f, // 5 bits are left in first byte + 0x3f, // 6 bits are left in first byte + 0x7f, // 7 bits are left in first byte + 0xff // 8 bits are left in first byte + }; + + static int table2[] = { + 0x00, // 0 + 0x80, // 1 + 0xc0, // 2 + 0xe0, // 3 + 0xf0, // 4 + 0xf8, // 5 + 0xfc, // 6 + 0xfe, // 7 + 0xff // 8 + }; + + // Table to be used when fillOrder = 2, for flipping bytes. + static byte flipTable[] = { + 0, -128, 64, -64, 32, -96, 96, -32, + 16, -112, 80, -48, 48, -80, 112, -16, + 8, -120, 72, -56, 40, -88, 104, -24, + 24, -104, 88, -40, 56, -72, 120, -8, + 4, -124, 68, -60, 36, -92, 100, -28, + 20, -108, 84, -44, 52, -76, 116, -12, + 12, -116, 76, -52, 44, -84, 108, -20, + 28, -100, 92, -36, 60, -68, 124, -4, + 2, -126, 66, -62, 34, -94, 98, -30, + 18, -110, 82, -46, 50, -78, 114, -14, + 10, -118, 74, -54, 42, -86, 106, -22, + 26, -102, 90, -38, 58, -70, 122, -6, + 6, -122, 70, -58, 38, -90, 102, -26, + 22, -106, 86, -42, 54, -74, 118, -10, + 14, -114, 78, -50, 46, -82, 110, -18, + 30, -98, 94, -34, 62, -66, 126, -2, + 1, -127, 65, -63, 33, -95, 97, -31, + 17, -111, 81, -47, 49, -79, 113, -15, + 9, -119, 73, -55, 41, -87, 105, -23, + 25, -103, 89, -39, 57, -71, 121, -7, + 5, -123, 69, -59, 37, -91, 101, -27, + 21, -107, 85, -43, 53, -75, 117, -11, + 13, -115, 77, -51, 45, -83, 109, -19, + 29, -99, 93, -35, 61, -67, 125, -3, + 3, -125, 67, -61, 35, -93, 99, -29, + 19, -109, 83, -45, 51, -77, 115, -13, + 11, -117, 75, -53, 43, -85, 107, -21, + 27, -101, 91, -37, 59, -69, 123, -5, + 7, -121, 71, -57, 39, -89, 103, -25, + 23, -105, 87, -41, 55, -73, 119, -9, + 15, -113, 79, -49, 47, -81, 111, -17, + 31, -97, 95, -33, 63, -65, 127, -1, + }; + + // The main 10 bit white runs lookup table + static short white[] = { + // 0 - 7 + 6430, 6400, 6400, 6400, 3225, 3225, 3225, 3225, + // 8 - 15 + 944, 944, 944, 944, 976, 976, 976, 976, + // 16 - 23 + 1456, 1456, 1456, 1456, 1488, 1488, 1488, 1488, + // 24 - 31 + 718, 718, 718, 718, 718, 718, 718, 718, + // 32 - 39 + 750, 750, 750, 750, 750, 750, 750, 750, + // 40 - 47 + 1520, 1520, 1520, 1520, 1552, 1552, 1552, 1552, + // 48 - 55 + 428, 428, 428, 428, 428, 428, 428, 428, + // 56 - 63 + 428, 428, 428, 428, 428, 428, 428, 428, + // 64 - 71 + 654, 654, 654, 654, 654, 654, 654, 654, + // 72 - 79 + 1072, 1072, 1072, 1072, 1104, 1104, 1104, 1104, + // 80 - 87 + 1136, 1136, 1136, 1136, 1168, 1168, 1168, 1168, + // 88 - 95 + 1200, 1200, 1200, 1200, 1232, 1232, 1232, 1232, + // 96 - 103 + 622, 622, 622, 622, 622, 622, 622, 622, + // 104 - 111 + 1008, 1008, 1008, 1008, 1040, 1040, 1040, 1040, + // 112 - 119 + 44, 44, 44, 44, 44, 44, 44, 44, + // 120 - 127 + 44, 44, 44, 44, 44, 44, 44, 44, + // 128 - 135 + 396, 396, 396, 396, 396, 396, 396, 396, + // 136 - 143 + 396, 396, 396, 396, 396, 396, 396, 396, + // 144 - 151 + 1712, 1712, 1712, 1712, 1744, 1744, 1744, 1744, + // 152 - 159 + 846, 846, 846, 846, 846, 846, 846, 846, + // 160 - 167 + 1264, 1264, 1264, 1264, 1296, 1296, 1296, 1296, + // 168 - 175 + 1328, 1328, 1328, 1328, 1360, 1360, 1360, 1360, + // 176 - 183 + 1392, 1392, 1392, 1392, 1424, 1424, 1424, 1424, + // 184 - 191 + 686, 686, 686, 686, 686, 686, 686, 686, + // 192 - 199 + 910, 910, 910, 910, 910, 910, 910, 910, + // 200 - 207 + 1968, 1968, 1968, 1968, 2000, 2000, 2000, 2000, + // 208 - 215 + 2032, 2032, 2032, 2032, 16, 16, 16, 16, + // 216 - 223 + 10257, 10257, 10257, 10257, 12305, 12305, 12305, 12305, + // 224 - 231 + 330, 330, 330, 330, 330, 330, 330, 330, + // 232 - 239 + 330, 330, 330, 330, 330, 330, 330, 330, + // 240 - 247 + 330, 330, 330, 330, 330, 330, 330, 330, + // 248 - 255 + 330, 330, 330, 330, 330, 330, 330, 330, + // 256 - 263 + 362, 362, 362, 362, 362, 362, 362, 362, + // 264 - 271 + 362, 362, 362, 362, 362, 362, 362, 362, + // 272 - 279 + 362, 362, 362, 362, 362, 362, 362, 362, + // 280 - 287 + 362, 362, 362, 362, 362, 362, 362, 362, + // 288 - 295 + 878, 878, 878, 878, 878, 878, 878, 878, + // 296 - 303 + 1904, 1904, 1904, 1904, 1936, 1936, 1936, 1936, + // 304 - 311 + -18413, -18413, -16365, -16365, -14317, -14317, -10221, -10221, + // 312 - 319 + 590, 590, 590, 590, 590, 590, 590, 590, + // 320 - 327 + 782, 782, 782, 782, 782, 782, 782, 782, + // 328 - 335 + 1584, 1584, 1584, 1584, 1616, 1616, 1616, 1616, + // 336 - 343 + 1648, 1648, 1648, 1648, 1680, 1680, 1680, 1680, + // 344 - 351 + 814, 814, 814, 814, 814, 814, 814, 814, + // 352 - 359 + 1776, 1776, 1776, 1776, 1808, 1808, 1808, 1808, + // 360 - 367 + 1840, 1840, 1840, 1840, 1872, 1872, 1872, 1872, + // 368 - 375 + 6157, 6157, 6157, 6157, 6157, 6157, 6157, 6157, + // 376 - 383 + 6157, 6157, 6157, 6157, 6157, 6157, 6157, 6157, + // 384 - 391 + -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, + // 392 - 399 + -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, + // 400 - 407 + 14353, 14353, 14353, 14353, 16401, 16401, 16401, 16401, + // 408 - 415 + 22547, 22547, 24595, 24595, 20497, 20497, 20497, 20497, + // 416 - 423 + 18449, 18449, 18449, 18449, 26643, 26643, 28691, 28691, + // 424 - 431 + 30739, 30739, -32749, -32749, -30701, -30701, -28653, -28653, + // 432 - 439 + -26605, -26605, -24557, -24557, -22509, -22509, -20461, -20461, + // 440 - 447 + 8207, 8207, 8207, 8207, 8207, 8207, 8207, 8207, + // 448 - 455 + 72, 72, 72, 72, 72, 72, 72, 72, + // 456 - 463 + 72, 72, 72, 72, 72, 72, 72, 72, + // 464 - 471 + 72, 72, 72, 72, 72, 72, 72, 72, + // 472 - 479 + 72, 72, 72, 72, 72, 72, 72, 72, + // 480 - 487 + 72, 72, 72, 72, 72, 72, 72, 72, + // 488 - 495 + 72, 72, 72, 72, 72, 72, 72, 72, + // 496 - 503 + 72, 72, 72, 72, 72, 72, 72, 72, + // 504 - 511 + 72, 72, 72, 72, 72, 72, 72, 72, + // 512 - 519 + 104, 104, 104, 104, 104, 104, 104, 104, + // 520 - 527 + 104, 104, 104, 104, 104, 104, 104, 104, + // 528 - 535 + 104, 104, 104, 104, 104, 104, 104, 104, + // 536 - 543 + 104, 104, 104, 104, 104, 104, 104, 104, + // 544 - 551 + 104, 104, 104, 104, 104, 104, 104, 104, + // 552 - 559 + 104, 104, 104, 104, 104, 104, 104, 104, + // 560 - 567 + 104, 104, 104, 104, 104, 104, 104, 104, + // 568 - 575 + 104, 104, 104, 104, 104, 104, 104, 104, + // 576 - 583 + 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, + // 584 - 591 + 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, + // 592 - 599 + 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, + // 600 - 607 + 4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, + // 608 - 615 + 266, 266, 266, 266, 266, 266, 266, 266, + // 616 - 623 + 266, 266, 266, 266, 266, 266, 266, 266, + // 624 - 631 + 266, 266, 266, 266, 266, 266, 266, 266, + // 632 - 639 + 266, 266, 266, 266, 266, 266, 266, 266, + // 640 - 647 + 298, 298, 298, 298, 298, 298, 298, 298, + // 648 - 655 + 298, 298, 298, 298, 298, 298, 298, 298, + // 656 - 663 + 298, 298, 298, 298, 298, 298, 298, 298, + // 664 - 671 + 298, 298, 298, 298, 298, 298, 298, 298, + // 672 - 679 + 524, 524, 524, 524, 524, 524, 524, 524, + // 680 - 687 + 524, 524, 524, 524, 524, 524, 524, 524, + // 688 - 695 + 556, 556, 556, 556, 556, 556, 556, 556, + // 696 - 703 + 556, 556, 556, 556, 556, 556, 556, 556, + // 704 - 711 + 136, 136, 136, 136, 136, 136, 136, 136, + // 712 - 719 + 136, 136, 136, 136, 136, 136, 136, 136, + // 720 - 727 + 136, 136, 136, 136, 136, 136, 136, 136, + // 728 - 735 + 136, 136, 136, 136, 136, 136, 136, 136, + // 736 - 743 + 136, 136, 136, 136, 136, 136, 136, 136, + // 744 - 751 + 136, 136, 136, 136, 136, 136, 136, 136, + // 752 - 759 + 136, 136, 136, 136, 136, 136, 136, 136, + // 760 - 767 + 136, 136, 136, 136, 136, 136, 136, 136, + // 768 - 775 + 168, 168, 168, 168, 168, 168, 168, 168, + // 776 - 783 + 168, 168, 168, 168, 168, 168, 168, 168, + // 784 - 791 + 168, 168, 168, 168, 168, 168, 168, 168, + // 792 - 799 + 168, 168, 168, 168, 168, 168, 168, 168, + // 800 - 807 + 168, 168, 168, 168, 168, 168, 168, 168, + // 808 - 815 + 168, 168, 168, 168, 168, 168, 168, 168, + // 816 - 823 + 168, 168, 168, 168, 168, 168, 168, 168, + // 824 - 831 + 168, 168, 168, 168, 168, 168, 168, 168, + // 832 - 839 + 460, 460, 460, 460, 460, 460, 460, 460, + // 840 - 847 + 460, 460, 460, 460, 460, 460, 460, 460, + // 848 - 855 + 492, 492, 492, 492, 492, 492, 492, 492, + // 856 - 863 + 492, 492, 492, 492, 492, 492, 492, 492, + // 864 - 871 + 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, + // 872 - 879 + 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, + // 880 - 887 + 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, + // 888 - 895 + 2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, + // 896 - 903 + 200, 200, 200, 200, 200, 200, 200, 200, + // 904 - 911 + 200, 200, 200, 200, 200, 200, 200, 200, + // 912 - 919 + 200, 200, 200, 200, 200, 200, 200, 200, + // 920 - 927 + 200, 200, 200, 200, 200, 200, 200, 200, + // 928 - 935 + 200, 200, 200, 200, 200, 200, 200, 200, + // 936 - 943 + 200, 200, 200, 200, 200, 200, 200, 200, + // 944 - 951 + 200, 200, 200, 200, 200, 200, 200, 200, + // 952 - 959 + 200, 200, 200, 200, 200, 200, 200, 200, + // 960 - 967 + 232, 232, 232, 232, 232, 232, 232, 232, + // 968 - 975 + 232, 232, 232, 232, 232, 232, 232, 232, + // 976 - 983 + 232, 232, 232, 232, 232, 232, 232, 232, + // 984 - 991 + 232, 232, 232, 232, 232, 232, 232, 232, + // 992 - 999 + 232, 232, 232, 232, 232, 232, 232, 232, + // 1000 - 1007 + 232, 232, 232, 232, 232, 232, 232, 232, + // 1008 - 1015 + 232, 232, 232, 232, 232, 232, 232, 232, + // 1016 - 1023 + 232, 232, 232, 232, 232, 232, 232, 232, + }; + + // Additional make up codes for both White and Black runs + static short additionalMakeup[] = { + 28679, 28679, 31752, (short)32777, + (short)33801, (short)34825, (short)35849, (short)36873, + (short)29703, (short)29703, (short)30727, (short)30727, + (short)37897, (short)38921, (short)39945, (short)40969 + }; + + // Initial black run look up table, uses the first 4 bits of a code + static short initBlack[] = { + // 0 - 7 + 3226, 6412, 200, 168, 38, 38, 134, 134, + // 8 - 15 + 100, 100, 100, 100, 68, 68, 68, 68 + }; + + // + static short twoBitBlack[] = {292, 260, 226, 226}; // 0 - 3 + + // Main black run table, using the last 9 bits of possible 13 bit code + static short black[] = { + // 0 - 7 + 62, 62, 30, 30, 0, 0, 0, 0, + // 8 - 15 + 0, 0, 0, 0, 0, 0, 0, 0, + // 16 - 23 + 0, 0, 0, 0, 0, 0, 0, 0, + // 24 - 31 + 0, 0, 0, 0, 0, 0, 0, 0, + // 32 - 39 + 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, + // 40 - 47 + 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, + // 48 - 55 + 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, + // 56 - 63 + 3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, + // 64 - 71 + 588, 588, 588, 588, 588, 588, 588, 588, + // 72 - 79 + 1680, 1680, 20499, 22547, 24595, 26643, 1776, 1776, + // 80 - 87 + 1808, 1808, -24557, -22509, -20461, -18413, 1904, 1904, + // 88 - 95 + 1936, 1936, -16365, -14317, 782, 782, 782, 782, + // 96 - 103 + 814, 814, 814, 814, -12269, -10221, 10257, 10257, + // 104 - 111 + 12305, 12305, 14353, 14353, 16403, 18451, 1712, 1712, + // 112 - 119 + 1744, 1744, 28691, 30739, -32749, -30701, -28653, -26605, + // 120 - 127 + 2061, 2061, 2061, 2061, 2061, 2061, 2061, 2061, + // 128 - 135 + 424, 424, 424, 424, 424, 424, 424, 424, + // 136 - 143 + 424, 424, 424, 424, 424, 424, 424, 424, + // 144 - 151 + 424, 424, 424, 424, 424, 424, 424, 424, + // 152 - 159 + 424, 424, 424, 424, 424, 424, 424, 424, + // 160 - 167 + 750, 750, 750, 750, 1616, 1616, 1648, 1648, + // 168 - 175 + 1424, 1424, 1456, 1456, 1488, 1488, 1520, 1520, + // 176 - 183 + 1840, 1840, 1872, 1872, 1968, 1968, 8209, 8209, + // 184 - 191 + 524, 524, 524, 524, 524, 524, 524, 524, + // 192 - 199 + 556, 556, 556, 556, 556, 556, 556, 556, + // 200 - 207 + 1552, 1552, 1584, 1584, 2000, 2000, 2032, 2032, + // 208 - 215 + 976, 976, 1008, 1008, 1040, 1040, 1072, 1072, + // 216 - 223 + 1296, 1296, 1328, 1328, 718, 718, 718, 718, + // 224 - 231 + 456, 456, 456, 456, 456, 456, 456, 456, + // 232 - 239 + 456, 456, 456, 456, 456, 456, 456, 456, + // 240 - 247 + 456, 456, 456, 456, 456, 456, 456, 456, + // 248 - 255 + 456, 456, 456, 456, 456, 456, 456, 456, + // 256 - 263 + 326, 326, 326, 326, 326, 326, 326, 326, + // 264 - 271 + 326, 326, 326, 326, 326, 326, 326, 326, + // 272 - 279 + 326, 326, 326, 326, 326, 326, 326, 326, + // 280 - 287 + 326, 326, 326, 326, 326, 326, 326, 326, + // 288 - 295 + 326, 326, 326, 326, 326, 326, 326, 326, + // 296 - 303 + 326, 326, 326, 326, 326, 326, 326, 326, + // 304 - 311 + 326, 326, 326, 326, 326, 326, 326, 326, + // 312 - 319 + 326, 326, 326, 326, 326, 326, 326, 326, + // 320 - 327 + 358, 358, 358, 358, 358, 358, 358, 358, + // 328 - 335 + 358, 358, 358, 358, 358, 358, 358, 358, + // 336 - 343 + 358, 358, 358, 358, 358, 358, 358, 358, + // 344 - 351 + 358, 358, 358, 358, 358, 358, 358, 358, + // 352 - 359 + 358, 358, 358, 358, 358, 358, 358, 358, + // 360 - 367 + 358, 358, 358, 358, 358, 358, 358, 358, + // 368 - 375 + 358, 358, 358, 358, 358, 358, 358, 358, + // 376 - 383 + 358, 358, 358, 358, 358, 358, 358, 358, + // 384 - 391 + 490, 490, 490, 490, 490, 490, 490, 490, + // 392 - 399 + 490, 490, 490, 490, 490, 490, 490, 490, + // 400 - 407 + 4113, 4113, 6161, 6161, 848, 848, 880, 880, + // 408 - 415 + 912, 912, 944, 944, 622, 622, 622, 622, + // 416 - 423 + 654, 654, 654, 654, 1104, 1104, 1136, 1136, + // 424 - 431 + 1168, 1168, 1200, 1200, 1232, 1232, 1264, 1264, + // 432 - 439 + 686, 686, 686, 686, 1360, 1360, 1392, 1392, + // 440 - 447 + 12, 12, 12, 12, 12, 12, 12, 12, + // 448 - 455 + 390, 390, 390, 390, 390, 390, 390, 390, + // 456 - 463 + 390, 390, 390, 390, 390, 390, 390, 390, + // 464 - 471 + 390, 390, 390, 390, 390, 390, 390, 390, + // 472 - 479 + 390, 390, 390, 390, 390, 390, 390, 390, + // 480 - 487 + 390, 390, 390, 390, 390, 390, 390, 390, + // 488 - 495 + 390, 390, 390, 390, 390, 390, 390, 390, + // 496 - 503 + 390, 390, 390, 390, 390, 390, 390, 390, + // 504 - 511 + 390, 390, 390, 390, 390, 390, 390, 390, + }; + + static byte twoDCodes[] = { + // 0 - 7 + 80, 88, 23, 71, 30, 30, 62, 62, + // 8 - 15 + 4, 4, 4, 4, 4, 4, 4, 4, + // 16 - 23 + 11, 11, 11, 11, 11, 11, 11, 11, + // 24 - 31 + 11, 11, 11, 11, 11, 11, 11, 11, + // 32 - 39 + 35, 35, 35, 35, 35, 35, 35, 35, + // 40 - 47 + 35, 35, 35, 35, 35, 35, 35, 35, + // 48 - 55 + 51, 51, 51, 51, 51, 51, 51, 51, + // 56 - 63 + 51, 51, 51, 51, 51, 51, 51, 51, + // 64 - 71 + 41, 41, 41, 41, 41, 41, 41, 41, + // 72 - 79 + 41, 41, 41, 41, 41, 41, 41, 41, + // 80 - 87 + 41, 41, 41, 41, 41, 41, 41, 41, + // 88 - 95 + 41, 41, 41, 41, 41, 41, 41, 41, + // 96 - 103 + 41, 41, 41, 41, 41, 41, 41, 41, + // 104 - 111 + 41, 41, 41, 41, 41, 41, 41, 41, + // 112 - 119 + 41, 41, 41, 41, 41, 41, 41, 41, + // 120 - 127 + 41, 41, 41, 41, 41, 41, 41, 41, + }; + + /** + * @param fillOrder The fill order of the compressed data bytes. + * @param w + * @param h + */ + public TIFFFaxDecoder(int fillOrder, int w, int h) { + this.fillOrder = fillOrder; + this.w = w; + this.h = h; + + this.bitPointer = 0; + this.bytePointer = 0; + this.prevChangingElems = new int[w]; + this.currChangingElems = new int[w]; + } + + // One-dimensional decoding methods + + public void decode1D(byte[] buffer, byte[] compData, + int startX, int height) { + this.data = compData; + + int lineOffset = 0; + int scanlineStride = (w + 7)/8; + + bitPointer = 0; + bytePointer = 0; + + for (int i = 0; i < height; i++) { + decodeNextScanline(buffer, lineOffset, startX); + lineOffset += scanlineStride; + } + } + + public void decodeNextScanline(byte[] buffer, + int lineOffset, int bitOffset) { + int bits = 0, code = 0, isT = 0; + int current, entry, twoBits; + boolean isWhite = true; + + // Initialize starting of the changing elements array + changingElemSize = 0; + + // While scanline not complete + while (bitOffset < w) { + while (isWhite) { + // White run + current = nextNBits(10); + entry = white[current]; + + // Get the 3 fields from the entry + isT = entry & 0x0001; + bits = (entry >>> 1) & 0x0f; + + if (bits == 12) { // Additional Make up code + // Get the next 2 bits + twoBits = nextLesserThan8Bits(2); + // Consolidate the 2 new bits and last 2 bits into 4 bits + current = ((current << 2) & 0x000c) | twoBits; + entry = additionalMakeup[current]; + bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 + code = (entry >>> 4) & 0x0fff; // 12 bits + bitOffset += code; // Skip white run + + updatePointer(4 - bits); + } else if (bits == 0) { // ERROR + throw new RuntimeException("Invalid code encountered."); + } else if (bits == 15) { // EOL + throw new RuntimeException("EOL code word encountered in White run."); + } else { + // 11 bits - 0000 0111 1111 1111 = 0x07ff + code = (entry >>> 5) & 0x07ff; + bitOffset += code; + + updatePointer(10 - bits); + if (isT == 0) { + isWhite = false; + currChangingElems[changingElemSize++] = bitOffset; + } + } + } + + // Check whether this run completed one width, if so + // advance to next byte boundary for compression = 2. + if (bitOffset == w) { + if (compression == 2) { + advancePointer(); + } + break; + } + + while (isWhite == false) { + // Black run + current = nextLesserThan8Bits(4); + entry = initBlack[current]; + + // Get the 3 fields from the entry + isT = entry & 0x0001; + bits = (entry >>> 1) & 0x000f; + code = (entry >>> 5) & 0x07ff; + + if (code == 100) { + current = nextNBits(9); + entry = black[current]; + + // Get the 3 fields from the entry + isT = entry & 0x0001; + bits = (entry >>> 1) & 0x000f; + code = (entry >>> 5) & 0x07ff; + + if (bits == 12) { + // Additional makeup codes + updatePointer(5); + current = nextLesserThan8Bits(4); + entry = additionalMakeup[current]; + bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 + code = (entry >>> 4) & 0x0fff; // 12 bits + + setToBlack(buffer, lineOffset, bitOffset, code); + bitOffset += code; + + updatePointer(4 - bits); + } else if (bits == 15) { + // EOL code + throw new RuntimeException("EOL code word encountered in Black run."); + } else { + setToBlack(buffer, lineOffset, bitOffset, code); + bitOffset += code; + + updatePointer(9 - bits); + if (isT == 0) { + isWhite = true; + currChangingElems[changingElemSize++] = bitOffset; + } + } + } else if (code == 200) { + // Is a Terminating code + current = nextLesserThan8Bits(2); + entry = twoBitBlack[current]; + code = (entry >>> 5) & 0x07ff; + bits = (entry >>> 1) & 0x0f; + + setToBlack(buffer, lineOffset, bitOffset, code); + bitOffset += code; + + updatePointer(2 - bits); + isWhite = true; + currChangingElems[changingElemSize++] = bitOffset; + } else { + // Is a Terminating code + setToBlack(buffer, lineOffset, bitOffset, code); + bitOffset += code; + + updatePointer(4 - bits); + isWhite = true; + currChangingElems[changingElemSize++] = bitOffset; + } + } + + // Check whether this run completed one width + if (bitOffset == w) { + if (compression == 2) { + advancePointer(); + } + break; + } + } + + currChangingElems[changingElemSize++] = bitOffset; + } + + // Two-dimensional decoding methods + + public void decode2D(byte[] buffer, + byte compData[], + int startX, + int height, + long tiffT4Options) { + this.data = compData; + compression = 3; + + bitPointer = 0; + bytePointer = 0; + + int scanlineStride = (w + 7)/8; + + int a0, a1, b1, b2; + int[] b = new int[2]; + int entry, code, bits; + boolean isWhite; + int currIndex = 0; + int temp[]; + + // fillBits - dealt with this in readEOL + // 1D/2D encoding - dealt with this in readEOL + + // uncompressedMode - haven't dealt with this yet. + + + oneD = (int)(tiffT4Options & 0x01); + uncompressedMode = (int)((tiffT4Options & 0x02) >> 1); + fillBits = (int)((tiffT4Options & 0x04) >> 2); + + // The data must start with an EOL code + if (readEOL(true) != 1) { + throw new RuntimeException("First scanline must be 1D encoded."); + } + + int lineOffset = 0; + int bitOffset; + + // Then the 1D encoded scanline data will occur, changing elements + // array gets set. + decodeNextScanline(buffer, lineOffset, startX); + lineOffset += scanlineStride; + + for (int lines = 1; lines < height; lines++) { + + // Every line must begin with an EOL followed by a bit which + // indicates whether the following scanline is 1D or 2D encoded. + if (readEOL(false) == 0) { + // 2D encoded scanline follows + + // Initialize previous scanlines changing elements, and + // initialize current scanline's changing elements array + temp = prevChangingElems; + prevChangingElems = currChangingElems; + currChangingElems = temp; + currIndex = 0; + + // a0 has to be set just before the start of this scanline. + a0 = -1; + isWhite = true; + bitOffset = startX; + + lastChangingElement = 0; + + while (bitOffset < w) { + // Get the next changing element + getNextChangingElement(a0, isWhite, b); + + b1 = b[0]; + b2 = b[1]; + + // Get the next seven bits + entry = nextLesserThan8Bits(7); + + // Run these through the 2DCodes table + entry = (int)(twoDCodes[entry] & 0xff); + + // Get the code and the number of bits used up + code = (entry & 0x78) >>> 3; + bits = entry & 0x07; + + if (code == 0) { + if (!isWhite) { + setToBlack(buffer, lineOffset, bitOffset, + b2 - bitOffset); + } + bitOffset = a0 = b2; + + // Set pointer to consume the correct number of bits. + updatePointer(7 - bits); + } else if (code == 1) { + // Horizontal + updatePointer(7 - bits); + + // identify the next 2 codes. + int number; + if (isWhite) { + number = decodeWhiteCodeWord(); + bitOffset += number; + currChangingElems[currIndex++] = bitOffset; + + number = decodeBlackCodeWord(); + setToBlack(buffer, lineOffset, bitOffset, number); + bitOffset += number; + currChangingElems[currIndex++] = bitOffset; + } else { + number = decodeBlackCodeWord(); + setToBlack(buffer, lineOffset, bitOffset, number); + bitOffset += number; + currChangingElems[currIndex++] = bitOffset; + + number = decodeWhiteCodeWord(); + bitOffset += number; + currChangingElems[currIndex++] = bitOffset; + } + + a0 = bitOffset; + } else if (code <= 8) { + // Vertical + a1 = b1 + (code - 5); + + currChangingElems[currIndex++] = a1; + + // We write the current color till a1 - 1 pos, + // since a1 is where the next color starts + if (!isWhite) { + setToBlack(buffer, lineOffset, bitOffset, + a1 - bitOffset); + } + bitOffset = a0 = a1; + isWhite = !isWhite; + + updatePointer(7 - bits); + } else { + throw new RuntimeException("Invalid code encountered while decoding 2D group 3 compressed data."); + } + } + + // Add the changing element beyond the current scanline for the + // other color too + currChangingElems[currIndex++] = bitOffset; + changingElemSize = currIndex; + } else { + // 1D encoded scanline follows + decodeNextScanline(buffer, lineOffset, startX); + } + + lineOffset += scanlineStride; + } + } + + public synchronized void decodeT6(byte[] buffer, + byte[] compData, + int startX, + int height, + long tiffT6Options) { + this.data = compData; + compression = 4; + + bitPointer = 0; + bytePointer = 0; + + int scanlineStride = (w + 7)/8; + + int a0, a1, b1, b2; + int entry, code, bits; + boolean isWhite; + int currIndex; + int temp[]; + + // Return values from getNextChangingElement + int[] b = new int[2]; + + // uncompressedMode - have written some code for this, but this + // has not been tested due to lack of test images using this optional + + uncompressedMode = (int)((tiffT6Options & 0x02) >> 1); + + // Local cached reference + int[] cce = currChangingElems; + + // Assume invisible preceding row of all white pixels and insert + // both black and white changing elements beyond the end of this + // imaginary scanline. + changingElemSize = 0; + cce[changingElemSize++] = w; + cce[changingElemSize++] = w; + + int lineOffset = 0; + int bitOffset; + + for (int lines = 0; lines < height; lines++) { + // a0 has to be set just before the start of the scanline. + a0 = -1; + isWhite = true; + + // Assign the changing elements of the previous scanline to + // prevChangingElems and start putting this new scanline's + // changing elements into the currChangingElems. + temp = prevChangingElems; + prevChangingElems = currChangingElems; + cce = currChangingElems = temp; + currIndex = 0; + + // Start decoding the scanline at startX in the raster + bitOffset = startX; + + // Reset search start position for getNextChangingElement + lastChangingElement = 0; + + // Till one whole scanline is decoded + while (bitOffset < w) { + // Get the next changing element + getNextChangingElement(a0, isWhite, b); + b1 = b[0]; + b2 = b[1]; + + // Get the next seven bits + entry = nextLesserThan8Bits(7); + // Run these through the 2DCodes table + entry = (int)(twoDCodes[entry] & 0xff); + + // Get the code and the number of bits used up + code = (entry & 0x78) >>> 3; + bits = entry & 0x07; + + if (code == 0) { // Pass + // We always assume WhiteIsZero format for fax. + if (!isWhite) { + setToBlack(buffer, lineOffset, bitOffset, + b2 - bitOffset); + } + bitOffset = a0 = b2; + + // Set pointer to only consume the correct number of bits. + updatePointer(7 - bits); + } else if (code == 1) { // Horizontal + // Set pointer to only consume the correct number of bits. + updatePointer(7 - bits); + + // identify the next 2 alternating color codes. + int number; + if (isWhite) { + // Following are white and black runs + number = decodeWhiteCodeWord(); + bitOffset += number; + cce[currIndex++] = bitOffset; + + number = decodeBlackCodeWord(); + setToBlack(buffer, lineOffset, bitOffset, number); + bitOffset += number; + cce[currIndex++] = bitOffset; + } else { + // First a black run and then a white run follows + number = decodeBlackCodeWord(); + setToBlack(buffer, lineOffset, bitOffset, number); + bitOffset += number; + cce[currIndex++] = bitOffset; + + number = decodeWhiteCodeWord(); + bitOffset += number; + cce[currIndex++] = bitOffset; + } + + a0 = bitOffset; + } else if (code <= 8) { // Vertical + a1 = b1 + (code - 5); + cce[currIndex++] = a1; + + // We write the current color till a1 - 1 pos, + // since a1 is where the next color starts + if (!isWhite) { + setToBlack(buffer, lineOffset, bitOffset, + a1 - bitOffset); + } + bitOffset = a0 = a1; + isWhite = !isWhite; + + updatePointer(7 - bits); + } else if (code == 11) { + if (nextLesserThan8Bits(3) != 7) { + throw new RuntimeException("Invalid code encountered while decoding 2D group 4 compressed data."); + } + + int zeros = 0; + boolean exit = false; + + while (!exit) { + while (nextLesserThan8Bits(1) != 1) { + zeros++; + } + + if (zeros > 5) { + // Exit code + + // Zeros before exit code + zeros = zeros - 6; + + if (!isWhite && (zeros > 0)) { + cce[currIndex++] = bitOffset; + } + + // Zeros before the exit code + bitOffset += zeros; + if (zeros > 0) { + // Some zeros have been written + isWhite = true; + } + + // Read in the bit which specifies the color of + // the following run + if (nextLesserThan8Bits(1) == 0) { + if (!isWhite) { + cce[currIndex++] = bitOffset; + } + isWhite = true; + } else { + if (isWhite) { + cce[currIndex++] = bitOffset; + } + isWhite = false; + } + + exit = true; + } + + if (zeros == 5) { + if (!isWhite) { + cce[currIndex++] = bitOffset; + } + bitOffset += zeros; + + // Last thing written was white + isWhite = true; + } else { + bitOffset += zeros; + + cce[currIndex++] = bitOffset; + setToBlack(buffer, lineOffset, bitOffset, 1); + ++bitOffset; + + // Last thing written was black + isWhite = false; + } + + } + } else { + throw new RuntimeException("Invalid code encountered while decoding 2D group 4 compressed data."); + } + } + + // Add the changing element beyond the current scanline for the + // other color too + //make sure that the index does not exceed the bounds of the array + if(currIndex < cce.length) + cce[currIndex++] = bitOffset; + + // Number of changing elements in this scanline. + changingElemSize = currIndex; + + lineOffset += scanlineStride; + } + } + + private void setToBlack(byte[] buffer, + int lineOffset, int bitOffset, + int numBits) { + int bitNum = 8*lineOffset + bitOffset; + int lastBit = bitNum + numBits; + + int byteNum = bitNum >> 3; + + // Handle bits in first byte + int shift = bitNum & 0x7; + if (shift > 0) { + int maskVal = 1 << (7 - shift); + byte val = buffer[byteNum]; + while (maskVal > 0 && bitNum < lastBit) { + val |= maskVal; + maskVal >>= 1; + ++bitNum; + } + buffer[byteNum] = val; + } + + // Fill in 8 bits at a time + byteNum = bitNum >> 3; + while (bitNum < lastBit - 7) { + buffer[byteNum++] = (byte)255; + bitNum += 8; + } + + // Fill in remaining bits + while (bitNum < lastBit) { + byteNum = bitNum >> 3; + buffer[byteNum] |= 1 << (7 - (bitNum & 0x7)); + ++bitNum; + } + } + + // Returns run length + private int decodeWhiteCodeWord() { + int current, entry, bits, isT, twoBits, code = -1; + int runLength = 0; + boolean isWhite = true; + + while (isWhite) { + current = nextNBits(10); + entry = white[current]; + + // Get the 3 fields from the entry + isT = entry & 0x0001; + bits = (entry >>> 1) & 0x0f; + + if (bits == 12) { // Additional Make up code + // Get the next 2 bits + twoBits = nextLesserThan8Bits(2); + // Consolidate the 2 new bits and last 2 bits into 4 bits + current = ((current << 2) & 0x000c) | twoBits; + entry = additionalMakeup[current]; + bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 + code = (entry >>> 4) & 0x0fff; // 12 bits + runLength += code; + updatePointer(4 - bits); + } else if (bits == 0) { // ERROR + throw new RuntimeException("Invalid code encountered."); + } else if (bits == 15) { // EOL + throw new RuntimeException("EOL code word encountered in White run."); + } else { + // 11 bits - 0000 0111 1111 1111 = 0x07ff + code = (entry >>> 5) & 0x07ff; + runLength += code; + updatePointer(10 - bits); + if (isT == 0) { + isWhite = false; + } + } + } + + return runLength; + } + + // Returns run length + private int decodeBlackCodeWord() { + int current, entry, bits, isT, code = -1; + int runLength = 0; + boolean isWhite = false; + + while (!isWhite) { + current = nextLesserThan8Bits(4); + entry = initBlack[current]; + + // Get the 3 fields from the entry + isT = entry & 0x0001; + bits = (entry >>> 1) & 0x000f; + code = (entry >>> 5) & 0x07ff; + + if (code == 100) { + current = nextNBits(9); + entry = black[current]; + + // Get the 3 fields from the entry + isT = entry & 0x0001; + bits = (entry >>> 1) & 0x000f; + code = (entry >>> 5) & 0x07ff; + + if (bits == 12) { + // Additional makeup codes + updatePointer(5); + current = nextLesserThan8Bits(4); + entry = additionalMakeup[current]; + bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 + code = (entry >>> 4) & 0x0fff; // 12 bits + runLength += code; + + updatePointer(4 - bits); + } else if (bits == 15) { + // EOL code + throw new RuntimeException("EOL code word encountered in Black run."); + } else { + runLength += code; + updatePointer(9 - bits); + if (isT == 0) { + isWhite = true; + } + } + } else if (code == 200) { + // Is a Terminating code + current = nextLesserThan8Bits(2); + entry = twoBitBlack[current]; + code = (entry >>> 5) & 0x07ff; + runLength += code; + bits = (entry >>> 1) & 0x0f; + updatePointer(2 - bits); + isWhite = true; + } else { + // Is a Terminating code + runLength += code; + updatePointer(4 - bits); + isWhite = true; + } + } + + return runLength; + } + + private int readEOL(boolean isFirstEOL) { + if (fillBits == 0) { + int next12Bits = nextNBits(12); + if (isFirstEOL && next12Bits == 0) { + + // Might have the case of EOL padding being used even + // though it was not flagged in the T4Options field. + // This was observed to be the case in TIFFs produced + // by a well known vendor who shall remain nameless. + + if(nextNBits(4) == 1) { + + // EOL must be padded: reset the fillBits flag. + + fillBits = 1; + return 1; + } + } + if(next12Bits != 1) { + throw new RuntimeException("Scanline must begin with EOL code word."); + } + } else if (fillBits == 1) { + + // First EOL code word xxxx 0000 0000 0001 will occur + // As many fill bits will be present as required to make + // the EOL code of 12 bits end on a byte boundary. + + int bitsLeft = 8 - bitPointer; + + if (nextNBits(bitsLeft) != 0) { + throw new RuntimeException("All fill bits preceding EOL code must be 0."); + } + + // If the number of bitsLeft is less than 8, then to have a 12 + // bit EOL sequence, two more bytes are certainly going to be + // required. The first of them has to be all zeros, so ensure + // that. + if (bitsLeft < 4) { + if (nextNBits(8) != 0) { + throw new RuntimeException("All fill bits preceding EOL code must be 0."); + } + } + + // There might be a random number of fill bytes with 0s, so + // loop till the EOL of 0000 0001 is found, as long as all + // the bytes preceding it are 0's. + int n; + while ((n = nextNBits(8)) != 1) { + + // If not all zeros + if (n != 0) { + throw new RuntimeException("All fill bits preceding EOL code must be 0."); + } + } + } + + // If one dimensional encoding mode, then always return 1 + if (oneD == 0) { + return 1; + } else { + // Otherwise for 2D encoding mode, + // The next one bit signifies 1D/2D encoding of next line. + return nextLesserThan8Bits(1); + } + } + + private void getNextChangingElement(int a0, boolean isWhite, int[] ret) { + // Local copies of instance variables + int[] pce = this.prevChangingElems; + int ces = this.changingElemSize; + + // If the previous match was at an odd element, we still + // have to search the preceeding element. + // int start = lastChangingElement & ~0x1; + int start = lastChangingElement > 0 ? lastChangingElement - 1 : 0; + if (isWhite) { + start &= ~0x1; // Search even numbered elements + } else { + start |= 0x1; // Search odd numbered elements + } + + int i = start; + for (; i < ces; i += 2) { + int temp = pce[i]; + if (temp > a0) { + lastChangingElement = i; + ret[0] = temp; + break; + } + } + + if (i + 1 < ces) { + ret[1] = pce[i + 1]; + } + } + + private int nextNBits(int bitsToGet) { + byte b, next, next2next; + int l = data.length - 1; + int bp = this.bytePointer; + + if (fillOrder == 1) { + b = data[bp]; + + if (bp == l) { + next = 0x00; + next2next = 0x00; + } else if ((bp + 1) == l) { + next = data[bp + 1]; + next2next = 0x00; + } else { + next = data[bp + 1]; + next2next = data[bp + 2]; + } + } else if (fillOrder == 2) { + b = flipTable[data[bp] & 0xff]; + + if (bp == l) { + next = 0x00; + next2next = 0x00; + } else if ((bp + 1) == l) { + next = flipTable[data[bp + 1] & 0xff]; + next2next = 0x00; + } else { + next = flipTable[data[bp + 1] & 0xff]; + next2next = flipTable[data[bp + 2] & 0xff]; + } + } else { + throw new RuntimeException("TIFF_FILL_ORDER tag must be either 1 or 2."); + } + + int bitsLeft = 8 - bitPointer; + int bitsFromNextByte = bitsToGet - bitsLeft; + int bitsFromNext2NextByte = 0; + if (bitsFromNextByte > 8) { + bitsFromNext2NextByte = bitsFromNextByte - 8; + bitsFromNextByte = 8; + } + + bytePointer++; + + int i1 = (b & table1[bitsLeft]) << (bitsToGet - bitsLeft); + int i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte); + + int i3 = 0; + if (bitsFromNext2NextByte != 0) { + i2 <<= bitsFromNext2NextByte; + i3 = (next2next & table2[bitsFromNext2NextByte]) >>> + (8 - bitsFromNext2NextByte); + i2 |= i3; + bytePointer++; + bitPointer = bitsFromNext2NextByte; + } else { + if (bitsFromNextByte == 8) { + bitPointer = 0; + bytePointer++; + } else { + bitPointer = bitsFromNextByte; + } + } + + int i = i1 | i2; + return i; + } + + private int nextLesserThan8Bits(int bitsToGet) { + byte b, next; + int l = data.length - 1; + int bp = this.bytePointer; + + if (fillOrder == 1) { + b = data[bp]; + if (bp == l) { + next = 0x00; + } else { + next = data[bp + 1]; + } + } else if (fillOrder == 2) { + b = flipTable[data[bp] & 0xff]; + if (bp == l) { + next = 0x00; + } else { + next = flipTable[data[bp + 1] & 0xff]; + } + } else { + throw new RuntimeException("TIFF_FILL_ORDER tag must be either 1 or 2."); + } + + int bitsLeft = 8 - bitPointer; + int bitsFromNextByte = bitsToGet - bitsLeft; + + int shift = bitsLeft - bitsToGet; + int i1, i2; + if (shift >= 0) { + i1 = (b & table1[bitsLeft]) >>> shift; + bitPointer += bitsToGet; + if (bitPointer == 8) { + bitPointer = 0; + bytePointer++; + } + } else { + i1 = (b & table1[bitsLeft]) << (-shift); + i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte); + + i1 |= i2; + bytePointer++; + bitPointer = bitsFromNextByte; + } + + return i1; + } + + // Move pointer backwards by given amount of bits + private void updatePointer(int bitsToMoveBack) { + int i = bitPointer - bitsToMoveBack; + + if (i < 0) { + bytePointer--; + bitPointer = 8 + i; + } else { + bitPointer = i; + } + } + + // Move to the next byte boundary + private boolean advancePointer() { + if (bitPointer != 0) { + bytePointer++; + bitPointer = 0; + } + + return true; + } +} + -- cgit v1.2.3