001/* 002 * $RCSfile: TIFFT6Compressor.java,v $ 003 * 004 * 005 * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without 008 * modification, are permitted provided that the following conditions 009 * are met: 010 * 011 * - Redistribution of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * 014 * - Redistribution in binary form must reproduce the above copyright 015 * notice, this list of conditions and the following disclaimer in 016 * the documentation and/or other materials provided with the 017 * distribution. 018 * 019 * Neither the name of Sun Microsystems, Inc. or the names of 020 * contributors may be used to endorse or promote products derived 021 * from this software without specific prior written permission. 022 * 023 * This software is provided "AS IS," without a warranty of any 024 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 025 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 026 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY 027 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 028 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 029 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS 030 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 031 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, 032 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND 033 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR 034 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE 035 * POSSIBILITY OF SUCH DAMAGES. 036 * 037 * You acknowledge that this software is not designed or intended for 038 * use in the design, construction, operation or maintenance of any 039 * nuclear facility. 040 * 041 * $Revision: 1.3 $ 042 * $Date: 2006/04/11 22:10:37 $ 043 * $State: Exp $ 044 */ 045package com.github.jaiimageio.impl.plugins.tiff; 046 047import com.github.jaiimageio.plugins.tiff.BaselineTIFFTagSet; 048import com.github.jaiimageio.plugins.tiff.TIFFCompressor; 049import com.github.jaiimageio.plugins.tiff.TIFFField; 050import com.github.jaiimageio.plugins.tiff.TIFFTag; 051 052import java.io.IOException; 053 054import javax.imageio.IIOException; 055 056/** 057 * 058 */ 059public class TIFFT6Compressor extends TIFFFaxCompressor { 060 061 public TIFFT6Compressor() { 062 super("CCITT T.6", BaselineTIFFTagSet.COMPRESSION_CCITT_T_6, true); 063 } 064 065 /** 066 * Encode a buffer of data using CCITT T.6 Compression also known as 067 * Group 4 facsimile compression. 068 * 069 * @param data The row of data to compress. 070 * @param lineStride Byte step between the same sample in different rows. 071 * @param colOffset Bit offset within first <code>data[rowOffset]</code>. 072 * @param width Number of bits in the row. 073 * @param height Number of rows in the buffer. 074 * @param compData The compressed data. 075 * 076 * @return The number of bytes saved in the compressed data array. 077 */ 078 public synchronized int encodeT6(byte[] data, 079 int lineStride, 080 int colOffset, 081 int width, 082 int height, 083 byte[] compData) 084 { 085 // 086 // ao, a1, a2 are bit indices in the current line 087 // b1 and b2 are bit indices in the reference line (line above) 088 // color is the current color (WHITE or BLACK) 089 // 090 byte[] refData = null; 091 int refAddr = 0; 092 int lineAddr = 0; 093 int outIndex = 0; 094 095 initBitBuf(); 096 097 // 098 // Iterate over all lines 099 // 100 while(height-- != 0) { 101 int a0 = colOffset; 102 int last = a0 + width; 103 104 int testbit = 105 ((data[lineAddr + (a0>>>3)]&0xff) >>> 106 (7-(a0 & 0x7))) & 0x1; 107 int a1 = testbit != 0 ? 108 a0 : nextState(data, lineAddr, a0, last); 109 110 testbit = refData == null ? 111 0: ((refData[refAddr + (a0>>>3)]&0xff) >>> 112 (7-(a0 & 0x7))) & 0x1; 113 int b1 = testbit != 0 ? 114 a0 : nextState(refData, refAddr, a0, last); 115 116 // 117 // The current color is set to WHITE at line start 118 // 119 int color = WHITE; 120 121 while(true) { 122 int b2 = nextState(refData, refAddr, b1, last); 123 if(b2 < a1) { // pass mode 124 outIndex += add2DBits(compData, outIndex, pass, 0); 125 a0 = b2; 126 } else { 127 int tmp = b1 - a1 + 3; 128 if((tmp <= 6) && (tmp >= 0)) { // vertical mode 129 outIndex += add2DBits(compData, outIndex, vert, tmp); 130 a0 = a1; 131 } else { // horizontal mode 132 int a2 = nextState(data, lineAddr, a1, last); 133 outIndex += add2DBits(compData, outIndex, horz, 0); 134 outIndex += add1DBits(compData, outIndex, a1-a0, color); 135 outIndex += add1DBits(compData, outIndex, a2-a1, color^1); 136 a0 = a2; 137 } 138 } 139 if(a0 >= last) { 140 break; 141 } 142 color = ((data[lineAddr + (a0>>>3)]&0xff) >>> 143 (7-(a0 & 0x7))) & 0x1; 144 a1 = nextState(data, lineAddr, a0, last); 145 b1 = nextState(refData, refAddr, a0, last); 146 testbit = refData == null ? 147 0: ((refData[refAddr + (b1>>>3)]&0xff) >>> 148 (7-(b1 & 0x7))) & 0x1; 149 if(testbit == color) { 150 b1 = nextState(refData, refAddr, b1, last); 151 } 152 } 153 154 refData = data; 155 refAddr = lineAddr; 156 lineAddr += lineStride; 157 158 } // End while(height--) 159 160 // 161 // append eofb 162 // 163 outIndex += addEOFB(compData, outIndex); 164 165 // Flip the bytes if inverse fill was requested. 166 if(inverseFill) { 167 for(int i = 0; i < outIndex; i++) { 168 compData[i] = TIFFFaxDecompressor.flipTable[compData[i]&0xff]; 169 } 170 } 171 172 return outIndex; 173 } 174 175 public int encode(byte[] b, int off, 176 int width, int height, 177 int[] bitsPerSample, 178 int scanlineStride) throws IOException { 179 if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) { 180 throw new IIOException( 181 "Bits per sample must be 1 for T6 compression!"); 182 } 183 184 185 if (metadata instanceof TIFFImageMetadata) { 186 TIFFImageMetadata tim = (TIFFImageMetadata)metadata; 187 188 long[] options = new long[1]; 189 options[0] = 0; 190 191 BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance(); 192 TIFFField T6Options = 193 new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_T6_OPTIONS), 194 TIFFTag.TIFF_LONG, 195 1, 196 options); 197 tim.rootIFD.addTIFFField(T6Options); 198 } 199 200 // See comment in TIFFT4Compressor 201 int maxBits = 9*((width + 1)/2) + 2; 202 int bufSize = (maxBits + 7)/8; 203 bufSize = height*(bufSize + 2) + 12; 204 205 byte[] compData = new byte[bufSize]; 206 int bytes = encodeT6(b, scanlineStride, 8*off, width, height, 207 compData); 208 stream.write(compData, 0, bytes); 209 return bytes; 210 } 211}