diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/gnu/javax/imageio/png | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/gnu/javax/imageio/png')
15 files changed, 2625 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGChunk.java b/libjava/classpath/gnu/javax/imageio/png/PNGChunk.java new file mode 100644 index 000000000..ade0999fe --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGChunk.java @@ -0,0 +1,283 @@ +/* PNGChunk.java -- Generic PNG chunk + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +/** + * Class to load and validate a generic PNG chunk. + */ +public class PNGChunk +{ + + /** + * CRC table and initialization code. + */ + private static long[] crcTable; + + static + { + long c; + crcTable = new long[256]; + + for(int i = 0; i < 256; i++) + { + c = i; + for(int j = 0; j < 8; j++) + if( (c & 1) == 1 ) + c = 0xEDB88320L ^ (c >> 1); + else + c = c >> 1; + crcTable[i] = c; + } + } + + /** + * (recognized) PNG chunk types. + */ + public static final int TYPE_HEADER = 0x49484452; // 'IHDR' + public static final int TYPE_PALETTE = 0x504c5445;// 'PLTE' + public static final int TYPE_DATA = 0x49444154; // 'IDAT' + public static final int TYPE_TIME = 0x74494d45; // 'tIME' + public static final int TYPE_END = 0x49454e44; // 'IEND' + public static final int TYPE_PHYS = 0x70485973; // 'pHYS' + public static final int TYPE_GAMMA = 0x67414d41; // 'gAMA' + public static final int TYPE_PROFILE = 0x69434350; // 'iCCP' + + /** + * The chunk type - Represented in the file as 4 ASCII bytes, + */ + private int type; + + /** + * The chunk data + */ + protected byte[] data; + + /** + * The chunk's crc + */ + private int crc; + + /** + * Constructor for reading a generic chunk. + */ + protected PNGChunk( int type, byte[] data, int crc ) + { + this.type = type; + this.data = data; + this.crc = crc; + } + + /** + * Constructor for creating new chunks. + * (only used by subclasses - creating a generic chunk is rather useless) + */ + protected PNGChunk( int type ) + { + this.type = type; + } + + /** + * Loads a chunk from an InputStream. Does not perform validation, + * but will throw an IOException if the read fails. + * @param in - th einputstream to read from + * @param strict - if true, a PNGException is thrown on all invalid chunks, + * if false, only critical chunks will throw PNGExceptions. + */ + public static PNGChunk readChunk(InputStream in, boolean strict) + throws IOException, PNGException + { + byte data[] = new byte[4]; + if( in.read( data ) != 4 ) + throw new IOException("Could not read chunk length."); + int length = ((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + + if( in.read( data ) != 4 ) + throw new IOException("Could not read chunk type."); + int type = ((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + + byte[] chkdata = new byte[ length ]; + if( in.read( chkdata ) != length ) + throw new IOException("Could not read chunk data."); + + if( in.read( data ) != 4 ) + throw new IOException("Could not read chunk CRC."); + + int crc = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + + if( strict ) + return getChunk( type, chkdata, crc ); + else + { + try + { + return getChunk( type, chkdata, crc ); + } + catch(PNGException pnge) + { + if( isEssentialChunk( type ) ) + throw pnge; + return null; + } + } + } + + /** + * Returns a specialied object for a chunk, if we have one. + */ + private static PNGChunk getChunk( int type, byte[] data, int crc ) + throws PNGException + { + switch( type ) + { + case TYPE_HEADER: + return new PNGHeader( type, data, crc ); + case TYPE_DATA: + return new PNGData( type, data, crc ); + case TYPE_PALETTE: + return new PNGPalette( type, data, crc ); + case TYPE_TIME: + return new PNGTime( type, data, crc ); + case TYPE_PHYS: + return new PNGPhys( type, data, crc ); + case TYPE_GAMMA: + return new PNGGamma( type, data, crc ); + case TYPE_PROFILE: + return new PNGICCProfile( type, data, crc ); + default: + return new PNGChunk( type, data, crc ); + } + } + + /** + * Returns whether the chunk is essential or not + */ + private static boolean isEssentialChunk( int type ) + { + switch( type ) + { + case TYPE_HEADER: + case TYPE_DATA: + case TYPE_PALETTE: + case TYPE_END: + return true; + default: + return false; + } + } + + /** + * Validates the chunk + */ + public boolean isValidChunk() + { + return (crc == calcCRC()); + } + + /** + * Returns the chunk type. + */ + public int getType() + { + return type; + } + + /** + * Writes a PNG chunk to an output stream, + * performing the CRC calculation as well. + */ + public void writeChunk(OutputStream out) throws IOException + { + out.write( getInt(data.length) ); + out.write( getInt(type) ); + out.write( data ); + out.write( getInt(calcCRC()) ); + } + + /** + * Return whether the chunk contains any data. + */ + public boolean isEmpty() + { + return ( data.length == 0 ); + } + + /** + * Convenience method. Cast an int to four bytes (big endian). + * (Now why doesn't java have a simple way of doing this?) + */ + public static byte[] getInt(int intValue) + { + long i = (intValue & 0xFFFFFFFFL); + byte[] b = new byte[4]; + b[0] = (byte)((i & 0xFF000000L) >> 24); + b[1] = (byte)((i & 0x00FF0000L) >> 16); + b[2] = (byte)((i & 0x0000FF00L) >> 8); + b[3] = (byte)(i & 0x000000FFL); + return b; + } + + /** + * Calculates this chunk's CRC value. + */ + private int calcCRC() + { + long c = 0xFFFFFFFFL; + byte[] t = getInt( type ); + for(int i = 0; i < 4; i++) + c = crcTable[ (int)((c ^ t[i]) & 0xFF) ] ^ (c >> 8); + + for(int i = 0; i < data.length; i++) + c = crcTable[ (int)((c ^ data[i]) & 0xFF) ] ^ (c >> 8); + + return (int)(c ^ 0xFFFFFFFFL); + } + + public String toString() + { + return "PNG Chunk. Type: " + new String( getInt(type) ) + " , CRC: " + + crc + " , calculated CRC: "+calcCRC(); + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGData.java b/libjava/classpath/gnu/javax/imageio/png/PNGData.java new file mode 100644 index 000000000..08d765f66 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGData.java @@ -0,0 +1,104 @@ +/* PNGData.java -- PNG IDAT chunk. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.util.zip.Inflater; +import java.util.zip.Deflater; + +/** + * A PNG IDAT (data) chunk. + */ +public class PNGData extends PNGChunk +{ + private int offset; + + protected PNGData( int type, byte[] data, int crc ) + { + super( type, data, crc ); + } + + protected PNGData( int chunkSize ) + { + super( PNGChunk.TYPE_DATA ); + data = new byte[ chunkSize ]; + offset = 0; + } + + /** + * Deflates the available data in def to the chunk. + * + * @return true if the chunk is filled and no more data can be written, + * false otherwise. + */ + public void deflateToChunk( Deflater def ) + { + offset += def.deflate( data, offset, data.length - offset ); + } + + /** + * Returns true if the chunk is filled. + */ + public boolean chunkFull() + { + return (offset >= data.length); + } + + /** + * Shrink the chunk to offset size, used for the last chunk in a stream + * (no trailing data!) + */ + public void shrink() + { + byte[] newData = new byte[ offset ]; + System.arraycopy( data, 0, newData, 0, offset ); + data = newData; + } + + /** + * Feeds the data in the chunk to a ZIP inflater object. + */ + public void feedToInflater( Inflater inf ) + { + inf.setInput( data ); + } + + public String toString() + { + return "PNG Data chunk. Length = "+data.length; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGDecoder.java b/libjava/classpath/gnu/javax/imageio/png/PNGDecoder.java new file mode 100644 index 000000000..4481107c4 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGDecoder.java @@ -0,0 +1,331 @@ +/* PNGDecoder.java + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.util.zip.Inflater; +import java.util.zip.DataFormatException; +import java.awt.image.ColorModel; +import java.awt.image.ComponentColorModel; +import java.awt.image.ComponentSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferUShort; +import java.awt.image.IndexColorModel; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.Raster; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.WritableRaster; +import java.awt.color.ColorSpace; + +public class PNGDecoder +{ + private PNGHeader header; + private byte[] raster; + private byte[] scanline, lastScanline; + private byte[] filterType; + private int offset, length; + private int currentScanline; + private final int stride; + private Inflater inflater; + private boolean readFilter; + private int bpp; // bytes per pixel + + /** + * Constructs a filter object for + */ + public PNGDecoder(PNGHeader header) + { + this.header = header; + offset = 0; + inflater = new Inflater(); + stride = header.getScanlineStride(); + length = stride * header.getHeight(); + + // Allocate the output raster + raster = new byte[ length ]; + scanline = new byte[ stride ]; + lastScanline = new byte[ stride ]; + currentScanline = 0; + readFilter = true; + bpp = header.bytesPerPixel(); + filterType = new byte[1]; + inflater = new Inflater(); + } + + private int getBytes( byte[] buf, int offset ) throws PNGException + { + try + { + return inflater.inflate( buf, offset, buf.length - offset); + } + catch(DataFormatException dfe) + { + throw new PNGException("Error inflating data."); + } + } + + /** + * Decodes a data chunk. + */ + public void addData( PNGData chunk ) throws PNGException + { + int n = 0; + if( isFinished() ) + return; + chunk.feedToInflater( inflater ); + do + { + if( readFilter ) + if( getBytes( filterType, 0 ) < 1 ) + return; + + n = getBytes( scanline, offset ); + + if( offset + n < stride ) + { + offset += n; + readFilter = false; + } + else + { + scanline = PNGFilter.unFilterScanline( filterType[0], scanline, + lastScanline, bpp ); + System.arraycopy( scanline, 0, + raster, currentScanline * stride, stride ); + lastScanline = scanline; + scanline = new byte[scanline.length]; + currentScanline++; + readFilter = true; + offset = 0; + } + } + while( n > 0 && currentScanline < header.getHeight() ); + } + + /** + * Parse the appropriate color type and create an AWT raster for it. + * @param header - the file header. + */ + public WritableRaster getRaster( PNGHeader header ) + { + SampleModel sm = null; + DataBuffer db = null; + int t; + int width = header.getWidth(); + int height = header.getHeight(); + int depth = header.getDepth(); + + switch( header.getColorType() ) + { + case PNGHeader.GRAYSCALE_WITH_ALPHA: + if( depth == 8 ) + { + t = DataBuffer.TYPE_BYTE; + db = getByteBuffer(); + } + else + { + t = DataBuffer.TYPE_USHORT; + db = getShortBuffer(); + } + sm = new ComponentSampleModel(t, width, height, 2, width * 2, + new int[]{0, 1}); + break; + + case PNGHeader.GRAYSCALE: + switch( depth ) + { + case 16: + sm = new ComponentSampleModel(DataBuffer.TYPE_USHORT, + width, height, 1, width, + new int[]{ 0 }); + db = getShortBuffer(); + break; + + case 8: + sm = new ComponentSampleModel(DataBuffer.TYPE_BYTE, + width, height, 1, width, + new int[]{ 0 }); + db = getByteBuffer(); + break; + + default: + sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, depth); + db = getByteBuffer(); + break; + } + break; + + case PNGHeader.RGB: + if( depth == 8 ) + { + t = DataBuffer.TYPE_BYTE; + db = getByteBuffer(); + } + else + { + t = DataBuffer.TYPE_USHORT; + db = getShortBuffer(); + } + sm = new ComponentSampleModel(t, width, height, 3, 3 * width, + new int[]{0, 1, 2}); + break; + + case PNGHeader.RGB_WITH_ALPHA: + if( depth == 8 ) + { + t = DataBuffer.TYPE_BYTE; + db = getByteBuffer(); + } + else + { + t = DataBuffer.TYPE_USHORT; + db = getShortBuffer(); + } + + sm = new ComponentSampleModel(t, width, height, 4, width * 4, + new int[]{0, 1, 2, 3}); + break; + + case PNGHeader.INDEXED: + if( depth == 8 ) + sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, + new int[] {0xFF}); + else + sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, depth); + db = getByteBuffer(); + break; + } + + return Raster.createWritableRaster(sm, db, null); + } + + /** + * Wrap the raster with a DataBufferUShort, + * conversion is big-endian (PNG native). + */ + private DataBuffer getShortBuffer() + { + short[] data = new short[(raster.length >> 1)]; + for( int i = 0; i < data.length; i++ ) + data[i] = (short)(((raster[i * 2] & 0xFF) << 8) | + (raster[i * 2 + 1] & 0xFF)); + return new DataBufferUShort( data, data.length ); + } + + /** + * Wrap the raster with a DataBufferByte + */ + private DataBuffer getByteBuffer() + { + return new DataBufferByte( raster, raster.length ); + } + + public ColorModel getColorModel( ColorSpace cs, + int colorType, int depth ) + { + int[] bits; + boolean hasAlpha = false; + int transferType; + + switch( colorType ) + { + case PNGHeader.GRAYSCALE_WITH_ALPHA: + if( cs == null ) + cs = ColorSpace.getInstance( ColorSpace.CS_GRAY ); + hasAlpha = true; + bits = new int[]{ depth, depth }; + break; + + case PNGHeader.RGB: + bits = new int[]{ depth, depth, depth }; + break; + + case PNGHeader.RGB_WITH_ALPHA: + hasAlpha = true; + bits = new int[]{ depth, depth, depth, depth }; + break; + + case PNGHeader.GRAYSCALE: + if( depth < 8 ) + return grayPalette( depth ); + + if( cs == null ) + cs = ColorSpace.getInstance( ColorSpace.CS_GRAY ); + bits = new int[]{ depth }; + break; + + default: + case PNGHeader.INDEXED: + return null; // Handled by the palette chunk. + } + + if( cs == null ) + cs = ColorSpace.getInstance( ColorSpace.CS_sRGB ); + + + return new ComponentColorModel(cs, bits, hasAlpha, false, + (hasAlpha ? + ComponentColorModel.TRANSLUCENT : + ComponentColorModel.OPAQUE), + ((depth == 16) ? DataBuffer.TYPE_USHORT : + DataBuffer.TYPE_BYTE)); + } + + private IndexColorModel grayPalette(int depth) + { + byte[] c = new byte[ (1 << depth) ]; + for(int i = 0; i < c.length; i++) + c[i] = (byte)(255.0 * (((double)i) / ((double)c.length - 1.0))); + return new IndexColorModel(8, c.length, c, c, c); + } + + public byte[] getRaster() + { + return raster; + } + + public boolean isFinished() + { + return currentScanline >= header.getHeight(); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGEncoder.java b/libjava/classpath/gnu/javax/imageio/png/PNGEncoder.java new file mode 100644 index 000000000..b31787635 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGEncoder.java @@ -0,0 +1,233 @@ +/* PNGEncoder.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.util.Vector; +import java.util.zip.Deflater; +import java.awt.color.ColorSpace; +import java.awt.color.ICC_ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferUShort; +import java.awt.image.IndexColorModel; +import java.awt.image.WritableRaster; + +public class PNGEncoder +{ + /** + * The default data chunk size. 8 kb. + */ + private static final int defaultChunkSize = 8192; + + private PNGHeader header; + private PNGPalette palette; + private int stride, bpp; + private byte[] rawData; + private PNGICCProfile profile; + + public PNGEncoder( BufferedImage bi ) throws PNGException + { + ColorModel c = bi.getColorModel(); + int width = bi.getWidth(); + int height = bi.getHeight(); + int depth = 0; + int colorType; + boolean interlace = false; + + if( c instanceof IndexColorModel ) + { + colorType = PNGHeader.INDEXED; + int n = ((IndexColorModel)c).getMapSize(); + if( n <= 2 ) + depth = 1; + else if( n <= 4 ) + depth = 2; + else if( n <= 16 ) + depth = 4; + else if( n <= 256 ) + depth = 8; + else + throw new PNGException("Depth must be <= 8 bits for indexed color."); + palette = new PNGPalette( ((IndexColorModel)c) ); + } + else + { + ColorSpace cs = c.getColorSpace(); + ColorSpace grayCS = ColorSpace.getInstance( ColorSpace.CS_GRAY ); + if( cs == grayCS || bi.getType() == BufferedImage.TYPE_BYTE_GRAY + || bi.getType() == BufferedImage.TYPE_USHORT_GRAY ) + colorType = c.hasAlpha() ? PNGHeader.GRAYSCALE_WITH_ALPHA : + PNGHeader.GRAYSCALE; + else + colorType = c.hasAlpha() ? PNGHeader.RGB_WITH_ALPHA : PNGHeader.RGB; + // Figure out the depth + int[] bits = c.getComponentSize(); + depth = bits[0]; + for(int i = 1; i < bits.length; i++ ) + if( bits[i] > depth ) depth = bits[i]; + if( (cs != grayCS && !cs.isCS_sRGB()) && cs instanceof ICC_ColorSpace ) + profile = new PNGICCProfile( ((ICC_ColorSpace)cs).getProfile() ); + } + + header = new PNGHeader(width, height, depth, colorType, interlace); + + stride = header.getScanlineStride(); // scanline stride + bpp = header.bytesPerPixel(); // bytes per pixel + getRawData( bi ); + } + + /** + * Returns the generated header. + */ + public PNGHeader getHeader() + { + return header; + } + + /** + * Returns the generated palette. + */ + public PNGPalette getPalette() + { + return palette; + } + + /** + * Returns the associated ICC profile, if any. + */ + public PNGICCProfile getProfile() + { + return profile; + } + + /** + * Encodes the raster and returns a Vector of PNGData chunks. + */ + public Vector encodeImage() + { + Deflater deflater = new Deflater(); // The deflater + boolean useFilter = PNGFilter.useFilter( header ); + byte[] lastScanline = new byte[ stride ]; + + byte[] data = new byte[ rawData.length + header.getHeight() ]; + + byte filterByte = PNGFilter.FILTER_NONE; + for( int i = 0; i < header.getHeight(); i++) + { + byte[] scanline = new byte[ stride ]; + System.arraycopy(rawData, (i * stride), scanline, 0, stride); + if( useFilter && i > 0) + filterByte = PNGFilter.chooseFilter( scanline, lastScanline, bpp); + + byte[] filtered = PNGFilter.filterScanline( filterByte, scanline, + lastScanline, bpp ); + data[i * (stride + 1)] = filterByte; + System.arraycopy(filtered, 0, data, 1 + (i * (stride + 1)), stride); + + lastScanline = scanline; + } + + deflater.setInput( data ); + deflater.finish(); + + PNGData chunk; + Vector chunks = new Vector(); + do + { + chunk = new PNGData( defaultChunkSize ); + chunk.deflateToChunk( deflater ); + chunks.add( chunk ); + } + while( chunk.chunkFull() ); + chunk.shrink(); // Shrink the last chunk. + return chunks; + } + + /** + * Get the image's raw data. + * FIXME: This may need improving on. + */ + private void getRawData( BufferedImage bi ) throws PNGException + { + WritableRaster raster = bi.getRaster(); + rawData = new byte[ stride * header.getHeight() ]; + if( header.isIndexed() ) + { + DataBuffer db = raster.getDataBuffer(); + if( !( db instanceof DataBufferByte ) ) + throw new PNGException("Unexpected DataBuffer for an IndexColorModel."); + byte[] data = ((DataBufferByte)db).getData(); + for(int i = 0; i < header.getHeight(); i++ ) + System.arraycopy( data, i * stride, rawData, i * stride, stride ); + return; + } + + if( header.getDepth() == 16 ) + { + DataBuffer db = raster.getDataBuffer(); + if( !( db instanceof DataBufferUShort ) ) + throw new PNGException("Unexpected DataBuffer for 16-bit."); + short[] data = ((DataBufferUShort)db).getData(); + for(int i = 0; i < header.getHeight(); i++ ) + for(int j = 0; j < ( stride >> 1); j++) + { + rawData[ j * 2 + i * stride ] = (byte)((data[j + i * (stride >> 1 )] & 0xFF00) >> 8); + rawData[ j * 2 + i * stride + 1 ] = (byte)(data[j + i * (stride >> 1 )] & 0xFF); + } + return; + } + + int size = ( header.getColorType() == PNGHeader.RGB_WITH_ALPHA ) ? 4 : 3; + int width = header.getWidth(); + int height = header.getHeight(); + int[] pixels = bi.getRGB( 0, 0, width, height, null, 0, width ); + + for( int i = 0; i < width * height; i++ ) + { + rawData[ i * size ] = (byte)((pixels[i] & 0xFF0000) >> 16); + rawData[ i * size + 1 ] = (byte)((pixels[i] & 0xFF00) >> 8); + rawData[ i * size + 2 ] = (byte)(pixels[i] & 0xFF); + } + + if( size == 4 ) + for( int i = 0; i < width * height; i++ ) + rawData[ i * size + 3 ] = (byte)((pixels[i] & 0xFF000000) >> 24); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGException.java b/libjava/classpath/gnu/javax/imageio/png/PNGException.java new file mode 100644 index 000000000..ef5342cf8 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGException.java @@ -0,0 +1,48 @@ +/* PNGException.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.io.IOException; + +public class PNGException extends IOException +{ + public PNGException(String msg) + { + super( msg ); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGFile.java b/libjava/classpath/gnu/javax/imageio/png/PNGFile.java new file mode 100644 index 000000000..76154cc66 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGFile.java @@ -0,0 +1,257 @@ +/* PNGFile.java -- High-level representation of a PNG file. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.util.Vector; +import java.awt.image.BufferedImage; +import java.awt.image.WritableRaster; +import java.awt.image.ColorModel; +import java.awt.color.ColorSpace; + +public class PNGFile +{ + /** + * The PNG file signature. + */ + private static final byte[] signature = new byte[] + { (byte)137, 80, 78, 71, 13, 10, 26, 10 }; + + /** + * The end chunk in raw form, no need for anything fancy here, it's just + * 0 bytes of length, the "IEND" tag and its CRC. + */ + private static final byte[] endChunk = new byte[] + { 0, 0, 0, 0, (byte)0x49, (byte)0x45, (byte)0x4E, (byte)0x44, + (byte)0xAE, (byte)0x42, (byte)0x60, (byte)0x82 }; + + /** + * The loaded data. + */ + private Vector chunks; + + /** + * The Header chunk + */ + private PNGHeader header; + + /** + * Whether this file has a palette chunk or not. + */ + private boolean hasPalette; + + /** + * Image width and height. + */ + private int width, height; + + /** + * The decoder, if any. + */ + private PNGDecoder decoder; + + /** + * The encoder, if any. (Either this or the above must exist). + */ + private PNGEncoder encoder; + + /** + * The source of this PNG (if encoding) + */ + private BufferedImage sourceImage; + + /** + * Creates a PNGFile object from an InputStream. + */ + public PNGFile(InputStream in) throws IOException, PNGException + { + PNGChunk chunk; + byte[] fileHdr = new byte[8]; + chunks = new Vector(); + hasPalette = false; + + if( in.read( fileHdr ) != 8 ) + throw new IOException("Could not read file header."); + if( !validateHeader( fileHdr ) ) + throw new PNGException("Invalid file header. Not a PNG file."); + + chunk = PNGChunk.readChunk( in, false ); + if( !(chunk instanceof PNGHeader) ) + throw new PNGException("First chunk not a header chunk."); + header = (PNGHeader)chunk; + if( !header.isValidChunk() ) + throw new PNGException("First chunk not a valid header."); + System.out.println(header); + + decoder = new PNGDecoder( header ); + // Read chunks. + do + { + chunk = PNGChunk.readChunk( in, false ); + /* + * We could exit here or output some kind of warning. + * But in the meantime, we'll just silently drop invalid chunks. + */ + if( chunk.isValidChunk() ) + { + if( chunk instanceof PNGData ) + decoder.addData( (PNGData)chunk ); + else // Silently ignore multiple headers, and use only the first. + if( chunk.getType() != PNGChunk.TYPE_END ) + { + chunks.add( chunk ); + hasPalette |= ( chunk instanceof PNGPalette ); + } + } + else + System.out.println("WARNING: Invalid chunk!"); + } + while( chunk.getType() != PNGChunk.TYPE_END ); + + if( header.isIndexed() && !hasPalette ) + throw new PNGException("File is indexed color and has no palette."); + + width = header.getWidth(); + height = header.getHeight(); + } + + /** + * Creates a PNG file from an existing BufferedImage. + */ + public PNGFile(BufferedImage bi) throws PNGException + { + sourceImage = bi; + width = bi.getWidth(); + height = bi.getHeight(); + chunks = new Vector(); + encoder = new PNGEncoder( bi ); + header = encoder.getHeader(); + if( header.isIndexed() ) + chunks.add( encoder.getPalette() ); + + // Do the compression and put the data chunks in the list. + chunks.addAll( encoder.encodeImage() ); + } + + /** + * Writes a PNG file to an OutputStream + */ + public void writePNG(OutputStream out) throws IOException + { + out.write( signature ); // write the signature. + header.writeChunk( out ); + for( int i = 0; i < chunks.size(); i++ ) + { + PNGChunk chunk = ((PNGChunk)chunks.elementAt(i)); + chunk.writeChunk( out ); + } + out.write( endChunk ); + } + + /** + * Check 8 bytes to see if it's a valid PNG header. + */ + private boolean validateHeader( byte[] hdr ) + { + if( hdr.length != 8 ) + return false; + for( int i = 0; i < 8; i++ ) + if( signature[i] != hdr[i] ) + return false; + return true; + } + + /** + * Return a loaded image as a bufferedimage. + */ + public BufferedImage getBufferedImage() + { + if( decoder == null ) + return sourceImage; + + WritableRaster r = decoder.getRaster( header ); + ColorModel cm; + if( header.isIndexed() ) + { + PNGPalette pngp = getPalette(); + cm = pngp.getPalette( getColorSpace() ); + } + else + cm = decoder.getColorModel( getColorSpace(), + header.getColorType(), + header.getDepth() ); + + return new BufferedImage(cm, r, false, null); + } + + /** + * Find the palette chunk and return it + */ + private PNGPalette getPalette() + { + for(int i = 0; i < chunks.size(); i++ ) + if( chunks.elementAt(i) instanceof PNGPalette ) + return ((PNGPalette)chunks.elementAt(i)); + return null; + } + + /** + * Return the Color space to use, first preference is ICC profile, then + * a gamma chunk, or returns null for the default sRGB. + */ + private ColorSpace getColorSpace() + { + PNGICCProfile icc = null; + PNGGamma gamma = null; + for(int i = 0; i < chunks.size(); i++ ) + { + if( chunks.elementAt(i) instanceof PNGICCProfile ) + icc = ((PNGICCProfile)chunks.elementAt(i)); + else if(chunks.elementAt(i) instanceof PNGGamma ) + gamma = ((PNGGamma)chunks.elementAt(i)); + } + + if( icc != null ) + return icc.getColorSpace(); +// if( gamma != null && !header.isGrayscale()) +// return gamma.getColorSpace( header.isGrayscale() ); + return null; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGFilter.java b/libjava/classpath/gnu/javax/imageio/png/PNGFilter.java new file mode 100644 index 000000000..9be7b9127 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGFilter.java @@ -0,0 +1,237 @@ +/* PNGFilter.java -- PNG image filters. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +/** + * A utility class of static methods implementing the PNG filtering algorithms. + */ +public class PNGFilter +{ + + public static final byte FILTER_NONE = 0; + public static final byte FILTER_SUB = 1; + public static final byte FILTER_UP = 2; + public static final byte FILTER_AVERAGE = 3; + public static final byte FILTER_PAETH = 4; + + /** + * Return whether a filter should be used or FILTER_NONE, + * following the recommendations in the PNG spec. + */ + public static boolean useFilter( PNGHeader header ) + { + switch( header.getColorType() ) + { + case PNGHeader.INDEXED: + return false; + + case PNGHeader.GRAYSCALE: + case PNGHeader.RGB: + if( header.bytesPerPixel() <= 1 ) + return false; + case PNGHeader.GRAYSCALE_WITH_ALPHA: + case PNGHeader.RGB_WITH_ALPHA: + default: + return true; + } + } + + /** + * Heuristic for adaptively choosing a filter, following the scheme + * suggested in the PNG spec. + * @return a fiter type. + */ + public static byte chooseFilter( byte[] scanline, byte[] lastScanline, + int bpp) + + { + long[] values = new long[5]; + int idx = 0; + for( int i = 0; i < 5; i++ ) + { + byte[] filtered = filterScanline((byte)i, scanline, lastScanline, bpp); + values[i] = 0; + for(int j = 0; j < filtered.length; j++ ) + values[i] += (int)(filtered[j] & 0xFF); + if( values[ idx ] > values[i] ) + idx = i; + } + return (byte)idx; + } + + /** + * Filter a scanline. + */ + public static byte[] filterScanline( byte filtertype, byte[] scanline, + byte[] lastScanline, int bpp) + { + int stride = scanline.length; + byte[] out = new byte[ stride ]; + switch( filtertype ) + { + case FILTER_SUB: + for( int i = 0; i < bpp; i++) + out[ i ] = scanline[ i ]; + + for( int i = bpp; i < stride; i++ ) + out[i] = (byte)(scanline[ i ] - + scanline[ i - bpp ]); + break; + + case FILTER_UP: + for( int i = 0; i < stride; i++ ) + out[ i ] = (byte)(scanline[ i ] - lastScanline[ i ]); + break; + + case FILTER_AVERAGE: + for( int i = 0; i < bpp; i++) + out[ i ] = (byte)((scanline[ i ] & 0xFF) - ((lastScanline[ i ] & 0xFF) >> 1)); + for( int i = bpp; i < stride; i++ ) + out[ i ] = (byte)((scanline[ i ] & 0xFF) - + (((scanline[ i - bpp ] & 0xFF) + + (lastScanline[ i ] & 0xFF)) >> 1)); + break; + + case FILTER_PAETH: + for( int i = 0; i < stride; i++ ) + { + int x; + { + int a, b, c; + if( i >= bpp ) + { + a = (scanline[ i - bpp ] & 0xFF); // left + c = (lastScanline[ i - bpp ] & 0xFF); // upper-left + } + else + a = c = 0; + b = (lastScanline[ i ] & 0xFF); // up + + int p = (a + b - c); // initial estimate + // distances to a, b, c + int pa = (p > a) ? p - a : a - p; + int pb = (p > b) ? p - b : b - p; + int pc = (p > c) ? p - c : c - p; + // return nearest of a,b,c, + // breaking ties in order a,b,c. + if( pa <= pb && pa <= pc ) x = a; + else { if( pb <= pc ) x = b; + else x = c; + } + } + out[ i ] = (byte)(scanline[ i ] - x); + } + break; + default: + case FILTER_NONE: + return scanline; + } + return out; + } + + /** + * Unfilter a scanline. + */ + public static byte[] unFilterScanline( int filtertype, byte[] scanline, + byte[] lastScanline, int bpp) + { + int stride = scanline.length; + byte[] out = new byte[ stride ]; + switch( filtertype ) + { + + case FILTER_NONE: + System.arraycopy( scanline, 0, out, 0, stride ); + break; + + case FILTER_SUB: + for( int i = 0; i < bpp; i++) + out[ i ] = scanline[ i ]; + + for( int i = bpp; i < stride; i++ ) + out[ i ] = (byte)(scanline[ i ] + + out[ i - bpp ]); + break; + + case FILTER_UP: + for( int i = 0; i < stride; i++ ) + out[ i ] = (byte)(scanline[ i ] + lastScanline[ i ]); + break; + + case FILTER_AVERAGE: + for( int i = 0; i < bpp; i++) + out[ i ] = (byte)((scanline[ i ] & 0xFF) + ((lastScanline[ i ] & 0xFF) >> 1)); + for( int i = bpp; i < stride; i++ ) + out[ i ] = (byte)((scanline[ i ] & 0xFF) + + (((out[ i - bpp ] & 0xFF) + (lastScanline[ i ] & 0xFF)) >> 1)); + break; + + case FILTER_PAETH: + for( int i = 0; i < stride; i++ ) + { + int x; + { + int a, b, c; + if( i >= bpp ) + { + a = (out[ i - bpp ] & 0xFF); // left + c = (lastScanline[ i - bpp ] & 0xFF); // upper-left + } + else + a = c = 0; + b = (lastScanline[ i ] & 0xFF); // up + + int p = (a + b - c); // initial estimate + // distances to a, b, c + int pa = (p > a) ? p - a : a - p; + int pb = (p > b) ? p - b : b - p; + int pc = (p > c) ? p - c : c - p; + // return nearest of a,b,c, + // breaking ties in order a,b,c. + if( pa <= pb && pa <= pc ) x = a; + else { if( pb <= pc ) x = b; + else x = c; + } + } + out[ i ] = (byte)(scanline[ i ] + x); + } + break; + } + return out; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGGamma.java b/libjava/classpath/gnu/javax/imageio/png/PNGGamma.java new file mode 100644 index 000000000..b9c3f21c3 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGGamma.java @@ -0,0 +1,85 @@ +/* PNGGamma.java -- GAMA chunk. + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.awt.color.ColorSpace; + +/** + * A PNG gAMA (gamma) chunk. + */ +public class PNGGamma extends PNGChunk +{ + private double gamma; + + protected PNGGamma( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + if( data.length < 4 ) + throw new PNGException("Unexpectedly short time chunk. ("+data.length+" bytes)"); + long g = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + gamma = (double)g; + gamma = 100000.0/gamma; + } + + public PNGGamma( double g ) + { + super( TYPE_GAMMA ); + data = new byte[ 4 ]; + gamma = g; + long tmp = (long)(100000.0/gamma); + data[0] = (byte)((tmp & 0xFF000000) >> 24); + data[1] = (byte)((tmp & 0xFF0000) >> 16); + data[2] = (byte)((tmp & 0xFF00) >> 8); + data[3] = (byte)(tmp & 0xFF); + } + + /** + * Returns a ColorSpace object corresponding to this gamma value. + */ + public ColorSpace getColorSpace(boolean grayscale) + { + // FIXME. + return null; + } + + public String toString() + { + return "PNG Gamma chunk, value: "+gamma; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGHeader.java b/libjava/classpath/gnu/javax/imageio/png/PNGHeader.java new file mode 100644 index 000000000..115e50311 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGHeader.java @@ -0,0 +1,257 @@ +/* PNGHeader.java -- PNG Header + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +/** + * A PNG Header chunk. + */ +public class PNGHeader extends PNGChunk +{ + private int width, height, depth; + private int colorType, compression, filter, interlace; + + /** + * The valid interlace types. + */ + public static final int INTERLACE_NONE = 0; + public static final int INTERLACE_ADAM7 = 1; + + /** + * The valid color types. + */ + public static final int GRAYSCALE = 0; + public static final int RGB = 2; + public static final int INDEXED = 3; + public static final int GRAYSCALE_WITH_ALPHA = 4; + public static final int RGB_WITH_ALPHA = 6; + + /** + * Parses a PNG Header chunk. + */ + protected PNGHeader( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + if( data.length < 13 ) + throw new PNGException("Unexpectedly short header chunk. (" + data.length + + " bytes)"); + + width = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + height = ((data[4] & 0xFF) << 24) | ( (data[5] & 0xFF) << 16 ) | + ((data[6] & 0xFF) << 8) | (data[7] & 0xFF); + depth = (data[8] & 0xFF); + colorType = (data[9] & 0xFF); + compression = (data[10] & 0xFF); + filter = (data[11] & 0xFF); + interlace = (data[12] & 0xFF); + } + + /** + * Create a PNG header chunk. + * Warning: This trusts that the parameters are valid. + */ + public PNGHeader(int width, int height, int depth, + int colorType, boolean interlace) + { + super( TYPE_HEADER ); + data = new byte[ 13 ]; + + this.width = width; + this.height = height; + this.depth = depth; + compression = filter = 0; + this.colorType = colorType; + this.interlace = interlace ? 1 : 0; + + // Build the data chunk. + byte[] a = getInt( width ); + byte[] b = getInt( height ); + data[0] = a[0]; data[1] = a[1]; data[2] = a[2]; data[3] = a[3]; + data[4] = b[0]; data[5] = b[1]; data[6] = b[2]; data[7] = b[3]; + data[8] = (byte)depth; + data[9] = (byte)colorType; + data[10] = (byte)compression; + data[11] = (byte)filter; + data[12] = (byte)this.interlace; + } + + /** + * Validates the header fields + */ + public boolean isValidChunk() + { + if( !super.isValidChunk() ) + return false; + + // width and height must be nonzero + if( width == 0 || height == 0 ) + return false; + // colorType can be 0,2,3,4,6 + if( (colorType & 0xFFFFFFF8) != 0 || colorType == 5 || colorType == 1) + return false; + // Possible valid depths are 1,2,4,8,16 + if( !((depth == 1) || (depth == 2) || (depth == 4) || + (depth == 8) || (depth == 16)) ) + return false; + if( colorType == INDEXED && depth == 16 ) + return false; + if( ( colorType == RGB || colorType == GRAYSCALE_WITH_ALPHA || + colorType == RGB_WITH_ALPHA ) && + depth < 8 ) + return false; + // Only compression and filter methods zero are defined + if( compression != 0 || filter != 0 ) + return false; + // Interlace methods, 0 and 1 are valid values. + if( (interlace & 0xFFFFFFFE) != 0 ) + return false; + + return true; + } + + /** + * Returns <code>true</code> if this PNG is indexed-color + */ + public boolean isIndexed() + { + return (colorType == INDEXED); + } + + /** + * Returns <code>true</code> if this PNG is grayscale + */ + public boolean isGrayscale() + { + return ((colorType == GRAYSCALE) || (colorType == GRAYSCALE_WITH_ALPHA)); + } + + /** + * Returns the color type of the image. + */ + public int getColorType() + { + return colorType; + } + + /** + * Returns whether the image is interlaced or not. + */ + public boolean isInterlaced() + { + return (interlace != 0); + } + + /** + * Returns the number of bytes per pixel. + */ + public int bytesPerPixel() + { + switch( colorType ) + { + case GRAYSCALE_WITH_ALPHA: + return ((depth * 2) >> 3); + case RGB: + return ((depth * 3) >> 3); + case RGB_WITH_ALPHA: + return ((depth * 4) >> 3); + + default: + case GRAYSCALE: + case INDEXED: + int i = (depth >> 3); + if( i > 0 ) return i; + return 1; // if bytes per pixel < 1, return 1 anyway. + } + } + + /** + * Returns the stride of one scanline, in bytes. + */ + public int getScanlineStride() + { + long nBits = 0; // bits per scanline - scanlines are on byte offsets. + switch( colorType ) + { + case GRAYSCALE: + nBits = width * depth; + break; + case RGB: + nBits = width * depth * 3; + break; + case INDEXED: + nBits = depth * width; + break; + case GRAYSCALE_WITH_ALPHA: + nBits = depth * width * 2; + break; + case RGB_WITH_ALPHA: + nBits = depth * width * 4; + break; + } + // Round up number of bits to the nearest byte + if( (nBits & 0x07) != 0 ) + nBits += (8 - (nBits & 0x07)); + + return (int)(nBits >> 3); // return # of bytes. + } + + public int getWidth() + { + return width; + } + + public int getHeight() + { + return height; + } + + public int getDepth() + { + return depth; + } + + /** + * Debugging string. + */ + public String toString() + { + return "Header Chunk. Image width:"+width+" height:"+height+ + " depth:"+depth+" color type:"+colorType+" compression type:"+ + compression+" filter type:"+ filter+" interlace:"+interlace; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGICCProfile.java b/libjava/classpath/gnu/javax/imageio/png/PNGICCProfile.java new file mode 100644 index 000000000..9ecea7166 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGICCProfile.java @@ -0,0 +1,116 @@ +/* PNGICCProfile.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.awt.color.ICC_Profile; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ColorSpace; +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.io.ByteArrayInputStream; +import java.util.zip.InflaterInputStream; +import java.util.zip.Deflater; + +/** + * A PNG iCCP (ICC Profile) chunk. + */ +public class PNGICCProfile extends PNGChunk +{ + private String name; + private ICC_Profile profile; + // A generic profile name to use "ICC Profile" + private static final byte[] genericName = new byte[] + { 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65 }; + + protected PNGICCProfile( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + int i = 0; + while( data[i++] != 0 ) + ; + + try + { + name = new String(data, 0, i, "8859_1"); + } + catch(UnsupportedEncodingException e) + { + name = ""; // shouldn't really happen. + } + if( data[i++] != 0 ) + throw new PNGException("Can't handle nonzero compression types with iCCP chunks."); + try + { + ByteArrayInputStream bos = new ByteArrayInputStream( data, i, + data.length - i ); + profile = ICC_Profile.getInstance( new InflaterInputStream( bos ) ); + } + catch(IOException ioe) + { + throw new PNGException("Couldn't read iCCP profile chunk."); + } + System.out.println("Got profile:"+profile); + } + + public PNGICCProfile( ICC_Profile profile ) + { + super( TYPE_PROFILE ); + this.profile = profile; + byte[] profData = profile.getData(); + byte[] outData = new byte[ profData.length * 2 ]; + Deflater deflater = new Deflater(); + deflater.setInput( profData ); + deflater.finish(); + int n = deflater.deflate( outData ); + data = new byte[ n + 11 + 2 ]; + System.arraycopy(genericName, 0, data, 0, 11 ); + data[11] = data[12] = 0; // null separator and compression type. + // Copy compressed data + System.arraycopy(outData, 0, data, 13, n ); + } + + public ColorSpace getColorSpace() + { + return new ICC_ColorSpace( profile ); + } + + public String toString() + { + return "PNG ICC Profile, name: "+name; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGImageReader.java b/libjava/classpath/gnu/javax/imageio/png/PNGImageReader.java new file mode 100644 index 000000000..3209baa26 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGImageReader.java @@ -0,0 +1,224 @@ +/* PNGImageReader.java -- The ImageIO ImageReader for PNG + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.imageio.png; + +import gnu.javax.imageio.IIOInputStream; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; + +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageInputStream; + +/** + * The ImageIO ImageReader for PNG images. + * + * @author Roman Kennke (kennke@aicas.com) + */ +public class PNGImageReader + extends ImageReader +{ + + /** + * The PNG file. + */ + private PNGFile pngFile; + + /** + * The decoded image. + */ + private BufferedImage image; + + /** + * The supported image types for PNG. + */ + private ArrayList imageTypes; + + /** + * Creates a new instance. + * + * @param spi the corresponding ImageReaderSpi + */ + public PNGImageReader(PNGImageReaderSpi spi) + { + super(spi); + } + + /** + * Returns the height of the image. + */ + public int getHeight(int imageIndex) + throws IOException + { + checkIndex(imageIndex); + readImage(); + return image.getHeight(); + } + + /** + * Returns the width of the image. + * + * @param imageIndex the index of the image + * + * @return the width of the image + */ + public int getWidth(int imageIndex) throws IOException + { + checkIndex(imageIndex); + readImage(); + return image.getWidth(); + } + + /** + * Returns the image types for the image. + * + * @see ImageReader#getImageTypes(int) + */ + public Iterator getImageTypes(int imageIndex) + throws IOException + { + checkIndex(imageIndex); + readImage(); + if (imageTypes == null) + { + imageTypes = new ArrayList(); + imageTypes.add(new ImageTypeSpecifier(image.getColorModel(), + image.getSampleModel())); + } + return imageTypes.iterator(); + } + + /** + * Returns the number of images in the stream. + * + * @return the number of images in the stream + * + * @see ImageReader#getNumImages(boolean) + */ + public int getNumImages(boolean allowSearch) + throws IOException + { + return 1; + } + + /** + * Reads the image. + * + * @param imageIndex the index of the image to read + * @param param additional parameters + */ + public BufferedImage read(int imageIndex, ImageReadParam param) + throws IOException + { + checkIndex(imageIndex); + readImage(); + return image; + } + + /** + * Sets the input and checks the input parameter. + * + * @see ImageReader#setInput(Object, boolean, boolean) + */ + public void setInput(Object input, + boolean seekForwardOnly, + boolean ignoreMetadata) + { + super.setInput(input, seekForwardOnly, ignoreMetadata); + if (! (input instanceof InputStream || input instanceof ImageInputStream)) + throw new IllegalArgumentException("Input not an ImageInputStream"); + } + + public IIOMetadata getImageMetadata(int imageIndex) + throws IOException + { + // TODO: Not (yet) supported. + checkIndex(imageIndex); + return null; + } + + public IIOMetadata getStreamMetadata() + throws IOException + { + // TODO: Not (yet) supported. + return null; + } + + /** + * Checks the image indexa and throws and IndexOutOfBoundsException if + * appropriate. + * + * @param index the index to check + */ + private void checkIndex(int index) + { + if (index > 0) + throw new IndexOutOfBoundsException("Image index out of bounds"); + } + + /** + * Makes sure that the image is read. + * + * @throws IOException if something goes wrong + */ + private void readImage() + throws IOException + { + if (pngFile == null) + { + if (input instanceof InputStream) + pngFile = new PNGFile((InputStream) input); + else if (input instanceof ImageInputStream) + pngFile = new PNGFile(new IIOInputStream((ImageInputStream) input)); + else + assert false : "Must not happen"; + } + + if (pngFile != null && image == null) + { + image = pngFile.getBufferedImage(); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGImageReaderSpi.java b/libjava/classpath/gnu/javax/imageio/png/PNGImageReaderSpi.java new file mode 100644 index 000000000..0092ab558 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGImageReaderSpi.java @@ -0,0 +1,128 @@ +/* PNGImageReaderSpi.java -- The ImageReader service provider for PNG + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.imageio.png; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; + +import javax.imageio.ImageReader; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; + +/** + * The ImageIO ImageReader service provider for PNG images. + * + * @author Roman Kennke (kennke@aicas.com) + */ +public class PNGImageReaderSpi + extends ImageReaderSpi +{ + + /** + * The PNG file signature. + */ + private static final byte[] SIGNATURE = new byte[] + { (byte) 137, 80, 78, 71, 13, 10, 26, 10 }; + + private static final String VENDOR_NAME = "GNU"; + static final String VERSION = "1.0"; + static final String READER_CLASSNAME = + "gnu.javax.imageio.png.PNGImageReader"; + static final String[] NAMES = { "Portable Network Graphics" }; + static final String[] SUFFIXES = { ".png" , ".PNG" }; + static final String[] MIME_TYPES = { "image/png" }; + static final String[] WRITER_SPI_NAMES = + new String[] { "gnu.javax.imageio.png.PNGWriterSpi" }; + static final Class[] INPUT_TYPES = new Class[]{ InputStream.class, + ImageInputStream.class}; + public PNGImageReaderSpi() + { + super(VENDOR_NAME, VERSION, NAMES, SUFFIXES, MIME_TYPES, READER_CLASSNAME, + INPUT_TYPES, WRITER_SPI_NAMES, false, null, null, null, null, false, + null, null, null, null); + } + + /** + * Determines if the PNG ImageReader can decode the specified input. + * + * @param source the source to decode + */ + public boolean canDecodeInput(Object source) throws IOException + { + boolean canDecode = false; + if (source instanceof ImageInputStream) + { + ImageInputStream in = (ImageInputStream) source; + in.mark(); + canDecode = true; + for (int i = 0; i < SIGNATURE.length && canDecode; i++) + { + byte sig = (byte) in.read(); + if (sig != SIGNATURE[i]) { + canDecode = false; + } + } + in.reset(); + } + return canDecode; + } + + /** + * Returns a new PNGImageReader instance. + * + * @param extension the extension, ignored + */ + public ImageReader createReaderInstance(Object extension) + throws IOException + { + return new PNGImageReader(this); + } + + /** + * Returns a description. + * + * @param locale the locale + */ + public String getDescription(Locale locale) + { + return "Portable Network Graphics"; + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGPalette.java b/libjava/classpath/gnu/javax/imageio/png/PNGPalette.java new file mode 100644 index 000000000..197cad846 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGPalette.java @@ -0,0 +1,127 @@ +/* PNGPalette.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.awt.color.ColorSpace; +import java.awt.image.IndexColorModel; + +/** + * A PNG Palette chunk. + */ +public class PNGPalette extends PNGChunk +{ + private int[] red,green,blue; + + protected PNGPalette( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + double l = data.length; + l /= 3.0; + // Check if it's divisible by 3. (Yuck.) + if( l - Math.floor(l) != 0.0 ) + throw new PNGException("Invalid size of palette chunk."); + int nEntries = (int)l; + + red = new int[ nEntries ]; + green = new int[ nEntries ]; + blue = new int[ nEntries ]; + for( int i = 0; i < nEntries; i++ ) + { + red[i] = (data[ i * 3 ] & 0xFF); + green[i] = (data[ i * 3 + 1 ] & 0xFF); + blue[i] = (data[ i * 3 + 2] & 0xFF); + } + } + + public PNGPalette( IndexColorModel cm ) + { + super( TYPE_PALETTE ); + int n = cm.getMapSize(); + data = new byte[ n * 3 ]; + red = new int[ n ]; + green = new int[ n ]; + blue = new int[ n ]; + for(int i = 0; i < n; i++ ) + { + red[i] = data[i * 3] = (byte)cm.getRed(i); + green[i] = data[i * 3 + 1] = (byte)cm.getGreen(i); + blue[i] = data[i * 3 + 2] = (byte)cm.getBlue(i); + } + } + + public IndexColorModel getPalette( ColorSpace cs ) + { + int nc = red.length; + byte[] r = new byte[nc]; + byte[] g = new byte[nc]; + byte[] b = new byte[nc]; + + if( cs == null ) + { + for(int i = 0; i < nc; i ++ ) + { + r[i] = (byte)red[i]; + g[i] = (byte)green[i]; + b[i] = (byte)blue[i]; + } + } + else + { + for(int i = 0; i < nc; i ++ ) + { + float[] in = new float[3]; + in[0] = (((float)red[i]) / 255f); + in[1] = (((float)green[i]) / 255f); + in[2] = (((float)blue[i]) / 255f); + float[] out = cs.toRGB( in ); + r[i] = (byte)( Math.round(out[0] * 255.0) ); + g[i] = (byte)( Math.round(out[1] * 255.0) ); + b[i] = (byte)( Math.round(out[2] * 255.0) ); + } + } + return new IndexColorModel(8, nc, r, g, b); + } + + public String toString() + { + String s = "PNG Palette:\n"; + for( int i = 0; i < red.length; i++) + s = s + "Index " + i + ": ["+ red[i] +", "+green[i]+", "+blue[i]+"]\n"; + return s; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGPhys.java b/libjava/classpath/gnu/javax/imageio/png/PNGPhys.java new file mode 100644 index 000000000..d15f09e88 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGPhys.java @@ -0,0 +1,112 @@ +/* PNGPhys.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +/** + * A PNG "pHYS" chunk - pixel physical dimensions + */ +public class PNGPhys extends PNGChunk +{ + long x, y; + double ratio; + boolean usesRatio; + + protected PNGPhys( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + if( data.length < 9 ) + throw new PNGException("Unexpected size of pHYS chunk."); + x = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) | + ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); + y = ((data[4] & 0xFF) << 24) | ( (data[5] & 0xFF) << 16 ) | + ((data[6] & 0xFF) << 8) | (data[7] & 0xFF); + if(data[8] == 0) + { + ratio = ((double)x)/((double)y); + usesRatio = true; + } + } + + public PNGPhys( double ratio ) + { + super( TYPE_PHYS ); + + this.ratio = ratio; + usesRatio = true; + + if( ratio < 1.0 ) + { + y = 0xFFFFFFFF; + x = (long)(0xFFFFFFFFL * ratio); + } + else + { + x = 0xFFFFFFFF; + y = (long)(0xFFFFFFFFL * ratio); + } + makeData(); + } + + public PNGPhys( int x, int y ) + { + super( TYPE_PHYS ); + usesRatio = false; + this.x = x; + this.y = y; + makeData(); + } + + private void makeData() + { + data = new byte[ 9 ]; + byte[] a = getInt( (int)x ); + byte[] b = getInt( (int)y ); + data[0] = a[0]; data[1] = a[1]; data[2] = a[2]; data[3] = a[3]; + data[4] = b[0]; data[5] = b[1]; data[6] = b[2]; data[7] = b[3]; + data[7] = (usesRatio) ? 0 : (byte)0xFF; + } + + public String toString() + { + String s = "PNG Physical pixel size chunk."; + if( usesRatio ) + return s + " Aspect ratio (x/y): " + ratio; + else + return s + " " + x + " by " + y + " pixels per meter. (x, y)."; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/png/PNGTime.java b/libjava/classpath/gnu/javax/imageio/png/PNGTime.java new file mode 100644 index 000000000..824f06f83 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/png/PNGTime.java @@ -0,0 +1,83 @@ +/* PNGTime.java -- + Copyright (C) 2006 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.imageio.png; + +import java.util.Date; + +/** + * A PNG tIME chunk. + */ +public class PNGTime extends PNGChunk +{ + private Date date; + + protected PNGTime( int type, byte[] data, int crc ) throws PNGException + { + super( type, data, crc ); + if( data.length < 7 ) + throw new PNGException("Unexpectedly short time chunk. ("+data.length+" bytes)"); + + // PNG value is absolute (2006, not 106 or 06), java is from 1900. + int year = ( (data[0] & 0xFF) << 8 ) | (data[1] & 0xFF); + int month = (data[2] & 0xFF); // java counts from 0. PNG from 1. + int day = (data[3] & 0xFF); + int hour = (data[4] & 0xFF); + int minute = (data[5] & 0xFF); + int second = (data[6] & 0xFF); + date = new Date( year - 1900, month - 1, day, hour, minute, second ); + } + + public PNGTime( Date d ) + { + super( TYPE_TIME ); + data = new byte[ 7 ]; + int tmp = d.getYear() + 1900; + data[0] = (byte)((tmp & 0xFF00) >> 8); + data[1] = (byte)(tmp & 0x00FF); + data[2] = (byte)(d.getMonth() + 1); + data[3] = (byte)(d.getDay()); + data[4] = (byte)(d.getHours()); + data[5] = (byte)(d.getMinutes()); + data[6] = (byte)(d.getSeconds()); + } + + public String toString() + { + return "PNG Time chunk: "+date; + } +} |