/* * 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.fr.third.JAI; class TIFFFaxEncoder { /** * The CCITT numerical definition of white. */ private static final int WHITE = 0; /** * The CCITT numerical definition of black. */ private static final int BLACK = 1; // --- Begin tables for CCITT compression --- private static byte[] byteTable = new byte[] { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, // 0 to 15 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16 to 31 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 32 to 47 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 48 to 63 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 to 79 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 to 95 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 to 111 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 112 to 127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128 to 143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144 to 159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160 to 175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176 to 191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192 to 207 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208 to 223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224 to 239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 240 to 255 }; /** * Terminating codes for black runs. */ private static int[] termCodesBlack = new int[] { /* 0 0x0000 */ 0x0dc0000a, 0x40000003, 0xc0000002, 0x80000002, /* 4 0x0004 */ 0x60000003, 0x30000004, 0x20000004, 0x18000005, /* 8 0x0008 */ 0x14000006, 0x10000006, 0x08000007, 0x0a000007, /* 12 0x000c */ 0x0e000007, 0x04000008, 0x07000008, 0x0c000009, /* 16 0x0010 */ 0x05c0000a, 0x0600000a, 0x0200000a, 0x0ce0000b, /* 20 0x0014 */ 0x0d00000b, 0x0d80000b, 0x06e0000b, 0x0500000b, /* 24 0x0018 */ 0x02e0000b, 0x0300000b, 0x0ca0000c, 0x0cb0000c, /* 28 0x001c */ 0x0cc0000c, 0x0cd0000c, 0x0680000c, 0x0690000c, /* 32 0x0020 */ 0x06a0000c, 0x06b0000c, 0x0d20000c, 0x0d30000c, /* 36 0x0024 */ 0x0d40000c, 0x0d50000c, 0x0d60000c, 0x0d70000c, /* 40 0x0028 */ 0x06c0000c, 0x06d0000c, 0x0da0000c, 0x0db0000c, /* 44 0x002c */ 0x0540000c, 0x0550000c, 0x0560000c, 0x0570000c, /* 48 0x0030 */ 0x0640000c, 0x0650000c, 0x0520000c, 0x0530000c, /* 52 0x0034 */ 0x0240000c, 0x0370000c, 0x0380000c, 0x0270000c, /* 56 0x0038 */ 0x0280000c, 0x0580000c, 0x0590000c, 0x02b0000c, /* 60 0x003c */ 0x02c0000c, 0x05a0000c, 0x0660000c, 0x0670000c }; /** * Terminating codes for white runs. */ private static int[] termCodesWhite = new int[] { /* 0 0x0000 */ 0x35000008, 0x1c000006, 0x70000004, 0x80000004, /* 4 0x0004 */ 0xb0000004, 0xc0000004, 0xe0000004, 0xf0000004, /* 8 0x0008 */ 0x98000005, 0xa0000005, 0x38000005, 0x40000005, /* 12 0x000c */ 0x20000006, 0x0c000006, 0xd0000006, 0xd4000006, /* 16 0x0010 */ 0xa8000006, 0xac000006, 0x4e000007, 0x18000007, /* 20 0x0014 */ 0x10000007, 0x2e000007, 0x06000007, 0x08000007, /* 24 0x0018 */ 0x50000007, 0x56000007, 0x26000007, 0x48000007, /* 28 0x001c */ 0x30000007, 0x02000008, 0x03000008, 0x1a000008, /* 32 0x0020 */ 0x1b000008, 0x12000008, 0x13000008, 0x14000008, /* 36 0x0024 */ 0x15000008, 0x16000008, 0x17000008, 0x28000008, /* 40 0x0028 */ 0x29000008, 0x2a000008, 0x2b000008, 0x2c000008, /* 44 0x002c */ 0x2d000008, 0x04000008, 0x05000008, 0x0a000008, /* 48 0x0030 */ 0x0b000008, 0x52000008, 0x53000008, 0x54000008, /* 52 0x0034 */ 0x55000008, 0x24000008, 0x25000008, 0x58000008, /* 56 0x0038 */ 0x59000008, 0x5a000008, 0x5b000008, 0x4a000008, /* 60 0x003c */ 0x4b000008, 0x32000008, 0x33000008, 0x34000008 }; /** * Make-up codes for black runs. */ private static int[] makeupCodesBlack = new int[] { /* 0 0x0000 */ 0x00000000, 0x03c0000a, 0x0c80000c, 0x0c90000c, /* 4 0x0004 */ 0x05b0000c, 0x0330000c, 0x0340000c, 0x0350000c, /* 8 0x0008 */ 0x0360000d, 0x0368000d, 0x0250000d, 0x0258000d, /* 12 0x000c */ 0x0260000d, 0x0268000d, 0x0390000d, 0x0398000d, /* 16 0x0010 */ 0x03a0000d, 0x03a8000d, 0x03b0000d, 0x03b8000d, /* 20 0x0014 */ 0x0290000d, 0x0298000d, 0x02a0000d, 0x02a8000d, /* 24 0x0018 */ 0x02d0000d, 0x02d8000d, 0x0320000d, 0x0328000d, /* 28 0x001c */ 0x0100000b, 0x0180000b, 0x01a0000b, 0x0120000c, /* 32 0x0020 */ 0x0130000c, 0x0140000c, 0x0150000c, 0x0160000c, /* 36 0x0024 */ 0x0170000c, 0x01c0000c, 0x01d0000c, 0x01e0000c, /* 40 0x0028 */ 0x01f0000c, 0x00000000, 0x00000000, 0x00000000, /* 44 0x002c */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 48 0x0030 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 52 0x0034 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 56 0x0038 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; /** * Make-up codes for white runs. */ private static int[] makeupCodesWhite = new int[] { /* 0 0x0000 */ 0x00000000, 0xd8000005, 0x90000005, 0x5c000006, /* 4 0x0004 */ 0x6e000007, 0x36000008, 0x37000008, 0x64000008, /* 8 0x0008 */ 0x65000008, 0x68000008, 0x67000008, 0x66000009, /* 12 0x000c */ 0x66800009, 0x69000009, 0x69800009, 0x6a000009, /* 16 0x0010 */ 0x6a800009, 0x6b000009, 0x6b800009, 0x6c000009, /* 20 0x0014 */ 0x6c800009, 0x6d000009, 0x6d800009, 0x4c000009, /* 24 0x0018 */ 0x4c800009, 0x4d000009, 0x60000006, 0x4d800009, /* 28 0x001c */ 0x0100000b, 0x0180000b, 0x01a0000b, 0x0120000c, /* 32 0x0020 */ 0x0130000c, 0x0140000c, 0x0150000c, 0x0160000c, /* 36 0x0024 */ 0x0170000c, 0x01c0000c, 0x01d0000c, 0x01e0000c, /* 40 0x0028 */ 0x01f0000c, 0x00000000, 0x00000000, 0x00000000, /* 44 0x002c */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 48 0x0030 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 52 0x0034 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 56 0x0038 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; /** * Pass mode table. */ private static int[] passMode = new int[] { 0x10000004 // 0001 }; /** * Vertical mode table. */ private static int[] vertMode = new int[] { 0x06000007, // 0000011 0x0c000006, // 000011 0x60000003, // 011 0x80000001, // 1 0x40000003, // 010 0x08000006, // 000010 0x04000007 // 0000010 }; /** * Horizontal mode table. */ private static int[] horzMode = new int[] { 0x20000003 // 001 }; /** * Black and white terminating code table. */ private static int[][] termCodes = new int[][] {termCodesWhite, termCodesBlack}; /** * Black and white make-up code table. */ private static int[][] makeupCodes = new int[][] {makeupCodesWhite, makeupCodesBlack}; /** * Black and white pass mode table. */ private static int[][] pass = new int[][] {passMode, passMode}; /** * Black and white vertical mode table. */ private static int[][] vert = new int[][] {vertMode, vertMode}; /** * Black and white horizontal mode table. */ private static int[][] horz = new int[][] {horzMode, horzMode}; // --- End tables for CCITT compression --- /** * Whether bits are inserted in reverse order (TIFF FillOrder 2). */ private boolean inverseFill; /** * Output bit buffer. */ private int bits; /** * Number of bits in the output bit buffer. */ private int ndex; /** * Constructs a TIFFFaxEncoder for CCITT bilevel encoding. * * @param inverseFill Whether bits are inserted in reverse order * (TIFF FillOrder 2). */ TIFFFaxEncoder(boolean inverseFill) { this.inverseFill = inverseFill; } /** * Return min of maxOffset or offset of first pixel * different from pixel at bitOffset. */ private int nextState(byte[] data, int base, int bitOffset, int maxOffset) { if(data == null) { return maxOffset; } int next = base + (bitOffset>>>3); int end = base + (maxOffset>>>3) - 1; int extra = bitOffset & 0x7; int testbyte; if((data[next] & (0x80 >>> extra)) != 0) { // look for "0" testbyte = ~(data[next]) & (0xff >>> extra); while (next < end) { if (testbyte != 0) { break; } testbyte = ~(data[++next]) & 0xff; } } else { // look for "1" if ((testbyte = (data[next] & (0xff >>> extra))) != 0) { bitOffset = (next-base)*8 + byteTable[testbyte]; return ((bitOffset < maxOffset) ? bitOffset : maxOffset); } while (next < end) { if ((testbyte = data[++next]&0xff) != 0) { // "1" is in current byte bitOffset = (next-base)*8 + byteTable[testbyte]; return ((bitOffset < maxOffset) ? bitOffset : maxOffset); } } } bitOffset = (next-base)*8 + byteTable[testbyte]; return ((bitOffset < maxOffset) ? bitOffset : maxOffset); } /** * Initialize bit buffer machinery. */ private void initBitBuf() { ndex = 0; bits = 0x00000000; } /** * Get code for run and add to compressed bitstream. */ private int add1DBits(byte[] buf, int where, // byte offs int count, // #pixels in run int color) // color of run { int sixtyfours; int mask; int len = where; sixtyfours = count >>> 6; // count / 64; count = count & 0x3f; // count % 64 if (sixtyfours != 0) { for ( ; sixtyfours > 40; sixtyfours -= 40) { mask = makeupCodes[color][40]; bits |= (mask & 0xfff80000) >>> ndex; ndex += (int)(mask & 0x0000ffff); while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } } mask = makeupCodes[color][sixtyfours]; bits |= (mask & 0xfff80000) >>> ndex; ndex += (int)(mask & 0x0000ffff); while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } } mask = termCodes[color][count]; bits |= (mask & 0xfff80000) >>> ndex; ndex += (int)(mask & 0x0000ffff); while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } return(len - where); } /** * Place entry from mode table into compressed bitstream. */ private int add2DBits(byte[] buf, // compressed buffer int where, // byte offset into compressed buffer int[][] mode, // 2-D mode to be encoded int entry) // mode entry (0 unless vertical) { int mask; int len = where; int color = 0; mask = mode[color][entry]; bits |= (mask & 0xfff80000) >>> ndex; ndex += (int)(mask & 0x0000ffff); while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } return(len - where); } /** * Add an End-of-Line (EOL == 0x001) to the compressed bitstream * with optional byte alignment. */ private int addEOL(boolean is1DMode,// 1D encoding boolean addFill, // byte aligned EOLs boolean add1, // add1 ? EOL+1 : EOL+0 byte[] buf, // compressed buffer address int where) // current byte offset into buffer { int len = where; // // Add zero-valued fill bits such that the EOL is aligned as // // xxxx 0000 0000 0001 // if(addFill) { // // Simply increment the bit count. No need to feed bits into // the output buffer at this point as there are at most 7 bits // in the bit buffer, at most 7 are added here, and at most // 13 below making the total 7+7+13 = 27 before the bit feed // at the end of this routine. // ndex += ((ndex <= 4) ? 4 - ndex : 12 - ndex); } // // Write EOL into buffer // if(is1DMode) { bits |= 0x00100000 >>> ndex; ndex += 12; } else { bits |= (add1 ? 0x00180000 : 0x00100000) >>> ndex; ndex += 13; } while (ndex > 7) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } return(len - where); } /** * Add an End-of-Facsimile-Block (EOFB == 0x001001) to the compressed * bitstream. */ private int addEOFB(byte[] buf, // compressed buffer int where) // byte offset into compressed buffer { int len = where; // // eofb code // bits |= 0x00100100 >>> ndex; // // eofb code length // ndex += 24; // // flush all pending bits // while(ndex > 0) { buf[len++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } return(len - where); } /** * One-dimensionally encode a row of data using CCITT Huffman compression. * The bit buffer should be initialized as required before invoking this * method and should be flushed after the method returns. The fill order * is always highest-order to lowest-order bit so the calling routine * should handle bit inversion. */ private int encode1D(byte[] data, int rowOffset, int colOffset, int rowLength, byte[] compData, int compOffset) { int lineAddr = rowOffset; int bitIndex = colOffset; int last = bitIndex + rowLength; int outIndex = compOffset; // // Is first pixel black // int testbit = ((data[lineAddr + (bitIndex>>>3)]&0xff) >>> (7-(bitIndex & 0x7))) & 0x1; int currentColor = BLACK; if(testbit != 0) { outIndex += add1DBits(compData, outIndex, 0, WHITE); } else { currentColor = WHITE; } // // Run-length encode line // while(bitIndex < last) { int bitCount = nextState(data, lineAddr, bitIndex, last) - bitIndex; outIndex += add1DBits(compData, outIndex, bitCount, currentColor); bitIndex += bitCount; currentColor ^= 0x00000001; } return outIndex - compOffset; } /** * Encode a row of data using Modified Huffman Compression also known as * CCITT RLE (Run Lenth Encoding). * * @param data The row of data to compress. * @param rowOffset Starting index in data. * @param colOffset Bit offset within first data[rowOffset]. * @param rowLength Number of bits in the row. * @param compData The compressed data. * * @return The number of bytes saved in the compressed data array. */ synchronized int encodeRLE(byte[] data, int rowOffset, int colOffset, int rowLength, byte[] compData) { // // Initialize bit buffer machinery. // initBitBuf(); // // Run-length encode line. // int outIndex = encode1D(data, rowOffset, colOffset, rowLength, compData, 0); // // Flush pending bits // while(ndex > 0) { compData[outIndex++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } // // Flip the bytes if inverse fill was requested. // if(inverseFill) { byte[] flipTable = TIFFFaxDecoder.flipTable; for(int i = 0; i < outIndex; i++) { compData[i] = flipTable[compData[i]&0xff]; } } return outIndex; } /** * Encode a buffer of data using CCITT T.4 Compression also known as * Group 3 facsimile compression. * * @param is1DMode Whether to perform one-dimensional encoding. * @param isEOLAligned Whether EOL bit sequences should be padded. * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. * @param colOffset Bit offset within first data[rowOffset]. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. * * @return The number of bytes saved in the compressed data array. */ synchronized int encodeT4(boolean is1DMode, boolean isEOLAligned, byte[] data, int lineStride, int colOffset, int width, int height, byte[] compData) { // // ao, a1, a2 are bit indices in the current line // b1 and b2 are bit indices in the reference line (line above) // color is the current color (WHITE or BLACK) // byte[] refData = data; int lineAddr = 0; int outIndex = 0; initBitBuf(); int KParameter = 2; for(int numRows = 0; numRows < height; numRows++) { if(is1DMode || (numRows % KParameter) == 0) { // 1D encoding // Write EOL+1 outIndex += addEOL(is1DMode, isEOLAligned, true, compData, outIndex); // Encode row outIndex += encode1D(data, lineAddr, colOffset, width, compData, outIndex); } else { // 2D encoding. // Write EOL+0 outIndex += addEOL(is1DMode, isEOLAligned, false, compData, outIndex); // Set reference to previous line int refAddr = lineAddr - lineStride; // Encode row int a0 = colOffset; int last = a0 + width; int testbit = ((data[lineAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; int a1 = testbit != 0 ? a0 : nextState(data, lineAddr, a0, last); testbit = ((refData[refAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; int b1 = testbit != 0 ? a0 : nextState(refData, refAddr, a0, last); // The current color is set to WHITE at line start int color = WHITE; while(true) { int b2 = nextState(refData, refAddr, b1, last); if(b2 < a1) { // pass mode outIndex += add2DBits(compData, outIndex, pass, 0); a0 = b2; } else { int tmp = b1 - a1 + 3; if((tmp <= 6) && (tmp >= 0)) { // vertical mode outIndex += add2DBits(compData, outIndex, vert, tmp); a0 = a1; } else { // horizontal mode int a2 = nextState(data, lineAddr, a1, last); outIndex += add2DBits(compData, outIndex, horz, 0); outIndex += add1DBits(compData, outIndex, a1-a0, color); outIndex += add1DBits(compData, outIndex, a2-a1, color^1); a0 = a2; } } if(a0 >= last) { break; } color = ((data[lineAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; a1 = nextState(data, lineAddr, a0, last); b1 = nextState(refData, refAddr, a0, last); testbit = ((refData[refAddr + (b1>>>3)]&0xff) >>> (7-(b1 & 0x7))) & 0x1; if(testbit == color) { b1 = nextState(refData, refAddr, b1, last); } } } // Skip to next line. lineAddr += lineStride; } for(int i = 0; i < 6; i++) { outIndex += addEOL(is1DMode, isEOLAligned, true, compData, outIndex); } // // flush all pending bits // while(ndex > 0) { compData[outIndex++] = (byte)(bits >>> 24); bits <<= 8; ndex -= 8; } // Flip the bytes if inverse fill was requested. if(inverseFill) { for(int i = 0; i < outIndex; i++) { compData[i] = TIFFFaxDecoder.flipTable[compData[i]&0xff]; } } return outIndex; } /** * Encode a buffer of data using CCITT T.6 Compression also known as * Group 4 facsimile compression. * * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. * @param colOffset Bit offset within first data[rowOffset]. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. * * @return The number of bytes saved in the compressed data array. */ public synchronized int encodeT6(byte[] data, int lineStride, int colOffset, int width, int height, byte[] compData) { // // ao, a1, a2 are bit indices in the current line // b1 and b2 are bit indices in the reference line (line above) // color is the current color (WHITE or BLACK) // byte[] refData = null; int refAddr = 0; int lineAddr = 0; int outIndex = 0; initBitBuf(); // // Iterate over all lines // while(height-- != 0) { int a0 = colOffset; int last = a0 + width; int testbit = ((data[lineAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; int a1 = testbit != 0 ? a0 : nextState(data, lineAddr, a0, last); testbit = refData == null ? 0: ((refData[refAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; int b1 = testbit != 0 ? a0 : nextState(refData, refAddr, a0, last); // // The current color is set to WHITE at line start // int color = WHITE; while(true) { int b2 = nextState(refData, refAddr, b1, last); if(b2 < a1) { // pass mode outIndex += add2DBits(compData, outIndex, pass, 0); a0 = b2; } else { int tmp = b1 - a1 + 3; if((tmp <= 6) && (tmp >= 0)) { // vertical mode outIndex += add2DBits(compData, outIndex, vert, tmp); a0 = a1; } else { // horizontal mode int a2 = nextState(data, lineAddr, a1, last); outIndex += add2DBits(compData, outIndex, horz, 0); outIndex += add1DBits(compData, outIndex, a1-a0, color); outIndex += add1DBits(compData, outIndex, a2-a1, color^1); a0 = a2; } } if(a0 >= last) { break; } color = ((data[lineAddr + (a0>>>3)]&0xff) >>> (7-(a0 & 0x7))) & 0x1; a1 = nextState(data, lineAddr, a0, last); b1 = nextState(refData, refAddr, a0, last); testbit = refData == null ? 0: ((refData[refAddr + (b1>>>3)]&0xff) >>> (7-(b1 & 0x7))) & 0x1; if(testbit == color) { b1 = nextState(refData, refAddr, b1, last); } } refData = data; refAddr = lineAddr; lineAddr += lineStride; } // End while(height--) // // append eofb // outIndex += addEOFB(compData, outIndex); // Flip the bytes if inverse fill was requested. if(inverseFill) { for(int i = 0; i < outIndex; i++) { compData[i] = TIFFFaxDecoder.flipTable[compData[i]&0xff]; } } return outIndex; } }