All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jaiimageio.impl.plugins.tiff.TIFFFaxDecompressor Maven / Gradle / Ivy

Go to download

Java Advanced Imaging Image I/O Tools API core, but without the classes involved with javax.media.jai dependencies, JPEG2000 or codecLibJIIO, meaning that this library can be distributed under the modified BSD license and should be GPL compatible.

The newest version!
/*
 * $RCSfile: TIFFFaxDecompressor.java,v $
 *
 * 
 * Copyright (c) 2005 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: 
 * 
 * - Redistribution of source code must retain the above copyright 
 *   notice, this  list of conditions and the following disclaimer.
 * 
 * - Redistribution in binary form must reproduce 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 MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
 * USING, MODIFYING OR DISTRIBUTING THIS 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 THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES. 
 * 
 * You acknowledge that this software is not designed or intended for 
 * use in the design, construction, operation or maintenance of any 
 * nuclear facility. 
 *
 * $Revision: 1.15 $
 * $Date: 2007/08/31 23:17:28 $
 * $State: Exp $
 */
package com.github.jaiimageio.impl.plugins.tiff;

import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.PrintStream;

import javax.imageio.IIOException;

import com.github.jaiimageio.plugins.tiff.BaselineTIFFTagSet;
import com.github.jaiimageio.plugins.tiff.TIFFDecompressor;
import com.github.jaiimageio.plugins.tiff.TIFFField;

public class TIFFFaxDecompressor extends TIFFDecompressor {

    /**
     * The logical order of bits within a byte.
     * 
     * 1 = MSB-to-LSB
     * 2 = LSB-to-MSB (flipped)
     * 
*/ protected int fillOrder; protected int compression; private int t4Options; private int t6Options; // Variables set by T4Options /** * Uncompressed mode flag: 1 if uncompressed, 0 if not. */ protected int uncompressedMode = 0; /** * EOL padding flag: 1 if fill bits have been added before an EOL such * that the EOL ends on a byte boundary, 0 otherwise. */ protected int fillBits = 0; /** * Coding dimensionality: 1 for 2-dimensional, 0 for 1-dimensional. */ protected int oneD; private byte[] data; private int bitPointer, bytePointer; // Output image buffer private byte[] buffer; private int w, h, bitsPerScanline; private int lineBitNum; // 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; 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, }; public TIFFFaxDecompressor() {} /** * Invokes the superclass method and then sets instance variables on * the basis of the metadata set on this decompressor. */ public void beginDecoding() { super.beginDecoding(); if(metadata instanceof TIFFImageMetadata) { TIFFImageMetadata tmetadata = (TIFFImageMetadata)metadata; TIFFField f; f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER); this.fillOrder = f == null ? 1 : f.getAsInt(0); f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION); this.compression = f == null ? BaselineTIFFTagSet.COMPRESSION_CCITT_RLE : f.getAsInt(0); f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_T4_OPTIONS); this.t4Options = f == null ? 0 : f.getAsInt(0); this.oneD = (int)(t4Options & 0x01); // uncompressedMode - haven't dealt with this yet. this.uncompressedMode = (int)((t4Options & 0x02) >> 1); this.fillBits = (int)((t4Options & 0x04) >> 2); f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_T6_OPTIONS); this.t6Options = f == null ? 0 : f.getAsInt(0); } else { this.fillOrder = 1; // MSB-to-LSB this.compression = BaselineTIFFTagSet.COMPRESSION_CCITT_RLE; // RLE this.t4Options = 0; // Irrelevant as applies to T.4 only this.oneD = 0; // One-dimensional this.uncompressedMode = 0; // Not uncompressed mode this.fillBits = 0; // No fill bits this.t6Options = 0; } } public void decodeRaw(byte[] b, int dstOffset, int pixelBitStride, // will always be 1 int scanlineStride) throws IOException { this.buffer = b; this.w = srcWidth; this.h = srcHeight; this.bitsPerScanline = scanlineStride*8; this.lineBitNum = 8*dstOffset; this.data = new byte[(int)byteCount]; this.bitPointer = 0; this.bytePointer = 0; this.prevChangingElems = new int[w + 1]; this.currChangingElems = new int[w + 1]; stream.seek(offset); stream.readFully(data); try { if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE) { decodeRLE(); } else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) { decodeT4(); } else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) { this.uncompressedMode = (int)((t6Options & 0x02) >> 1); decodeT6(); } else { throw new IIOException("Unknown compression type " + compression); } } catch(ArrayIndexOutOfBoundsException e) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); e.printStackTrace(new PrintStream(baos)); String s = new String(baos.toByteArray()); warning("Ignoring exception:\n "+s); } } public void decodeRLE() throws IIOException { for (int i = 0; i < h; i++) { // Decode the line. decodeNextScanline(srcMinY + i); // Advance to the next byte boundary if not already there. if (bitPointer != 0) { bytePointer++; bitPointer = 0; } // Update the total number of bits. lineBitNum += bitsPerScanline; } } public void decodeNextScanline(int lineIndex) throws IIOException { int bits = 0, code = 0, isT = 0; int current, entry, twoBits; boolean isWhite = true; int dstEnd = 0; int bitOffset = 0; // Initialize starting of the changing elements array changingElemSize = 0; // While scanline not complete while (bitOffset < w) { // Mark start of white run. int runOffset = bitOffset; while (isWhite && bitOffset < w) { // 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 warning("Error 0"); // XXX return? } else if (bits == 15) { // EOL // // Instead of throwing an exception, assume that the // EOL was premature; emit a warning and return. // warning("Premature EOL in white run of line "+lineIndex+ ": read "+bitOffset+" of "+w+" expected pixels."); return; } 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 (bitOffset == w) { // If the white run has not been terminated then ensure that // the next code word is a terminating code for a white run // of length zero. int runLength = bitOffset - runOffset; if(isWhite && runLength != 0 && runLength % 64 == 0 && nextNBits(8) != 0x35) { warning("Missing zero white run length terminating code!"); updatePointer(8); } break; } // Mark start of black run. runOffset = bitOffset; while (isWhite == false && bitOffset < w) { // 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(bitOffset, code); bitOffset += code; updatePointer(4 - bits); } else if (bits == 15) { // // Instead of throwing an exception, assume that the // EOL was premature; emit a warning and return. // warning("Premature EOL in black run of line "+ lineIndex+": read "+bitOffset+" of "+w+ " expected pixels."); return; } else { setToBlack(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(bitOffset, code); bitOffset += code; updatePointer(2 - bits); isWhite = true; currChangingElems[changingElemSize++] = bitOffset; } else { // Is a Terminating code setToBlack(bitOffset, code); bitOffset += code; updatePointer(4 - bits); isWhite = true; currChangingElems[changingElemSize++] = bitOffset; } } // Check whether this run completed one width if (bitOffset == w) { // If the black run has not been terminated then ensure that // the next code word is a terminating code for a black run // of length zero. int runLength = bitOffset - runOffset; if(!isWhite && runLength != 0 && runLength % 64 == 0 && nextNBits(10) != 0x37) { warning("Missing zero black run length terminating code!"); updatePointer(10); } break; } } currChangingElems[changingElemSize++] = bitOffset; } public void decodeT4() throws IIOException { int height = h; int a0, a1, b1, b2; int[] b = new int[2]; int entry, code, bits, color; boolean isWhite; int currIndex = 0; int temp[]; if(data.length < 2) { throw new IIOException("Insufficient data to read initial EOL."); } // The data should start with an EOL code int next12 = nextNBits(12); if(next12 != 1) { warning("T.4 compressed data should begin with EOL."); } updatePointer(12); // Find the first one-dimensionally encoded line. int modeFlag = 0; int lines = -1; // indicates imaginary line before first actual line. while(modeFlag != 1) { try { modeFlag = findNextLine(); lines++; // Normally 'lines' will be 0 on exiting loop. } catch(EOFException eofe) { throw new IIOException("No reference line present."); } } int bitOffset; // Then the 1D encoded scanline data will occur, changing elements // array gets set. decodeNextScanline(srcMinY); lines++; lineBitNum += bitsPerScanline; while(lines < height) { // Every line must begin with an EOL followed by a bit which // indicates whether the following scanline is 1D or 2D encoded. try { modeFlag = findNextLine(); } catch(EOFException eofe) { warning("Input exhausted before EOL found at line "+ (srcMinY+lines)+": read 0 of "+w+" expected pixels."); break; } if(modeFlag == 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 = 0; 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(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(bitOffset, number); bitOffset += number; currChangingElems[currIndex++] = bitOffset; } else { number = decodeBlackCodeWord(); setToBlack(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(bitOffset, a1 - bitOffset); } bitOffset = a0 = a1; isWhite = !isWhite; updatePointer(7 - bits); } else { warning("Unknown coding mode encountered at line "+ (srcMinY+lines)+": read "+bitOffset+" of "+w+ " expected pixels."); // Find the next one-dimensionally encoded line. int numLinesTested = 0; while(modeFlag != 1) { try { modeFlag = findNextLine(); numLinesTested++; } catch(EOFException eofe) { warning("Sync loss at line "+ (srcMinY+lines)+": read "+ lines+" of "+height+" lines."); return; } } lines += numLinesTested - 1; updatePointer(13); break; } } // Add the changing element beyond the current scanline for the // other color too currChangingElems[currIndex++] = bitOffset; changingElemSize = currIndex; } else { // modeFlag == 1 // 1D encoded scanline follows decodeNextScanline(srcMinY+lines); } lineBitNum += bitsPerScanline; lines++; } // while(lines < height) } public synchronized void decodeT6() throws IIOException { int height = h; int bufferOffset = 0; int a0, a1, b1, b2; int entry, code, bits; byte color; 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 // extension. This code is when code == 11. aastha 03/03/1999 // 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 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 bitOffset = 0; // 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) { if(b2 > w) { b2 = w; warning("Decoded row "+(srcMinY+lines)+ " too long; ignoring extra samples."); } setToBlack(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(); if(number > w - bitOffset) { number = w - bitOffset; warning("Decoded row "+(srcMinY+lines)+ " too long; ignoring extra samples."); } setToBlack(bitOffset, number); bitOffset += number; cce[currIndex++] = bitOffset; } else { // First a black run and then a white run follows number = decodeBlackCodeWord(); if(number > w - bitOffset) { number = w - bitOffset; warning("Decoded row "+(srcMinY+lines)+ " too long; ignoring extra samples."); } setToBlack(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) { if(a1 > w) { a1 = w; warning("Decoded row "+(srcMinY+lines)+ " too long; ignoring extra samples."); } setToBlack(bitOffset, a1 - bitOffset); } bitOffset = a0 = a1; isWhite = !isWhite; updatePointer(7 - bits); } else if (code == 11) { int entranceCode = nextLesserThan8Bits(3); if (entranceCode != 7) { String msg = "Unsupported entrance code "+entranceCode+ " for extension mode at line "+(srcMinY+lines)+"."; warning(msg); } 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(bitOffset, 1); ++bitOffset; // Last thing written was black isWhite = false; } } } else { String msg = "Unknown coding mode encountered at line "+ (srcMinY+lines)+"."; warning(msg); } } // while bitOffset < w // Add the changing element beyond the current scanline for the // other color too, if not already added previously if (currIndex <= w) cce[currIndex++] = bitOffset; // Number of changing elements in this scanline. changingElemSize = currIndex; lineBitNum += bitsPerScanline; } // for lines < height } private void setToBlack(int bitNum, int numBits) { // bitNum is relative to current scanline so bump it by lineBitNum bitNum += lineBitNum; 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() throws IIOException { 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 IIOException("Error 0"); } else if (bits == 15) { // EOL throw new IIOException("Error 1"); } 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() throws IIOException { int current, entry, bits, isT, twoBits, 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 IIOException("Error 2"); } 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 findNextLine() throws IIOException, EOFException { // Set maximum and current bit index into the compressed data. int bitIndexMax = data.length*8 - 1; int bitIndexMax12 = bitIndexMax - 12; int bitIndex = bytePointer*8 + bitPointer; // Loop while at least 12 bits are available. while(bitIndex <= bitIndexMax12) { // Get the next 12 bits. int next12Bits = nextNBits(12); bitIndex += 12; // Loop while the 12 bits are not unity, i.e., while the EOL // has not been reached, and there is at least one bit left. while(next12Bits != 1 && bitIndex < bitIndexMax) { next12Bits = ((next12Bits & 0x000007ff) << 1) | (nextLesserThan8Bits(1) & 0x00000001); bitIndex++; } if(next12Bits == 1) { // now positioned just after EOL if(oneD == 1) { // two-dimensional coding if(bitIndex < bitIndexMax) { // check next bit against type of line being sought return nextLesserThan8Bits(1); } } else { return 1; } } } // EOL not found. throw new EOFException(); } private void getNextChangingElement(int a0, boolean isWhite, int[] ret) throws IIOException { // 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) throws IIOException { 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 IIOException("Invalid FillOrder"); } 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) throws IIOException { 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 IIOException("Invalid FillOrder"); } 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) { if (bitsToMoveBack > 8) { bytePointer -= bitsToMoveBack/8; bitsToMoveBack %= 8; } int i = bitPointer - bitsToMoveBack; if (i < 0) { bytePointer--; bitPointer = 8 + i; } else { bitPointer = i; } } // Forward warning message to reader private void warning(String msg) { if(this.reader instanceof TIFFImageReader) { ((TIFFImageReader)reader).forwardWarningMessage(msg); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy