package uk.co.mmscomputing.imageio.tiff; import java.io.*; import java.awt.image.*; import javax.imageio.stream.*; import uk.co.mmscomputing.io.BitSwapInputStream; import uk.co.mmscomputing.io.LZWInputStream; import uk.co.mmscomputing.io.PackBitsInputStream; import uk.co.mmscomputing.io.ModHuffmanInputStream; import uk.co.mmscomputing.io.RLEBitInputStream; import uk.co.mmscomputing.io.InvertedInputStream; import uk.co.mmscomputing.io.IntFilterInputStream; import uk.co.mmscomputing.io.RGBInputStream; import uk.co.mmscomputing.imageio.jpeg.*; // [1] Adobe TIFF6.pdf /* Read: Black & White : base line : no compression, modified huffman, packbits + lzw [1] p.57ff Gray 4 & 8 bit: base line : no compression, packbits, jpeg(7)(8bit grayscale) + lzw [1] p.57ff Palette Color 4 & 8 bit: base line : no compression, packbits + lzw [1] p.57ff RGB : 888 rgb images : no compression, packbits, lzw, jpeg(7) YCbCr : 888 YCbCr images : no compression, packbits, lzw */ public class TIFFBaselineFactory implements TIFFConstants{ static final private String cn="uk.co.mmscomputing.imageio.tiff.TIFFBaselineFactory"; static final private String email="\nPlease send this tiff file to mm@mms-computing.co.uk."; static final private IndexColorModel bwwhiteiszero; static final private IndexColorModel bwblackiszero; static final private IndexColorModel graywhiteiszero; static final private IndexColorModel grayblackiszero; static public BufferedImage readImage(ImageInputStream in,IFD ifd)throws IOException{ int phmi=ifd.getPhotometricInterpretation(); int spp =ifd.getSamplesPerPixel(); int bps =ifd.getBitsPerSample(0); int pc =ifd.getPlanarConfiguration(); if(pc!=1){ System.out.println("9\b"+cn+".readImage:\n\tDo only support Planar Configuration 1."+email); return null; } if(ifd.getSampleFormat()!=1){ System.out.println("9\b"+cn+".readImage:\n\tDo not support sample format other than unsigned integer."+email); return null; } // todo: check for tile width & length => don't support tiles // System.err.println(" phmi = "+phmi+" bps = "+bps); switch(phmi){ case WhiteIsZero: if(spp==1){ switch(bps){ case 1: return readBWImage(in,ifd,bwwhiteiszero); case 4: return read4bitImage(in,ifd,graywhiteiszero); case 8: return readGray8bitImage(in,ifd,true); } } break; case BlackIsZero: if(spp==1){ switch(bps){ case 1: return readBWImage(in,ifd,bwblackiszero); case 4: return read4bitImage(in,ifd,grayblackiszero); case 8: return readGray8bitImage(in,ifd,false); } } break; case RGB: if(spp>=3){ for(int i=0;i>3)*rps,max=((width+7)>>3)*height; for(int i=0;i>3];int len=0; while(true){ rlis.resetToStartCodeWord(); // start next line with white try{ len=rlis.read(buf); // read one image line if(len==-1){break;} // end of page System.arraycopy(buf,0,imgdata,off,len); // copy line to image buffer mhis.skipPadding(8); // skip bits up until next byte boundary }catch(ModHuffmanInputStream.ModHuffmanCodingException mhce){ System.out.println(cn+".copyin:\n\t"+mhce); } off+=len; } }else{ byte[] buf=new byte[(width+7)>>3];int len=0,ecw=8-(width&0x0007),bits; while(true){ rlis.resetToStartCodeWord(); // start next line with white try{ len=rlis.read(buf,0,buf.length-1); // read one image line if(len==-1){break;} // end of page bits=rlis.readBits(7,ecw); buf[len]=(byte)bits; System.arraycopy(buf,0,imgdata,off,len+1); // copy line to image buffer mhis.skipPadding(8); // skip bits up until next byte boundary }catch(ModHuffmanInputStream.ModHuffmanCodingException mhce){ System.out.println(cn+".copyin:\n\t"+mhce); } off+=len+1; } } return off; } static private BufferedImage read4bitImage(ImageInputStream in,IFD ifd,IndexColorModel cm)throws IOException{ BufferedImage image=null; try{ int width =ifd.getWidth(); int height =ifd.getHeight(); int cmp =ifd.getCompression(); image=new BufferedImage(width,height,BufferedImage.TYPE_BYTE_BINARY,cm); WritableRaster raster=image.getRaster(); DataBufferByte buffer=(DataBufferByte)raster.getDataBuffer(); byte[] imgdata=(byte[])buffer.getData(); long[] offsets =ifd.getStripOffsets(); long[] counts =ifd.getStripByteCounts(); int rps =ifd.getRowsPerStrip(); int predictor=ifd.getPredictor(); if(predictor!=1){ // does any program use this ? System.out.println("9\b"+cn+".read4bitImage:\n\tDo not support 'Differencing Predictor' yet."); return image; } int offset=0,mbps=((width+1)>>1)*rps,max=((width+1)>>1)*height; // two 4-bit pixel per byte for(int i=0;i0){ if((spp-3)==esl){ // if last sample is alpha data alpha=ifd.getExtraSample(esl-1); // [1] p.77 : 1 = Associated alpha data (with pre-multiplied color) }else{ System.out.println("9\b"+cn+".readRGBImage:\n\tInvalid TIFF file. 'Samples per Pixel' != ('Extra Samples' + 3)."); } } switch(alpha){ case 1: image=new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB_PRE); case 2: image=new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB); default: image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); } WritableRaster raster=image.getRaster(); DataBufferInt buffer=(DataBufferInt)raster.getDataBuffer(); int[] imgdata=(int[])buffer.getData(); long[] offsets =ifd.getStripOffsets(); long[] counts =ifd.getStripByteCounts(); int rps =ifd.getRowsPerStrip(); int predictor=ifd.getPredictor(); if(predictor!=1){ System.out.println("9\b"+cn+".readRGBImage:\n\tDo not support 'Differencing Predictor' yet."+email); return image; } JPEGInputStream tables; try{ tables = new JPEGInputStream(new ByteArrayInputStream(ifd.getJPEGTables())); }catch(IllegalArgumentException iae){ tables=null; } IntFilterInputStream intis; int offset=0,mbps=width*rps,max=width*height; for(int i=0;i=0;i-=17){ byte b=(byte)i; System.out.print(""+b+","); } }catch(Exception e){ System.out.println(e); } } }