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 | |
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')
58 files changed, 10542 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/imageio/IIOInputStream.java b/libjava/classpath/gnu/javax/imageio/IIOInputStream.java new file mode 100644 index 000000000..1ede75f78 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/IIOInputStream.java @@ -0,0 +1,102 @@ +/* GIFStream.java -- + 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; + +import java.io.InputStream; +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; + +/** + * Implements InputStream on an ImageInputStream + * The purpose of this is to avoid IIO dependencies in the various decoders. + * (which only use read() anyway). + */ +public class IIOInputStream extends InputStream +{ + private ImageInputStream is; + + public IIOInputStream( ImageInputStream is ) + { + this.is = is; + } + + public int available() + { + return 0; + } + + public void close() throws IOException + { + is.close(); + } + + public void mark(int readlimit) + { + is.mark(); + } + + public boolean markSupported() + { + return true; + } + + public int read() throws IOException + { + return is.read(); + } + + public int read(byte[] b) throws IOException + { + return is.read(b); + } + + public int read(byte[] b, int offset, int length) throws IOException + { + return is.read(b, offset, length); + } + + public void reset() throws IOException + { + is.reset(); + } + + public long skip(long n) throws IOException + { + return is.skipBytes(n); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/BMPDecoder.java b/libjava/classpath/gnu/javax/imageio/bmp/BMPDecoder.java new file mode 100644 index 000000000..108461931 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/BMPDecoder.java @@ -0,0 +1,168 @@ +/* BMPDecoder.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.awt.image.IndexColorModel; +import java.awt.image.BufferedImage; + +public abstract class BMPDecoder { + + protected BMPInfoHeader infoHeader; + protected BMPFileHeader fileHeader; + protected long offset; + + public BMPDecoder(BMPFileHeader fh, BMPInfoHeader ih){ + fileHeader = fh; + infoHeader = ih; + offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE; + } + + /** + * Determines the coding type of the bitmap and returns the corresponding + * decoder. + */ + public static BMPDecoder getDecoder(BMPFileHeader fh, BMPInfoHeader ih){ + switch(ih.getCompression()){ + case BMPInfoHeader.BI_RGB: // uncompressed RGB + switch(ih.getBitCount()){ + case 32: + return new DecodeBF32(fh, ih, true); + + case 24: + return new DecodeRGB24(fh, ih); + + case 16: + return new DecodeBF16(fh, ih, true); + + case 8: + return new DecodeRGB8(fh, ih); + + case 4: + return new DecodeRGB4(fh, ih); + + case 1: + return new DecodeRGB1(fh, ih); + + default: + return null; + } + + case BMPInfoHeader.BI_RLE8: + return new DecodeRLE8(fh, ih); + + case BMPInfoHeader.BI_RLE4: + return new DecodeRLE4(fh, ih); + + case BMPInfoHeader.BI_BITFIELDS: + switch(ih.getBitCount()){ + case 16: + return new DecodeBF16(fh, ih, false); + + case 32: + return new DecodeBF32(fh, ih, false); + + default: + return null; + } + + default: + return null; + } + } + + /** + * The image decoder. + */ + public abstract BufferedImage decode(ImageInputStream in) + throws IOException, BMPException; + + /** + * Reads r,g,b bit masks from an inputstream + */ + protected int[] readBitMasks(ImageInputStream in) throws IOException { + int[] bitmasks = new int[3]; + byte[] temp = new byte[12]; + if(in.read(temp) != 12) + throw new IOException("Couldn't read bit masks."); + offset += 12; + + ByteBuffer buf = ByteBuffer.wrap(temp); + buf.order(ByteOrder.LITTLE_ENDIAN); + bitmasks[0] = buf.getInt(); + bitmasks[1] = buf.getInt(); + bitmasks[2] = buf.getInt(); + return bitmasks; + } + + /** + * Reads an N-color palette from an inputstream in RGBQUAD format and + * returns an equivalent ColorModel object + */ + protected IndexColorModel readPalette(ImageInputStream in) throws IOException { + int N = infoHeader.getNumberOfPaletteEntries(); + byte[] r = new byte[N]; + byte[] g = new byte[N]; + byte[] b = new byte[N]; + for(int i=0;i<N;i++){ + byte[] RGBquad = new byte[4]; + if(in.read(RGBquad) != 4) + throw new IOException("Error reading palette information."); + // RGBQUAD structure is b,g,r,0 + r[i] = RGBquad[2]; + g[i] = RGBquad[1]; + b[i] = RGBquad[0]; + } + + offset += 4*N; + return new IndexColorModel(8, N, r, g, b); + } + + /** + * Read bytes to the start of the image data + */ + protected void skipToImage(ImageInputStream in) throws IOException { + byte[] d = new byte[1]; + long n = fileHeader.getOffset() - offset; + for(int i=0;i<n;i++) + in.read(d); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/BMPEncoder.java b/libjava/classpath/gnu/javax/imageio/bmp/BMPEncoder.java new file mode 100644 index 000000000..d7c54c0d6 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/BMPEncoder.java @@ -0,0 +1,119 @@ +/* BMPEncoder.java -- + 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.bmp; + +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public abstract class BMPEncoder +{ + + /** + * Constructs a new BMPEncoder. + */ + public BMPEncoder() + { + // Nothing to do here. + } + + /** + * Determines the coding type of the bitmap and returns the corresponding + * encoder. + * + * @param fh - the file header + * @param ih - the info header + * @return the appropriate encoder + */ + public static BMPEncoder getEncoder(BMPFileHeader fh, BMPInfoHeader ih) + { + switch (ih.getCompression()) + { + case BMPInfoHeader.BI_RGB: + switch (ih.getBitCount()) + { + case 32: + return new EncodeRGB32(fh, ih); + + case 24: + return new EncodeRGB24(fh, ih); + + case 16: + return new EncodeRGB16(fh, ih); + + case 8: + return new EncodeRGB8(fh, ih); + + case 4: + return new EncodeRGB4(fh, ih); + + case 1: + return new EncodeRGB1(fh, ih); + + default: + return null; + } + case BMPInfoHeader.BI_RLE4: + return new EncodeRLE4(fh, ih); + + case BMPInfoHeader.BI_RLE8: + return new EncodeRLE8(fh, ih); + default: + return null; + } + } + + /** + * The image encoder. + * + * @param o - the image output stream + * @param streamMetadata - metadata associated with this stream, or + * null + * @param image - an IIOImage containing image data, metadata and + * thumbnails to be written + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + */ + public abstract void encode(ImageOutputStream o, IIOMetadata streamMetadata, + IIOImage image, ImageWriteParam param) + throws IOException; +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/BMPException.java b/libjava/classpath/gnu/javax/imageio/bmp/BMPException.java new file mode 100644 index 000000000..0ba3c6c74 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/BMPException.java @@ -0,0 +1,47 @@ +/* BMPException.java -- + Copyright (C) 2005 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.bmp; + +import javax.imageio.IIOException; + +public class BMPException extends IIOException { + + public BMPException(String message){ + super(message); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/BMPFileHeader.java b/libjava/classpath/gnu/javax/imageio/bmp/BMPFileHeader.java new file mode 100644 index 000000000..0cfd72323 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/BMPFileHeader.java @@ -0,0 +1,151 @@ +/* BMPFileHeader.java -- + Copyright (C) 2005 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.bmp; + +import java.awt.image.RenderedImage; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import javax.imageio.IIOImage; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class BMPFileHeader { + /** Header signature, always 'BM' */ + private final static short bfType = 0x424d; + + /** Bitmap file size, in bytes. */ + protected long bfSize; + + /** Offset from the beginning of the file to the bitmap data */ + protected long bfOffBits; + + /** BITMAPFILEHEADER is 14 bytes */ + public static final int SIZE = 14; + private static final int BITMAPINFOHEADER_SIZE = 40; + + /** + * Creates the header from an input stream, which is not closed. + * + * @throws IOException if an I/O error occured. + * @throws BMPException if the header was invalid + */ + public BMPFileHeader(ImageInputStream in) throws IOException, BMPException { + byte[] data = new byte[SIZE]; + + if (in.read(data) != SIZE) + throw new IOException("Couldn't read header."); + ByteBuffer buf = ByteBuffer.wrap(data); + + if(buf.getShort(0) != bfType) + throw new BMPException("Not a BMP file."); + + buf.order(ByteOrder.LITTLE_ENDIAN); + + // get size (keep unsigned) + bfSize = ((long)buf.getInt(2) & (0xFFFFFFFF)); + + // Two reserved shorts are here, and should be zero, + // perhaps they should be tested to be zero, but I don't + // feel this strictness is necessary. + + bfOffBits = ((long)buf.getInt(10) & (0xFFFFFFFF)); + } + + /** + * Creates the header from an output stream, which is not closed. + * + * @param out - the image output stream + * @param im - the image + * @throws IOException if an I/O error occured. + */ + public BMPFileHeader(ImageOutputStream out, IIOImage im) throws IOException + { + RenderedImage img = im.getRenderedImage(); + int w = img.getWidth(); + int h = img.getHeight(); + + bfOffBits = SIZE + BITMAPINFOHEADER_SIZE; + bfSize = ((w * h) * 3) + ((4 - ((w * 3) % 4)) * h) + bfOffBits; + + write(out); + } + + /** + * Writes the header to an output stream, which is not closed or flushed. + * + * @throws IOException if an I/O error occured. + */ + public void write(ImageOutputStream out) throws IOException { + ByteBuffer buf = ByteBuffer.allocate(SIZE); + buf.putShort(0, bfType); // ID + buf.putInt(2, (int)(bfSize & (0xFFFFFFFF))); // size + buf.putInt(6, 0); // 4 reserved bytes set to zero + buf.putInt(7, (int)(bfOffBits & (0xFFFFFFFF))); // size + out.write(buf.array()); + } + + /** + * Sets the file size + */ + public void setSize(long size){ + bfSize = size; + } + + /** + * Sets the bitmap offset within the file + */ + public void setOffset(long offset){ + bfOffBits = offset; + } + + /** + * Gets the file size + */ + public long getSize(){ + return bfSize; + } + + /** + * Gets the bitmap offset within the file + */ + public long getOffset(){ + return bfOffBits; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/BMPImageReader.java b/libjava/classpath/gnu/javax/imageio/bmp/BMPImageReader.java new file mode 100644 index 000000000..7b136bdf5 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/BMPImageReader.java @@ -0,0 +1,148 @@ +/* BMPImageReader.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.*; +import javax.imageio.spi.*; +import javax.imageio.metadata.*; +import javax.imageio.stream.ImageInputStream; +import java.util.Iterator; +import java.awt.image.BufferedImage; + +public class BMPImageReader extends ImageReader { + private BMPInfoHeader infoHeader; + private BMPFileHeader fileHeader; + private BMPDecoder decoder; + + protected BMPImageReader(ImageReaderSpi originatingProvider){ + super(originatingProvider); + infoHeader = null; + fileHeader = null; + decoder = null; + } + + private void validateIndex(int imageIndex) + throws IndexOutOfBoundsException { + if (imageIndex != 0) + throw new IndexOutOfBoundsException("Invalid image index."); + } + + public void setInput(Object input) { + super.setInput(input); + } + + public void setInput(Object input, + boolean seekForwardOnly, + boolean ignoreMetadata) { + super.setInput(input, seekForwardOnly, ignoreMetadata); + } + + public void setInput(Object input, boolean isStreamable) { + super.setInput(input, isStreamable); + + if (!(input instanceof ImageInputStream)) + throw new IllegalArgumentException("Input not an ImageInputStream."); + } + + private void checkStream() throws IOException { + if (!(input instanceof ImageInputStream)) + throw new IllegalStateException("Input not an ImageInputStream."); + if(input == null) + throw new IllegalStateException("No input stream."); + + } + + private void readHeaders() throws IOException, IIOException { + if(fileHeader != null) + return; + + checkStream(); + + fileHeader = new BMPFileHeader((ImageInputStream)input); + infoHeader = new BMPInfoHeader((ImageInputStream)input); + decoder = BMPDecoder.getDecoder(fileHeader, infoHeader); + } + + public int getWidth(int imageIndex) throws IOException { + validateIndex(imageIndex); + readHeaders(); + return infoHeader.getWidth(); + } + + public int getHeight(int imageIndex) throws IOException { + validateIndex(imageIndex); + readHeaders(); + return infoHeader.getHeight(); + } + + public Iterator getImageTypes(int imageIndex){ + validateIndex(imageIndex); + return null; + } + + /** + * Returns the number of images. BMP files can only contain a single one. + */ + public int getNumImages(boolean allowSearch){ + return 1; + } + + + // FIXME: Support metadata + public IIOMetadata getImageMetadata(int imageIndex){ + validateIndex(imageIndex); + return null; + } + + // FIXME: Support metadata + public IIOMetadata getStreamMetadata(){ + return null; + } + + /** + * Reads the image indexed by imageIndex and returns it as + * a complete BufferedImage, using a supplied ImageReadParam. + */ + public BufferedImage read(int imageIndex, ImageReadParam param) + throws IOException, IIOException { + validateIndex(imageIndex); + readHeaders(); + return decoder.decode((ImageInputStream)input); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/BMPImageReaderSpi.java b/libjava/classpath/gnu/javax/imageio/bmp/BMPImageReaderSpi.java new file mode 100644 index 000000000..5d027963a --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/BMPImageReaderSpi.java @@ -0,0 +1,116 @@ +/* BMPImageReaderSpi.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import java.util.Locale; +import javax.imageio.ImageReader; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; + +public class BMPImageReaderSpi extends ImageReaderSpi { + + static final String vendorName = "GNU"; + static final String version = "0.1"; + static final String readerClassName = + "gnu.javax.imageio.bmp.BMPImageReader"; + static final String[] names = { "Microsoft Windows BMP" }; + static final String[] suffixes = { ".bmp", ".bm" }; + static final String[] MIMETypes = { + "image/bmp", + "image/x-windows-bmp"}; + static final String[] writerSpiNames = + { "gnu.javax.imageio.bmp.BMPImageWriterSpi" }; + + static final boolean supportsStandardStreamMetadataFormat = false; + static final String nativeStreamMetadataFormatName = null; + static final String nativeStreamMetadataFormatClassName = null; + static final String[] extraStreamMetadataFormatNames = null; + static final String[] extraStreamMetadataFormatClassNames = null; + static final boolean supportsStandardImageMetadataFormat = false; + static final String nativeImageMetadataFormatName = null; + static final String nativeImageMetadataFormatClassName = null; + static final String[] extraImageMetadataFormatNames = null; + static final String[] extraImageMetadataFormatClassNames = null; + + public BMPImageReaderSpi() { + super(vendorName, version, + names, suffixes, MIMETypes, + readerClassName, + STANDARD_INPUT_TYPE, // Accept ImageInputStreams + writerSpiNames, + supportsStandardStreamMetadataFormat, + nativeStreamMetadataFormatName, + nativeStreamMetadataFormatClassName, + extraStreamMetadataFormatNames, + extraStreamMetadataFormatClassNames, + supportsStandardImageMetadataFormat, + nativeImageMetadataFormatName, + nativeImageMetadataFormatClassName, + extraImageMetadataFormatNames, + extraImageMetadataFormatClassNames); + } + + public String getDescription(Locale locale) { + return "Microsoft BMP v3"; + } + + public boolean canDecodeInput(Object input) + throws IOException { + if (!(input instanceof ImageInputStream)) + return false; + + ImageInputStream in = (ImageInputStream)input; + boolean retval; + + in.mark(); + try { + new BMPFileHeader(in); + retval = true; + } catch(BMPException e){ + retval = false; + } + in.reset(); + + return retval; + } + + public ImageReader createReaderInstance(Object extension) { + return new BMPImageReader(this); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/BMPImageWriter.java b/libjava/classpath/gnu/javax/imageio/bmp/BMPImageWriter.java new file mode 100644 index 000000000..407e66a72 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/BMPImageWriter.java @@ -0,0 +1,195 @@ +/* BMPImageWriter.java -- + 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.bmp; + +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.spi.ImageWriterSpi; +import javax.imageio.stream.ImageOutputStream; + +public class BMPImageWriter + extends ImageWriter +{ + protected BMPEncoder encoder; + protected BMPFileHeader fileHeader; + protected BMPInfoHeader infoHeader; + + /** + * Construct an bmp image writer. + * + * @param originatingProvider - the provider that is constructing this image + * writer, or null + */ + protected BMPImageWriter(ImageWriterSpi originatingProvider) + { + super(originatingProvider); + encoder = null; + fileHeader = null; + infoHeader = null; + } + + /** + * Convert IIOMetadata from an input reader format, returning an IIOMetadata + * suitable for use by an image writer. The ImageTypeSpecifier specifies the + * destination image type. An optional ImageWriteParam argument is available + * in case the image writing parameters affect the metadata conversion. + * + * @param inData - the metadata coming from an image reader + * @param imageType - the output image type of the writer + * @param param - the image writing parameters or null + * @return the converted metadata that should be used by the image writer, or + * null if this ImageTranscoder has no knowledge of the input metadata + * @exception IllegalArgumentException if either inData or imageType is null + */ + public IIOMetadata convertImageMetadata(IIOMetadata inData, + ImageTypeSpecifier imageType, + ImageWriteParam param) + { + // FIXME: Support metadata. + if (inData == null || imageType == null) + throw new IllegalArgumentException("IIOMetadata and ImageTypeSpecifier cannot be null."); + return null; + } + + /** + * Convert IIOMetadata from an input stream format, returning an + * IIOMetadata suitable for use by an image writer. + * + * An optional ImageWriteParam argument is available in case the + * image writing parameters affect the metadata conversion. + * + * @param inData - the metadata coming from an input image stream + * @param param - the image writing parameters or null + * @return the converted metadata that should be used by the image + * writer, or null if this ImageTranscoder has no knowledge of the + * input metadata + * + * @exception IllegalArgumentException if inData is null + */ + public IIOMetadata convertStreamMetadata (IIOMetadata inData, + ImageWriteParam param) + { + // FIXME: Support metadata. + if (inData == null) + throw new IllegalArgumentException("IIOMetadata cannot be null."); + return null; + } + + /** + * Get a metadata object appropriate for encoding an image specified + * by the given image type specifier and optional image write + * parameters. + * + * @param imageType - an image type specifier + * @param param - image writing parameters, or null + * @return a metadata object appropriate for encoding an image of + * the given type with the given parameters + */ + public IIOMetadata getDefaultImageMetadata (ImageTypeSpecifier imageType, ImageWriteParam param) + { + // FIXME: Support metadata. + return null; + } + + /** + * Get a metadata object appropriate for encoding the default image + * type handled by this writer, optionally considering image write + * parameters. + * + * @param param - image writing parameters, or null + * @return a metadata object appropriate for encoding an image of + * the default type with the given parameters + */ + public IIOMetadata getDefaultStreamMetadata (ImageWriteParam param) + { + // FIXME: Support metadata. + return null; + } + + /** + * Write an image stream, including thumbnails and metadata to the + * output stream. The output must have been set prior to this + * method being called. Metadata associated with the stream may be + * supplied, or it can be left null. IIOImage may contain raster + * data if this writer supports rasters, or it will contain a + * rendered image. Thumbnails are resized if need be. Image + * writing parameters may be specified to affect writing, or may be + * left null. + * + * @param streamMetadata - metadata associated with this stream, or + * null + * @param image - an IIOImage containing image data, metadata and + * thumbnails to be written + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + * @throws BMPException if the encoder has not been initialized. + */ + public void write(IIOMetadata streamMetadata, IIOImage image, + ImageWriteParam param) throws IOException, BMPException + { + checkStream(); + ImageOutputStream out = (ImageOutputStream) output; + fileHeader = new BMPFileHeader(out, image); + infoHeader = new BMPInfoHeader(out, image, param); + encoder = BMPEncoder.getEncoder(fileHeader, infoHeader); + + if (encoder != null) + encoder.encode(out, streamMetadata, image, param); + else + throw new BMPException("Encoder has not been initialized."); + } + + /** + * Checks the output stream. + * + * @throws IOException if there is an error with the output stream + */ + private void checkStream() throws IOException + { + if (!(output instanceof ImageOutputStream)) + throw new IllegalStateException("Output not an ImageOutputStream."); + if (output == null) + throw new IllegalStateException("No output stream."); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/BMPImageWriterSpi.java b/libjava/classpath/gnu/javax/imageio/bmp/BMPImageWriterSpi.java new file mode 100644 index 000000000..e158dcfd7 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/BMPImageWriterSpi.java @@ -0,0 +1,148 @@ +/* BMPImageWriterSpi.java -- + 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.bmp; + +import java.util.Locale; + +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriter; +import javax.imageio.spi.ImageWriterSpi; + +public class BMPImageWriterSpi + extends ImageWriterSpi +{ + + static final String vendorName = "GNU"; + static final String version = "0.1"; + static final String writerClassName = "gnu.javax.imageio.bmp.BMPImageWriter"; + static final String[] names = { "bmp", "BMP", "Microsoft Windows BMP" }; + static final String[] suffixes = { ".bmp", ".bm" }; + static final String[] MIMETypes = { "image/bmp", "image/x-windows-bmp" }; + static final String[] readerSpiNames = { "gnu.javax.imageio.bmp.BMPImageReaderSpi" }; + + static final boolean supportsStandardStreamMetadataFormat = false; + static final String nativeStreamMetadataFormatName = null; + static final String nativeStreamMetadataFormatClassName = null; + static final String[] extraStreamMetadataFormatNames = null; + static final String[] extraStreamMetadataFormatClassNames = null; + static final boolean supportsStandardImageMetadataFormat = false; + static final String nativeImageMetadataFormatName = null; + static final String nativeImageMetadataFormatClassName = null; + static final String[] extraImageMetadataFormatNames = null; + static final String[] extraImageMetadataFormatClassNames = null; + + private BMPImageWriter writerInstance; + + public BMPImageWriterSpi() + { + super(vendorName, version, names, suffixes, MIMETypes, writerClassName, + STANDARD_OUTPUT_TYPE, readerSpiNames, supportsStandardStreamMetadataFormat, + nativeStreamMetadataFormatName, nativeStreamMetadataFormatClassName, + extraStreamMetadataFormatNames, extraStreamMetadataFormatClassNames, + supportsStandardImageMetadataFormat, nativeImageMetadataFormatName, + nativeImageMetadataFormatClassName, extraImageMetadataFormatNames, + extraImageMetadataFormatClassNames); + } + + /** + * Returns true if the image can be encoded. + * + * @param type - the image type specifier. + * @return true if image can be encoded, otherwise false. + */ + public boolean canEncodeImage(ImageTypeSpecifier type) + { + if (type == null) + return false; + + BMPInfoHeader ih = writerInstance.infoHeader; + if (ih != null) + { + int compressionType = ih.getCompression(); + int bytes = type.getColorModel().getPixelSize(); + if ((compressionType == BMPInfoHeader.BI_RLE4 && (bytes != 4 || bytes != 8)) + || (compressionType == BMPInfoHeader.BI_RGB && ((bytes != 1 + || bytes != 4 + || bytes != 8 + || bytes != 16 + || bytes != 24 + || bytes != 32)))) + return false; + } + return true; + } + + /** + * Creates an instance of ImageWriter using the given extension. + * + * @param extension - the provider that is constructing this image writer, or + * null + */ + public ImageWriter createWriterInstance(Object extension) + { + if (extension != null && extension instanceof ImageWriterSpi) + writerInstance = new BMPImageWriter((ImageWriterSpi) extension); + else + writerInstance = new BMPImageWriter(this); + return writerInstance; + } + + /** + * Gets the instance of ImageWriter, if already created. + */ + public BMPImageWriter getWriterInstance() + { + if (writerInstance != null) + return writerInstance; + return (BMPImageWriter) createWriterInstance(null); + } + + /** + * Returns a short description of this service provider that can be + * presented to a human user. + * + * @param locale - the locale for which the description string should + * be localized. + */ + public String getDescription(Locale locale) + { + return "Microsoft BMP v3"; + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/BMPInfoHeader.java b/libjava/classpath/gnu/javax/imageio/bmp/BMPInfoHeader.java new file mode 100644 index 000000000..e14afdb04 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/BMPInfoHeader.java @@ -0,0 +1,317 @@ +/* BMPInfoHeader.java -- + Copyright (C) 2005 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.bmp; + +import java.awt.Dimension; +import java.awt.image.ColorModel; +import java.awt.image.RenderedImage; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class BMPInfoHeader +{ + /** Size of the bitmap info header */ + protected int biSize; + + /** Pixel width of the bitmap */ + protected int biWidth; + + /** Pixel height of the bitmap */ + protected int biHeight; + + /** Number of bitplanes = 1 */ + protected short biPlanes; + + /** Number of bpp = 1,4,8,24 */ + protected short biBitCount; + + /** Compression type, RGB8, RLE8, RLE4, BITFIELDS */ + protected int biCompression; + + /** Byte size of the uncompressed bitmap, can be 0. */ + protected int biSizeImage; + + /** X resolution, dots per meter */ + protected int biXPelsPerMeter; + + /** Y resolution, dots per meter */ + protected int biYPelsPerMeter; + + /** Number of colors used (palette only, can be 0 for all) */ + protected int biClrUsed; + + /** Number of 'important' colors, 0 for all */ + protected int biClrImportant; + + /** BITMAPINFOHEADER is 40 bytes */ + public static final int SIZE = 40; + + /** + * Compression types + */ + public static final int BI_RGB = 0; + public static final int BI_RLE8 = 1; + public static final int BI_RLE4 = 2; + public static final int BI_BITFIELDS = 3; + + /** + * Creates the header from an input stream, which is not closed. + * + * @param in - the image input stream + * @throws IOException if an I/O error occured. + * @throws BMPException if the header was invalid + */ + public BMPInfoHeader(ImageInputStream in) throws IOException, BMPException + { + byte[] data = new byte[SIZE]; + + if (in.read(data) != SIZE) + throw new IOException("Couldn't read header."); + ByteBuffer buf = ByteBuffer.wrap(data); + buf.order(ByteOrder.LITTLE_ENDIAN); + + int n; + if ((n = buf.getInt()) != SIZE) + throw new BMPException("Invalid BITMAPINFOHEADER size: " + n); + + biWidth = buf.getInt(); + biHeight = buf.getInt(); + biPlanes = buf.getShort(); + setBitCount(buf.getShort()); + setCompression(buf.getInt()); + biSizeImage = buf.getInt(); + biXPelsPerMeter = buf.getInt(); + biYPelsPerMeter = buf.getInt(); + biClrUsed = buf.getInt(); + biClrImportant = buf.getInt(); + } + + /** + * Creates the info header from an output stream, which is not closed. + * + * @param out - the image output stream + * @param im - the image + * @param param - the image write param. + * @throws IOException if an I/O error occured. + */ + public BMPInfoHeader(ImageOutputStream out, IIOImage im, ImageWriteParam param) throws IOException + { + RenderedImage img = im.getRenderedImage(); + ColorModel cMod = img.getColorModel(); + + biSize = SIZE; + biWidth = img.getWidth(); + biHeight = img.getHeight(); + biPlanes = 1; + + if (param != null && param.canWriteCompressed()) + { + String compType = param.getCompressionType(); + if (compType.equals("BI_RLE8")) + { + biCompression = BI_RLE8; + biBitCount = 8; + } + else if (compType.equals("BI_RLE4")) + { + biCompression = BI_RLE4; + biBitCount = 4; + } + else + { + biCompression = BI_RGB; + biBitCount = (short) cMod.getPixelSize(); + } + } + else + { + biBitCount = (short) cMod.getPixelSize(); + biCompression = BI_RGB; + } + + biXPelsPerMeter = 0x0; + biYPelsPerMeter = 0x0; + biClrUsed = 0; + biClrImportant = 0; + biSizeImage = ((biWidth * biHeight) * 3) + + ((4 - ((biWidth * 3) % 4)) * biHeight); + out.write(intToDWord(biSize)); + out.write(intToDWord(biWidth)); + out.write(intToDWord(biHeight)); + out.write(intToWord(biPlanes)); + out.write(intToWord(biBitCount)); + out.write(intToDWord(biCompression)); + out.write(intToDWord(biSizeImage)); + out.write(intToDWord(biXPelsPerMeter)); + out.write(intToDWord(biYPelsPerMeter)); + out.write(intToDWord(biClrUsed)); + out.write(intToDWord(biClrImportant)); + } + + /** + * Converts an int to a word, where the return value is stored in a + * 2-byte array. + * + * @param val - the value to convert + * @return the array + */ + private byte[] intToWord(int val) + { + byte b[] = new byte[2]; + b[0] = (byte) (val & 0x00FF); + b[1] = (byte) ((val >> 8) & 0x00FF); + return b; + } + + /** + * Converts an int to a double word, where the return value is + * stored in a 4-byte array. + * + * @param val - the value to convert + * @return the array + */ + private byte[] intToDWord(int val) + { + byte b[] = new byte[4]; + b[0] = (byte) (val & 0x00FF); + b[1] = (byte) ((val >> 8) & 0x000000FF); + b[2] = (byte) ((val >> 16) & 0x000000FF); + b[3] = (byte) ((val >> 24) & 0x000000FF); + return b; + } + + + public void setBitCount(short bitcount) throws BMPException + { + switch (bitcount) + { + case 1: + case 4: + case 8: + case 16: + case 24: + case 32: + biBitCount = bitcount; + break; + + default: + throw new BMPException("Invalid number of bits per pixel: " + bitcount); + } + } + + public short getBitCount() + { + return biBitCount; + } + + public void setCompression(int compression) throws BMPException + { + switch (compression) + { + case BI_RLE8: + if (getBitCount() != 8) + throw new BMPException("Invalid number of bits per pixel."); + biCompression = compression; + break; + case BI_RLE4: + if (getBitCount() != 4) + throw new BMPException("Invalid number of bits per pixel."); + biCompression = compression; + break; + + case BI_RGB: + case BI_BITFIELDS: + biCompression = compression; + break; + + default: + throw new BMPException("Unknown bitmap compression type."); + } + } + + public int getNumberOfPaletteEntries() + { + if (biClrUsed == 0) + switch (biBitCount) + { + case 1: + return 2; + case 4: + return 16; + case 8: + return 256; + + default: // should not happen + return 0; + } + + return biClrUsed; + } + + public int getCompression() + { + return biCompression; + } + + public Dimension getSize() + { + return new Dimension(biWidth, biHeight); + } + + public int getWidth() + { + return biWidth; + } + + public int getHeight() + { + return biHeight; + } + + public void setSize(Dimension d) + { + biWidth = (int) d.getWidth(); + biHeight = (int) d.getHeight(); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/DecodeBF16.java b/libjava/classpath/gnu/javax/imageio/bmp/DecodeBF16.java new file mode 100644 index 000000000..2f94ac613 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/DecodeBF16.java @@ -0,0 +1,99 @@ +/* DecodeBF16.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferUShort; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.SampleModel; +import java.awt.Dimension; + +public class DecodeBF16 extends BMPDecoder { + private int[] bitmasks; + private boolean useDefaultMasks; + + public DecodeBF16(BMPFileHeader fh, BMPInfoHeader ih, + boolean udm){ + super(fh,ih); + + useDefaultMasks = udm; + if(useDefaultMasks) // 5-6-5 mask, B,G,R + bitmasks = new int[] { 0x00F800, 0x0007E0, 0x00001F }; + } + + public BufferedImage decode(ImageInputStream in) throws IOException, BMPException { + if(!useDefaultMasks) + bitmasks = readBitMasks(in); + skipToImage(in); + + Dimension d = infoHeader.getSize(); + int h = (int)d.getHeight(); + int w = (int)d.getWidth(); + + // BMP scanlines are padded to dword offsets + int scansize = (w + (w&1)) << 1; + short[] data = new short[w*h]; + + for(int y=h-1;y>=0;y--){ + byte[] scanline = new byte[scansize]; + if(in.read(scanline) != scansize) + throw new IOException("Couldn't read image data."); + + for(int x=0;x<w;x++) + data[x + y*w] = (short)((scanline[x*2] & (0xFF)) | + ((scanline[x*2+1] & (0xFF)) << 8)); + } + + ColorModel cm = new DirectColorModel(16, + bitmasks[0], bitmasks[1], bitmasks[2]); + SampleModel sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_USHORT, + w, h, + bitmasks); + DataBuffer db = new DataBufferUShort(data, w*h, 0); + WritableRaster raster = Raster.createWritableRaster(sm, db, null); + return new BufferedImage(cm, raster, false, null); + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/DecodeBF32.java b/libjava/classpath/gnu/javax/imageio/bmp/DecodeBF32.java new file mode 100644 index 000000000..bfa469488 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/DecodeBF32.java @@ -0,0 +1,103 @@ +/* DecodeBF32.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DirectColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferInt; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.SampleModel; +import java.awt.Dimension; + +public class DecodeBF32 extends BMPDecoder { + private int[] bitmasks; + private boolean useDefaultMasks; + + public DecodeBF32(BMPFileHeader fh, BMPInfoHeader ih, + boolean udm){ + super(fh,ih); + + useDefaultMasks = udm; + if(useDefaultMasks) + bitmasks = new int[] { 0x00FF0000, 0x0000FF00, 0x000000FF }; + } + + public BufferedImage decode(ImageInputStream in) throws IOException, BMPException { + if(!useDefaultMasks) + bitmasks = readBitMasks(in); + skipToImage(in); + + Dimension d = infoHeader.getSize(); + int h = (int)d.getHeight(); + int w = (int)d.getWidth(); + + // BMP scanlines are padded to dword offsets + int scansize = w << 2; + int[] data = new int[w*h]; + + + for(int y=h-1;y>=0;y--){ + byte[] scanline = new byte[scansize]; + if(in.read(scanline) != scansize) + throw new IOException("Couldn't read image data."); + + for(int x=0;x<w;x++) + data[x + y*w] = ((scanline[x<<2] & (0xFF)) | + ((scanline[(x<<2)+1] & (0xFF)) << 8) | + ((scanline[(x<<2)+2] & (0xFF)) << 16) | + ((scanline[(x<<2)+3] & (0xFF)) << 24)); + } + + ColorModel cm = new DirectColorModel(32, + bitmasks[0], bitmasks[1], bitmasks[2]); + SampleModel sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, + w, h, + bitmasks); + DataBuffer db = new DataBufferInt(data, w*h); + WritableRaster raster = Raster.createWritableRaster(sm, db, null); + + return new BufferedImage(cm, raster, false, null); + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB1.java b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB1.java new file mode 100644 index 000000000..ca81bc433 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB1.java @@ -0,0 +1,94 @@ +/* DecodeRGB1.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.SampleModel; +import java.awt.Dimension; + +public class DecodeRGB1 extends BMPDecoder { + + public DecodeRGB1(BMPFileHeader fh, BMPInfoHeader ih){ + super(fh, ih); + } + + public BufferedImage decode(ImageInputStream in) + throws IOException, BMPException { + + IndexColorModel palette = readPalette(in); + skipToImage(in); + + Dimension d = infoHeader.getSize(); + int h = (int)d.getHeight(); + int w = (int)d.getWidth(); + int size = (w*h)>>3; + + int scansize = w>>3; + byte[] data = new byte[size]; + + for(int y=h-1;y>=0;y--){ + // Scanlines are padded to dword boundries + int readsize = scansize; + if((readsize & 3) != 0) readsize += (4 - (scansize & 3)); + + byte[] scanline = new byte[readsize]; + if(in.read(scanline) != readsize) + throw new IOException("Couldn't read image data."); + + for(int x=0;x<scansize;x++) + data[x + y*scansize] = scanline[x]; + } + + SampleModel sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + w, h, 1); + + DataBuffer db = new DataBufferByte(data, size, 0); + WritableRaster raster = Raster.createWritableRaster(sm, db, null); + + return new BufferedImage(palette, raster, false, null); + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB24.java b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB24.java new file mode 100644 index 000000000..0ddcc434e --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB24.java @@ -0,0 +1,77 @@ +/* DecodeRGB24.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.awt.Dimension; + +public class DecodeRGB24 extends BMPDecoder { + + public DecodeRGB24(BMPFileHeader fh, BMPInfoHeader ih){ + super(fh, ih); + } + + public BufferedImage decode(ImageInputStream in) throws IOException, BMPException { + skipToImage(in); + + Dimension d = infoHeader.getSize(); + int h = (int)d.getHeight(); + int w = (int)d.getWidth(); + BufferedImage image = new BufferedImage(w, h, + BufferedImage.TYPE_INT_RGB); + // BMP scanlines are padded to dword offsets + int scansize = ((w*3 & 3) != 0)? w*3 + 4 - (w*3 & 3): w*3; + int[] data = new int[w*h]; + + for(int y=h-1;y>=0;y--){ + byte[] scanline = new byte[scansize]; + if(in.read(scanline) != scansize) + throw new IOException("Couldn't read image data."); + + for(int x=0;x<w;x++) + data[x + y*w] = scanline[x*3] + + (scanline[x*3+1] << 8) + + (scanline[x*3+2] << 16); + } + image.setRGB(0, 0, w, h, data, 0, w); + return image; + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB4.java b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB4.java new file mode 100644 index 000000000..a904ef745 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB4.java @@ -0,0 +1,90 @@ +/* DecodeRGB4.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.SampleModel; +import java.awt.Dimension; + +public class DecodeRGB4 extends BMPDecoder { + + public DecodeRGB4(BMPFileHeader fh, BMPInfoHeader ih){ + super(fh, ih); + } + + public BufferedImage decode(ImageInputStream in) throws IOException, BMPException { + IndexColorModel palette = readPalette(in); + skipToImage(in); + + Dimension d = infoHeader.getSize(); + int h = (int)d.getHeight(); + int w = (int)d.getWidth(); + int size = (w*h) >> 1; + + // Scanline padded to dword offsets + int wbytes = (w + (w & 1)) >> 1; + int scansize = ((wbytes & 3) != 0)? (wbytes + 4 - (wbytes&3)) : wbytes; + + byte[] data = new byte[wbytes*h]; + + for(int y=h-1;y>=0;y--){ + byte[] scanline = new byte[scansize]; + if(in.read(scanline) != scansize) + throw new IOException("Couldn't read image data."); + + for(int x=0;x<wbytes;x++) + data[x + y*wbytes] = scanline[x]; + } + SampleModel sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + w, h, 4); + + DataBuffer db = new DataBufferByte(data, w*h, 0); + WritableRaster raster = Raster.createWritableRaster(sm, db, null); + + return new BufferedImage(palette, raster, false, null); + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB8.java b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB8.java new file mode 100644 index 000000000..218047e5d --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRGB8.java @@ -0,0 +1,88 @@ +/* DecodeRGB8.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.SampleModel; +import java.awt.Dimension; + +public class DecodeRGB8 extends BMPDecoder { + + public DecodeRGB8(BMPFileHeader fh, BMPInfoHeader ih){ + super(fh, ih); + } + + public BufferedImage decode(ImageInputStream in) throws IOException, BMPException { + IndexColorModel palette = readPalette(in); + skipToImage(in); + + Dimension d = infoHeader.getSize(); + int h = (int)d.getHeight(); + int w = (int)d.getWidth(); + + // BMP scanlines are padded to dword offsets + int scansize = ((w & 3) != 0)? w + 4 - (w & 3): w; + byte[] data = new byte[w*h]; + + for(int y=h-1;y>=0;y--){ + byte[] scanline = new byte[scansize]; + if(in.read(scanline) != scansize) + throw new IOException("Couldn't read image data."); + + for(int x=0;x<w;x++) + data[x + y*w] = scanline[x]; + } + + SampleModel sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE, + w, h, + new int[] {0xFF}); + DataBuffer db = new DataBufferByte(data, w*h, 0); + WritableRaster raster = Raster.createWritableRaster(sm, db, null); + + return new BufferedImage(palette, raster, false, null); + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/DecodeRLE4.java b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRLE4.java new file mode 100644 index 000000000..1c116c247 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRLE4.java @@ -0,0 +1,175 @@ +/* DecodeRLE4.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.SampleModel; +import java.awt.Dimension; + +public class DecodeRLE4 extends BMPDecoder { + + public DecodeRLE4(BMPFileHeader fh, BMPInfoHeader ih){ + super(fh, ih); + } + + /** + * RLE control codes + */ + private static final byte ESCAPE = (byte)0; + private static final byte EOL = (byte)0; // end of line + private static final byte EOB = (byte)1; // end of bitmap + private static final byte DELTA = (byte)2; // delta + + public BufferedImage decode(ImageInputStream in) throws IOException, BMPException { + IndexColorModel palette = readPalette(in); + skipToImage(in); + + Dimension d = infoHeader.getSize(); + int h = (int)d.getHeight(); + int w = (int)d.getWidth(); + + byte[] data = uncompress(w, h, in); + SampleModel sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + w, h, 4); + + DataBuffer db = new DataBufferByte(data, w*h, 0); + WritableRaster raster = Raster.createWritableRaster(sm, db, null); + + return new BufferedImage(palette, raster, false, null); + } + + private byte[] uncompress(int w, int h, ImageInputStream in) + throws BMPException, IOException { + byte[] cmd = new byte[2]; + byte[] data = new byte[w*h>>1]; + int offIn = 0; + int x=0,y=0; + + // width in bytes + w += (w&1); + w = w >> 1; + + try { + while(((x>>1) + y*w) < w*h){ + if(in.read(cmd) != 2) + throw new IOException("Error reading compressed data."); + + if(cmd[0] == ESCAPE){ + switch(cmd[1]){ + case EOB: // end of bitmap + return data; + case EOL: // end of line + x = 0; + y++; + break; + case DELTA: // delta + if(in.read(cmd) != 2) + throw new IOException("Error reading compressed data."); + int dx = cmd[0] & (0xFF); + int dy = cmd[1] & (0xFF); + x += dx; + y += dy; + break; + + default: + // decode a literal run + int length = cmd[1] & (0xFF); + + // size of run, which is word aligned. + int bytesize = length; + bytesize += (bytesize & 1); + bytesize >>= 1; + bytesize += (bytesize & 1); + + byte[] run = new byte[bytesize]; + if(in.read(run) != bytesize) + throw new IOException("Error reading compressed data."); + + if((x&1) == 0){ + length += (length&1); + length >>= 1; + System.arraycopy(run, 0, data, ((x>>1) + w*(h-y-1)), + length); + } else { + for(int i=0;i<length;i++){ + if((i&1) == 0) // copy high to low + data[((x+i)>>1) + w*(h-y-1)] + |= ((run[i>>1]&0xF0) >> 4); + else // copy low to high + data[((x+i)>>1) + w*(h-y-1)] + |= ((run[i>>1]&0x0F) << 4); + } + } + x += cmd[1] & (0xFF); + break; + } + } else { + // decode a byte run + int length = cmd[0] & (0xFF); + if((x&1) == 0){ + length += (length&1); + length >>= 1; + for(int i=0;i<length;i++) + data[(h-y-1)*w + i + (x >> 1)] = cmd[1]; + } else { + for(int i=0;i<length;i++){ + if((i&1) == 0) // copy high to low + data[((x+i)>>1) + w*(h-y-1)] + |= ((cmd[1]&0xF0) >> 4); + else // copy low to high + data[((x+i)>>1) + w*(h-y-1)] + |= ((cmd[1]&0x0F) << 4); + } + } + x += cmd[0] & (0xFF); + } + } + return data; + } catch(ArrayIndexOutOfBoundsException e){ + throw new BMPException("Invalid RLE data."); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/DecodeRLE8.java b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRLE8.java new file mode 100644 index 000000000..afc3da89e --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/DecodeRLE8.java @@ -0,0 +1,142 @@ +/* DecodeRLE8.java -- + Copyright (C) 2005 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.bmp; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.SampleModel; +import java.awt.Dimension; + +public class DecodeRLE8 extends BMPDecoder { + + public DecodeRLE8(BMPFileHeader fh, BMPInfoHeader ih){ + super(fh, ih); + } + + /** + * RLE control codes + */ + private static final byte ESCAPE = (byte)0; + private static final byte EOL = (byte)0; // end of line + private static final byte EOB = (byte)1; // end of bitmap + private static final byte DELTA = (byte)2; // delta + + public BufferedImage decode(ImageInputStream in) throws IOException, BMPException { + IndexColorModel palette = readPalette(in); + skipToImage(in); + + Dimension d = infoHeader.getSize(); + int h = (int)d.getHeight(); + int w = (int)d.getWidth(); + + byte[] data = uncompress(w, h, in); + SampleModel sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE, + w, h, + new int[] {0xFF}); + DataBuffer db = new DataBufferByte(data, w*h, 0); + WritableRaster raster = Raster.createWritableRaster(sm, db, null); + + return new BufferedImage(palette, raster, false, null); + } + + private byte[] uncompress(int w, int h, ImageInputStream in) + throws BMPException, IOException { + byte[] cmd = new byte[2]; + byte[] data = new byte[w*h]; + int offIn = 0; + int x=0,y=0; + + try { + while((x + y*w) < w*h){ + if(in.read(cmd) != 2) + throw new IOException("Error reading compressed data."); + + if(cmd[0] == ESCAPE){ + switch(cmd[1]){ + case EOB: // end of bitmap + return data; + case EOL: // end of line + x = 0; + y++; + break; + case DELTA: // delta + if(in.read(cmd) != 2) + throw new IOException("Error reading compressed data."); + int dx = cmd[0] & (0xFF); + int dy = cmd[1] & (0xFF); + x += dx; + y += dy; + break; + + default: + // decode a literal run + int length = cmd[1] & (0xFF); + int copylength = length; + + // absolute mode must be word-aligned + length += (length & 1); + + byte[] run = new byte[length]; + if(in.read(run) != length) + throw new IOException("Error reading compressed data."); + + System.arraycopy(run, 0, data, (x+w*(h-y-1)), + copylength); + x += copylength; + break; + } + } else { + // decode a byte run + int length = cmd[0] & (0xFF); + for(int i=0;i<length;i++) + data[(h-y-1)*w + x++] = cmd[1]; + } + } + return data; + } catch(ArrayIndexOutOfBoundsException e){ + throw new BMPException("Invalid RLE data."); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB1.java b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB1.java new file mode 100644 index 000000000..ffe671dc0 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB1.java @@ -0,0 +1,128 @@ +/* EncodeRGB1.java -- + 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.bmp; + +import java.awt.image.BufferedImage; +import java.awt.image.PixelGrabber; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class EncodeRGB1 + extends BMPEncoder +{ + protected BMPInfoHeader infoHeader; + protected BMPFileHeader fileHeader; + protected long offset; + + /** + * Constructs an instance of this class. + * + * @param fh - the file header to use. + * @param ih - the info header to use. + */ + public EncodeRGB1(BMPFileHeader fh, BMPInfoHeader ih) + { + super(); + fileHeader = fh; + infoHeader = ih; + offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE; + } + + /** + * The image encoder. + * + * @param o - the image output stream + * @param streamMetadata - metadata associated with this stream, or + * null + * @param image - an IIOImage containing image data. + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + */ + public void encode(ImageOutputStream o, IIOMetadata streamMetadata, + IIOImage image, ImageWriteParam param) throws IOException + { + int size; + int value; + int j; + int rowCount; + int rowIndex; + int lastRowIndex; + int[] bitmap; + byte rgb[] = new byte[1]; + size = (infoHeader.biWidth * infoHeader.biHeight) - 1; + rowCount = 1; + rowIndex = size - infoHeader.biWidth; + lastRowIndex = rowIndex; + try + { + bitmap = new int[infoHeader.biWidth * infoHeader.biHeight]; + PixelGrabber pg = new PixelGrabber((BufferedImage) image.getRenderedImage(), + 0, 0, infoHeader.biWidth, + infoHeader.biHeight, bitmap, 0, + infoHeader.biWidth); + pg.grabPixels(); + + for (j = 0; j < size; j++) + { + value = bitmap[rowIndex]; + + rgb[0] = (byte) (value & 0xFF); + + o.write(rgb); + if (rowCount == infoHeader.biWidth) + { + rowCount = 1; + rowIndex = lastRowIndex - infoHeader.biWidth; + lastRowIndex = rowIndex; + } + else + rowCount++; + rowIndex++; + } + } + catch (Exception wb) + { + wb.printStackTrace(); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB16.java b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB16.java new file mode 100644 index 000000000..a5450cc67 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB16.java @@ -0,0 +1,129 @@ +/* EncodeRGB16.java -- + 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.bmp; + +import java.awt.image.BufferedImage; +import java.awt.image.PixelGrabber; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class EncodeRGB16 + extends BMPEncoder +{ + protected BMPInfoHeader infoHeader; + protected BMPFileHeader fileHeader; + protected long offset; + + /** + * Constructs an instance of this class. + * + * @param fh - the file header to use. + * @param ih - the info header to use. + */ + public EncodeRGB16(BMPFileHeader fh, BMPInfoHeader ih) + { + super(); + fileHeader = fh; + infoHeader = ih; + offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE; + } + + /** + * The image encoder. + * + * @param o - the image output stream + * @param streamMetadata - metadata associated with this stream, or + * null + * @param image - an IIOImage containing image data. + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + */ + public void encode(ImageOutputStream o, IIOMetadata streamMetadata, + IIOImage image, ImageWriteParam param) throws IOException + { + int size; + int value; + int j; + int rowCount; + int rowIndex; + int lastRowIndex; + int[] bitmap; + byte rgb[] = new byte[2]; + size = (infoHeader.biWidth * infoHeader.biHeight) - 1; + rowCount = 1; + rowIndex = size - infoHeader.biWidth; + lastRowIndex = rowIndex; + try + { + bitmap = new int[infoHeader.biWidth * infoHeader.biHeight]; + PixelGrabber pg = new PixelGrabber((BufferedImage) image.getRenderedImage(), + 0, 0, infoHeader.biWidth, + infoHeader.biHeight, bitmap, 0, + infoHeader.biWidth); + pg.grabPixels(); + + for (j = 0; j < size; j++) + { + value = bitmap[rowIndex]; + + rgb[0] = (byte) (value & 0xFF); + rgb[1] = (byte) (value >> 8 & 0xFF); + + o.write(rgb); + if (rowCount == infoHeader.biWidth) + { + rowCount = 1; + rowIndex = lastRowIndex - infoHeader.biWidth; + lastRowIndex = rowIndex; + } + else + rowCount++; + rowIndex++; + } + } + catch (Exception wb) + { + wb.printStackTrace(); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB24.java b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB24.java new file mode 100644 index 000000000..7fbc83e2e --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB24.java @@ -0,0 +1,129 @@ +/* EncodeRGB24.java -- + 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.bmp; + +import java.awt.image.BufferedImage; +import java.awt.image.PixelGrabber; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class EncodeRGB24 + extends BMPEncoder +{ + protected BMPInfoHeader infoHeader; + protected BMPFileHeader fileHeader; + protected long offset; + + /** + * Constructs an instance of this class. + * + * @param fh - the file header to use. + * @param ih - the info header to use. + */ + public EncodeRGB24(BMPFileHeader fh, BMPInfoHeader ih) + { + super(); + fileHeader = fh; + infoHeader = ih; + offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE; + } + + /** + * The image encoder. + * + * @param o - the image output stream + * @param streamMetadata - metadata associated with this stream, or + * null + * @param image - an IIOImage containing image data. + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + */ + public void encode(ImageOutputStream o, IIOMetadata streamMetadata, + IIOImage image, ImageWriteParam param) throws IOException + { + int size; + int value; + int j; + int rowCount; + int rowIndex; + int lastRowIndex; + int[] bitmap; + byte rgb[] = new byte[3]; + size = (infoHeader.biWidth * infoHeader.biHeight) - 1; + rowCount = 1; + rowIndex = size - infoHeader.biWidth; + lastRowIndex = rowIndex; + try + { + bitmap = new int[infoHeader.biWidth * infoHeader.biHeight]; + PixelGrabber pg = new PixelGrabber((BufferedImage) image.getRenderedImage(), + 0, 0, infoHeader.biWidth, + infoHeader.biHeight, bitmap, 0, + infoHeader.biWidth); + pg.grabPixels(); + + for (j = 0; j < size; j++) + { + value = bitmap[rowIndex]; + + rgb[0] = (byte) (value & 0xFF); + rgb[1] = (byte) ((value >> 8) & 0xFF); + rgb[2] = (byte) ((value >> 16) & 0xFF); + o.write(rgb); + if (rowCount == infoHeader.biWidth) + { + rowCount = 1; + rowIndex = lastRowIndex - infoHeader.biWidth; + lastRowIndex = rowIndex; + } + else + rowCount++; + rowIndex++; + } + } + catch (Exception wb) + { + wb.printStackTrace(); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB32.java b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB32.java new file mode 100644 index 000000000..7deca3049 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB32.java @@ -0,0 +1,129 @@ +/* EncodeRGB32.java -- + 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.bmp; + +import java.awt.image.BufferedImage; +import java.awt.image.PixelGrabber; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class EncodeRGB32 + extends BMPEncoder +{ + protected BMPInfoHeader infoHeader; + protected BMPFileHeader fileHeader; + protected long offset; + + /** + * Constructs an instance of this class. + * + * @param fh - the file header to use. + * @param ih - the info header to use. + */ + public EncodeRGB32(BMPFileHeader fh, BMPInfoHeader ih) + { + super(); + fileHeader = fh; + infoHeader = ih; + offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE; + } + + /** + * The image encoder. + * + * @param o - the image output stream + * @param streamMetadata - metadata associated with this stream, or null + * @param image - an IIOImage containing image data. + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + */ + public void encode(ImageOutputStream o, IIOMetadata streamMetadata, + IIOImage image, ImageWriteParam param) throws IOException + { + int size; + int value; + int j; + int rowCount; + int rowIndex; + int lastRowIndex; + int[] bitmap; + byte rgb[] = new byte[4]; + size = (infoHeader.biWidth * infoHeader.biHeight) - 1; + rowCount = 1; + rowIndex = size - infoHeader.biWidth; + lastRowIndex = rowIndex; + try + { + bitmap = new int[infoHeader.biWidth * infoHeader.biHeight]; + PixelGrabber pg = new PixelGrabber((BufferedImage) image.getRenderedImage(), + 0, 0, infoHeader.biWidth, + infoHeader.biHeight, bitmap, 0, + infoHeader.biWidth); + pg.grabPixels(); + + for (j = 0; j < size; j++) + { + value = bitmap[rowIndex]; + + rgb[0] = (byte) (value & 0xFF); + rgb[1] = (byte) ((value >> 8) & 0xFF); + rgb[2] = (byte) ((value >> 16) & 0xFF); + rgb[3] = (byte) ((value >> 24) & 0xFF); + o.write(rgb); + if (rowCount == infoHeader.biWidth) + { + rowCount = 1; + rowIndex = lastRowIndex - infoHeader.biWidth; + lastRowIndex = rowIndex; + } + else + rowCount++; + rowIndex++; + } + } + catch (Exception wb) + { + wb.printStackTrace(); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB4.java b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB4.java new file mode 100644 index 000000000..b62283a7d --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB4.java @@ -0,0 +1,128 @@ +/* EncodeRGB4.java -- + 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.bmp; + +import java.awt.image.BufferedImage; +import java.awt.image.PixelGrabber; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class EncodeRGB4 + extends BMPEncoder +{ + protected BMPInfoHeader infoHeader; + protected BMPFileHeader fileHeader; + protected long offset; + + /** + * Constructs an instance of this class. + * + * @param fh - the file header to use. + * @param ih - the info header to use. + */ + public EncodeRGB4(BMPFileHeader fh, BMPInfoHeader ih) + { + super(); + fileHeader = fh; + infoHeader = ih; + offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE; + } + + /** + * The image encoder. + * + * @param o - the image output stream + * @param streamMetadata - metadata associated with this stream, or + * null + * @param image - an IIOImage containing image data. + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + */ + public void encode(ImageOutputStream o, IIOMetadata streamMetadata, + IIOImage image, ImageWriteParam param) throws IOException + { + int size; + int value; + int j; + int rowCount; + int rowIndex; + int lastRowIndex; + int[] bitmap; + byte rgb[] = new byte[1]; + size = (infoHeader.biWidth * infoHeader.biHeight) - 1; + rowCount = 1; + rowIndex = size - infoHeader.biWidth; + lastRowIndex = rowIndex; + try + { + bitmap = new int[infoHeader.biWidth * infoHeader.biHeight]; + PixelGrabber pg = new PixelGrabber((BufferedImage) image.getRenderedImage(), + 0, 0, infoHeader.biWidth, + infoHeader.biHeight, bitmap, 0, + infoHeader.biWidth); + pg.grabPixels(); + + for (j = 0; j < size; j++) + { + value = bitmap[rowIndex]; + + rgb[0] = (byte) (value & 0xFF); + + o.write(rgb); + if (rowCount == infoHeader.biWidth) + { + rowCount = 1; + rowIndex = lastRowIndex - infoHeader.biWidth; + lastRowIndex = rowIndex; + } + else + rowCount++; + rowIndex++; + } + } + catch (Exception wb) + { + wb.printStackTrace(); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB8.java b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB8.java new file mode 100644 index 000000000..ef0594a5f --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRGB8.java @@ -0,0 +1,127 @@ +/* EncodeRGB8.java -- + 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.bmp; + +import java.awt.image.BufferedImage; +import java.awt.image.PixelGrabber; +import java.io.IOException; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class EncodeRGB8 + extends BMPEncoder +{ + protected BMPInfoHeader infoHeader; + protected BMPFileHeader fileHeader; + protected long offset; + + /** + * Constructs an instance of this class. + * + * @param fh - the file header to use. + * @param ih - the info header to use. + */ + public EncodeRGB8(BMPFileHeader fh, BMPInfoHeader ih) + { + super(); + fileHeader = fh; + infoHeader = ih; + offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE; + } + + /** + * The image encoder. + * + * @param o - the image output stream + * @param streamMetadata - metadata associated with this stream, or + * null + * @param image - an IIOImage containing image data. + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + */ + public void encode(ImageOutputStream o, IIOMetadata streamMetadata, + IIOImage image, ImageWriteParam param) throws IOException + { + int size; + int value; + int j; + int rowCount; + int rowIndex; + int lastRowIndex; + int[] bitmap; + byte rgb[] = new byte[1]; + size = (infoHeader.biWidth * infoHeader.biHeight) - 1; + rowCount = 1; + rowIndex = size - infoHeader.biWidth; + lastRowIndex = rowIndex; + try + { + bitmap = new int[infoHeader.biWidth * infoHeader.biHeight]; + PixelGrabber pg = new PixelGrabber((BufferedImage) image.getRenderedImage(), + 0, 0, infoHeader.biWidth, + infoHeader.biHeight, bitmap, 0, + infoHeader.biWidth); + pg.grabPixels(); + + for (j = 0; j < size; j++) + { + value = bitmap[rowIndex]; + + rgb[0] = (byte) (value & 0xFF); + o.write(rgb); + if (rowCount == infoHeader.biWidth) + { + rowCount = 1; + rowIndex = lastRowIndex - infoHeader.biWidth; + lastRowIndex = rowIndex; + } + else + rowCount++; + rowIndex++; + } + } + catch (Exception wb) + { + wb.printStackTrace(); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/EncodeRLE4.java b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRLE4.java new file mode 100644 index 000000000..c54c3ca87 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRLE4.java @@ -0,0 +1,269 @@ +/* EncodeRLE4.java -- + 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.bmp; + +import java.awt.image.BufferedImage; +import java.awt.image.PixelGrabber; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class EncodeRLE4 + extends BMPEncoder +{ + protected BMPInfoHeader infoHeader; + protected BMPFileHeader fileHeader; + protected long offset; + + /** + * RLE control codes + */ + private static final byte ESCAPE = (byte)0; + private static final byte EOL = (byte)0; // end of line + private static final byte EOB = (byte)1; // end of bitmap + private static final byte DELTA = (byte)2; // delta + + /** + * Constructs an instance of this class. + * + * @param fh - the file header to use. + * @param ih - the info header to use. + */ + public EncodeRLE4(BMPFileHeader fh, BMPInfoHeader ih) + { + super(); + fileHeader = fh; + infoHeader = ih; + offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE; + } + + /** + * The image encoder. + * + * @param o - the image output stream + * @param streamMetadata - metadata associated with this stream, or + * null + * @param image - an IIOImage containing image data. + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + */ + public void encode(ImageOutputStream o, IIOMetadata streamMetadata, + IIOImage image, ImageWriteParam param) throws IOException + { + int size; + int value; + int j; + int rowCount; + int rowIndex; + int lastRowIndex; + int[] bitmap; + size = (infoHeader.biWidth * infoHeader.biHeight) - 1; + rowCount = 1; + rowIndex = size - infoHeader.biWidth; + lastRowIndex = rowIndex; + ByteBuffer buf = ByteBuffer.allocate(size); + try + { + bitmap = new int[infoHeader.biWidth * infoHeader.biHeight]; + PixelGrabber pg = new PixelGrabber((BufferedImage) image.getRenderedImage(), + 0, 0, infoHeader.biWidth, + infoHeader.biHeight, bitmap, 0, + infoHeader.biWidth); + pg.grabPixels(); + + for (j = 0; j < size; j++) + { + value = bitmap[rowIndex]; + buf.put((byte) (value & 0xFF)); + + if (rowCount == infoHeader.biWidth) + { + rowCount = 1; + rowIndex = lastRowIndex - infoHeader.biWidth; + lastRowIndex = rowIndex; + } + else + rowCount++; + rowIndex++; + } + + buf.flip(); + o.write(uncompress(infoHeader.biWidth, infoHeader.biHeight, buf)); + } + catch (Exception wb) + { + wb.printStackTrace(); + } + } + + /** + * Uncompresses the image stored in the buffer. + * + * @param w - the width of the image + * @param h - the height of the image + * @param buf - the ByteBuffer containing the pixel values. + * @return byte array containing the uncompressed image + * @throws IOException if an error is encountered while reading + * buffer. + */ + private byte[] uncompress(int w, int h, ByteBuffer buf) + throws IOException + { + byte[] cmd = new byte[2]; + byte[] data = new byte[w * h >> 1]; + int offIn = 0; + int x = 0, y = 0; + + w += (w & 1); + w = w >> 1; + + try + { + while (((x >> 1) + y * w) < w * h) + { + try + { + buf.get(cmd); + } + catch (BufferUnderflowException e) + { + throw new IOException("Error reading compressed data."); + } + + if (cmd[0] == ESCAPE) + { + switch (cmd[1]) + { + case EOB: + return data; + case EOL: + x = 0; + y++; + break; + case DELTA: + try + { + buf.get(cmd); + } + catch (BufferUnderflowException e) + { + throw new IOException("Error reading compressed data."); + } + + int dx = cmd[0] & (0xFF); + int dy = cmd[1] & (0xFF); + x += dx; + y += dy; + break; + + default: + int length = cmd[1] & (0xFF); + + int bytesize = length; + bytesize += (bytesize & 1); + bytesize >>= 1; + bytesize += (bytesize & 1); + + byte[] run = new byte[bytesize]; + try + { + buf.get(run); + } + catch (BufferUnderflowException e) + { + throw new IOException("Error reading compressed data."); + } + + if ((x & 1) == 0) + { + length += (length & 1); + length >>= 1; + System.arraycopy(run, 0, data, + ((x >> 1) + w * (h - y - 1)), length); + } + else + { + for (int i = 0; i < length; i++) + { + if ((i & 1) == 0) + data[((x + i) >> 1) + w * (h - y - 1)] |= ((run[i >> 1] & 0xF0) >> 4); + else + data[((x + i) >> 1) + w * (h - y - 1)] |= ((run[i >> 1] & 0x0F) << 4); + } + } + x += cmd[1] & (0xFF); + break; + } + } + else + { + int length = cmd[0] & (0xFF); + if ((x & 1) == 0) + { + length += (length & 1); + length >>= 1; + for (int i = 0; i < length; i++) + data[(h - y - 1) * w + i + (x >> 1)] = cmd[1]; + } + else + { + for (int i = 0; i < length; i++) + { + if ((i & 1) == 0) + data[((x + i) >> 1) + w * (h - y - 1)] |= ((cmd[1] & 0xF0) >> 4); + else + data[((x + i) >> 1) + w * (h - y - 1)] |= ((cmd[1] & 0x0F) << 4); + } + } + x += cmd[0] & (0xFF); + } + } + return data; + } + catch (ArrayIndexOutOfBoundsException e) + { + throw new BMPException("Invalid RLE data."); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/bmp/EncodeRLE8.java b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRLE8.java new file mode 100644 index 000000000..62277ef90 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/bmp/EncodeRLE8.java @@ -0,0 +1,234 @@ +/* EncodeRGB32.java -- + 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.bmp; + +import java.awt.image.BufferedImage; +import java.awt.image.PixelGrabber; +import java.io.IOException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; + +import javax.imageio.IIOImage; +import javax.imageio.ImageWriteParam; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.stream.ImageOutputStream; + +public class EncodeRLE8 + extends BMPEncoder +{ + protected BMPInfoHeader infoHeader; + protected BMPFileHeader fileHeader; + protected long offset; + + /** + * RLE control codes + */ + private static final byte ESCAPE = (byte)0; + private static final byte EOL = (byte)0; // end of line + private static final byte EOB = (byte)1; // end of bitmap + private static final byte DELTA = (byte)2; // delta + + /** + * Constructs an instance of this class. + * + * @param fh - the file header to use. + * @param ih - the info header to use. + */ + public EncodeRLE8(BMPFileHeader fh, BMPInfoHeader ih) + { + super(); + fileHeader = fh; + infoHeader = ih; + offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE; + } + + /** + * The image encoder. + * + * @param o - the image output stream + * @param streamMetadata - metadata associated with this stream, or + * null + * @param image - an IIOImage containing image data. + * @param param - image writing parameters, or null + * @exception IOException if a write error occurs + */ + public void encode(ImageOutputStream o, IIOMetadata streamMetadata, + IIOImage image, ImageWriteParam param) throws IOException + { + int size; + int value; + int j; + int rowCount; + int rowIndex; + int lastRowIndex; + int[] bitmap; + size = (infoHeader.biWidth * infoHeader.biHeight) - 1; + rowCount = 1; + rowIndex = size - infoHeader.biWidth; + lastRowIndex = rowIndex; + ByteBuffer buf = ByteBuffer.allocate(size); + try + { + bitmap = new int[infoHeader.biWidth * infoHeader.biHeight]; + PixelGrabber pg = new PixelGrabber((BufferedImage) image.getRenderedImage(), + 0, 0, infoHeader.biWidth, + infoHeader.biHeight, bitmap, 0, + infoHeader.biWidth); + pg.grabPixels(); + + for (j = 0; j < size; j++) + { + value = bitmap[rowIndex]; + buf.put((byte) (value & 0xFF)); + + if (rowCount == infoHeader.biWidth) + { + rowCount = 1; + rowIndex = lastRowIndex - infoHeader.biWidth; + lastRowIndex = rowIndex; + } + else + rowCount++; + rowIndex++; + } + + buf.flip(); + o.write(uncompress(infoHeader.biWidth, infoHeader.biHeight, buf)); + } + catch (Exception wb) + { + wb.printStackTrace(); + } + } + + + /** + * Uncompresses the image stored in the buffer. + * + * @param w - the width of the image + * @param h - the height of the image + * @param buf - the ByteBuffer containing the pixel values. + * @return byte array containing the uncompressed image + * @throws IOException if an error is encountered while reading + * buffer. + */ + private byte[] uncompress(int w, int h, ByteBuffer buf) throws IOException + { + byte[] cmd = new byte[2]; + byte[] data = new byte[w * h]; + int offIn = 0; + int x = 0, y = 0; + + try + { + while ((x + y * w) < w * h) + { + try + { + buf.get(cmd); + } + catch (BufferUnderflowException e) + { + throw new IOException("Error reading compressed data."); + } + + if (cmd[0] == ESCAPE) + { + switch (cmd[1]) + { + case EOB: + return data; + case EOL: + x = 0; + y++; + break; + case DELTA: + try + { + buf.get(cmd); + } + catch (BufferUnderflowException e) + { + throw new IOException("Error reading compressed data."); + } + + int dx = cmd[0] & (0xFF); + int dy = cmd[1] & (0xFF); + x += dx; + y += dy; + break; + + default: + int length = cmd[1] & (0xFF); + int copylength = length; + + length += (length & 1); + + byte[] run = new byte[length]; + + try + { + buf.get(run); + } + catch (BufferUnderflowException e) + { + throw new IOException("Error reading compressed data."); + } + + System.arraycopy(run, 0, data, (x + w * (h - y - 1)), + copylength); + x += copylength; + break; + } + } + else + { + int length = cmd[0] & (0xFF); + for (int i = 0; i < length; i++) + data[(h - y - 1) * w + x++] = cmd[1]; + } + } + return data; + } + catch (ArrayIndexOutOfBoundsException e) + { + throw new BMPException("Invalid RLE data."); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/gif/GIFFile.java b/libjava/classpath/gnu/javax/imageio/gif/GIFFile.java new file mode 100644 index 000000000..941397a0e --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/gif/GIFFile.java @@ -0,0 +1,709 @@ +/* GIFFile.java -- GIF decoder + 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.gif; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Vector; + +/** + * GIFFile - reads a GIF file. + * + * This class only does the bare minimum work, and returns the data in raw + * formats (described below). The class is J2ME compatible, and hopefully + * we can keep it that way without any significant overhead. + * + * @author Sven de Marothy. + */ +public class GIFFile +{ + // "NETSCAPE2.0" - identifier + private final static byte[] nsBlock = new byte[] + {0x4e, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e, 0x30 }; + + /** + * Block identifiers + */ + private final static int EXTENSION = 0x21; + private final static int LOCAL = 0x2C; + private final static int TERMINATOR = 0x3B; + + /** + * Extension block types + */ + private final static int EXTENSION_COMMENT = 254; + private final static int EXTENSION_GCONTROL = 249; + private final static int EXTENSION_APPLICATION = 255; + + /** + * Undraw commands for animation. + */ + private final static int UNDRAW_OVERWRITE = 1; + private final static int UNDRAW_RESTORE_BACKGROUND = 2; + private final static int UNDRAW_RESTORE_PREVIOUS = 3; + + /** + * Image position and dimensions (images may be partial) + */ + private int x, y, width, height; + + /** + * Global dimensions + */ + private int globalWidth, globalHeight; + + /** + * Background color index. + */ + private byte bgIndex; + + /** + * Number of colors + */ + private int nColors; + + /** + * Global palette, if any + */ + private byte[] globalPalette; + + /** + * Any + */ + private boolean hasGlobalColorMap; + + /** + * Local palette, if any (used if available) + */ + private byte[] localPalette; + + /** + * Interlaced GIF or not? + */ + private boolean interlaced; + + /** + * Has transparency? + */ + private boolean hasTransparency; + + /** + * Undraw mode (animations) + */ + private int undraw; + + /** + * Transparent index; + */ + private int transparentIndex; + + /** + * The uncompressed raster + */ + private byte[] raster; + + /** + * The compressed data (freed after uncompressing) + */ + private byte[] compressedData; + + /** + * Frame delay in 100ths of a second ( centiseconds, metrically ) + */ + private int duration; + + /** + * Indices used during decompression + */ + private int dataBlockIndex; + + /** + * The file comment , if a comment block exists. + */ + private String comment; + + /** + * Fields used by getBits() + */ + private int remainingBits = 0; + private int currentBits = 0; + + /** + * Netscape animation extension + */ + private boolean isLooped = false; + + /** Number of loops, 0 = infinite */ + private int loops; + + /** + * Additional frames if it's an animated GIF. + */ + private Vector animationFrames; + + /** + * Loads the file from an input stream, which is not closed. + * @throws IOException if an I/O error occured. + * @throws GIFException if some file parsing error occured + */ + public GIFFile(InputStream in) throws IOException, GIFException + { + // Validate the signature + if( !readSignature( in ) ) + throw new GIFException("Invalid GIF signature."); + + { + byte[] data = new byte[7]; + if (in.read(data) != 7) + throw new IOException("Couldn't read global descriptor."); + + globalWidth = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF); + globalHeight = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF); + byte flags = data[4]; + bgIndex = data[5]; + nColors = (1 << (( flags & 0x07) + 1)); + hasGlobalColorMap = ((flags & 0x80) != 0); + } + + if( hasGlobalColorMap ) + { + globalPalette = new byte[ nColors * 3 ]; + if( in.read( globalPalette ) != nColors * 3 ) + throw new IOException("Couldn't read color map."); + } + + int c = in.read(); + while( c == EXTENSION ) + { + readExtension( in ); + c = in.read(); + } + + if( c != LOCAL ) + throw new GIFException("Extension blocks not followed by a local descriptor ("+c+")"); + + loadImage( in ); + c = in.read(); + + if( c == TERMINATOR ) // Not an animated GIF. + return; + + // Load animation frames. Just quit if an error occurs instead + // of throwing an exception. + animationFrames = new Vector(); + try + { + while( c != TERMINATOR ) + { + animationFrames.add( new GIFFile( this, in, c ) ); + c = in.read(); + } + } + catch(IOException ioe) + { + } + catch(GIFException gife) + { + } + } + + /** + * Constructor for additional animation frames. + */ + private GIFFile(GIFFile parent, InputStream in, int c) + throws IOException, GIFException + { + // Copy global properties. + globalWidth = parent.globalWidth; + globalHeight = parent.globalHeight; + nColors = parent.nColors; + globalPalette = parent.globalPalette; + hasGlobalColorMap = parent.hasGlobalColorMap; + interlaced = parent.interlaced; + comment = parent.comment; + isLooped = parent.isLooped; + loops = parent.loops; + + while( c == EXTENSION ) + { + readExtension( in ); + c = in.read(); + } + + if( c != LOCAL ) + throw new GIFException("Extension blocks not followed by a local descriptor ("+c+")"); + + loadImage( in ); + } + + /** + * Reads a GIF file signature from an inputstream and checks it. + * + * @param in - the stream (reads 6 bytes, does not close or reset). + * @return true if the signature is a valid GIF signature. + * @throws IOException if the signature could not be read. + */ + public static boolean readSignature( InputStream in ) throws IOException + { + byte[] data = new byte[6]; + if (in.read(data) != 6) + throw new IOException("Couldn't read signature."); + + if( data[0] != 0x47 || data[1] != 0x49 || data[2] != 0x46 || + data[3] != 0x38 ) // GIF8 + return false; + + if( (data[4] != 0x39 && data[4] != 0x37) || // 7 | 9 + (data[5] != 0x61 && data[5] != 0x62) ) // 'a' or 'b' + return false; + return true; + } + + + /** + * Loads the image local descriptor and then loads/decodes the image raster, + * and then performs any necessary postprocessing like deinterlacing. + */ + private void loadImage(InputStream in) + throws IOException, GIFException + { + readLocal( in ); + + try + { + decodeRaster( in ); + } + catch(ArrayIndexOutOfBoundsException aioobe) + { + throw new GIFException("Error decompressing image."); + } + + if( interlaced ) // Clean up + deinterlace(); + packPixels(); + } + + /** + * Pack the pixels if it's a 2, 4 or 16 color image. + * While GIF may support any number of colors from 2-256, we won't bother + * trying to pack pixels not resulting in even byte boundaries. + * (AWT doesn't support that anyway, and most apps do the same.) + */ + private void packPixels() + { + if( nColors != 2 && nColors != 4 && nColors != 16 ) + return; + + int nbits = 1; + int ppbyte = 8; + if( nColors == 4 ) + { + nbits = 2; + ppbyte = 4; + } + else if( nColors == 16 ) + { + nbits = 4; + ppbyte = 2; + } + + int rem = (width & (ppbyte - 1)); + int w = ( rem == 0 ) ? (width / ppbyte) : + ((width + ppbyte - rem) / ppbyte); + byte[] nr = new byte[ w * height ]; + for(int j = 0; j < height; j++) + { + for(int i = 0; i < width - ppbyte; i += ppbyte) + for(int k = 0; k < ppbyte; k++) + nr[ j * w + (i / ppbyte) ] |= (byte)((raster[ width * j + i + k ] + << (8 - nbits * (1 + k)))); + for(int i = 0; i < rem; i++) + nr[ j * w + w - 1 ] |= (byte)((raster[ width * j + width - rem + i ] + << (nbits * (rem - i)))); + } + raster = nr; + } + + /** + * Returns the (global) width + */ + public int getWidth() + { + return width; + } + + /** + * Returns the image height + */ + public int getHeight() + { + return height; + } + + /** + * Returns the # of colors. + */ + public int getNColors() + { + return nColors; + } + + /** + * Returns whether the GIF has transparency. + */ + public boolean hasTransparency() + { + return hasTransparency; + } + + /** + * Returns the index of the transparent color. + */ + public int getTransparentIndex() + { + return transparentIndex; + } + + /** + * Retuns the GIF file comment, or null if none exists. + */ + public String getComment() + { + return comment; + } + + /** + * Get duration of the frame for animations. + */ + public int getDuration() + { + return duration; + } + + /** + * Deinterlaces the image. + */ + private void deinterlace() + { + byte[] nr = new byte[ width * height ]; + int n = 0; + for(int i = 0; i < ((height + 7) >> 3); i++) + { + System.arraycopy( raster, n, nr, width * i * 8, width ); + n += width; + } + for(int i = 0; i < ((height + 3) >> 3); i++) + { + System.arraycopy( raster, n, nr, width * ( 8 * i + 4 ), width ); + n += width; + } + for(int i = 0; i < (height >> 2); i++) + { + System.arraycopy( raster, n, nr, width * (4 * i + 2), width ); + n += width; + } + for(int i = 0; i < (height >> 1); i++) + { + System.arraycopy( raster, n, nr, width * (2 * i + 1), width ); + n += width; + } + raster = nr; + } + + /** + * Reads the local descriptor + */ + private void readLocal(InputStream in) throws IOException + { + byte[] data = new byte[9]; + if (in.read(data) != 9) + throw new IOException("Couldn't read local descriptor."); + x = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF); + y = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF); + width = ((data[5] & 0xFF) << 8) | (data[4] & 0xFF); + height = ((data[7] & 0xFF) << 8) | (data[6] & 0xFF); + byte flags = data[8]; + interlaced = (( flags & 0x40 ) != 0); + if( (flags & 0x80) != 0 ) + { // has a local color map + int nLocalColors = (1 << (( flags & 0x07) + 1)); + if( !hasGlobalColorMap ) + nColors = nLocalColors; + localPalette = new byte[ nLocalColors * 3 ]; + if( in.read( localPalette ) != nLocalColors * 3 ) + throw new IOException("Couldn't read color map."); + } + } + + /** + * Returns the image's palette in raw format + * (r0,g0,b0,r1,g1,b2..r(Ncolors-1),g(Ncolors-1),b(Ncolors-1)) + */ + public byte[] getRawPalette() + { + return hasGlobalColorMap ? globalPalette : localPalette; + } + + /** + * Returns the image file for animated gifs. + */ + public GIFFile getImage( int index ) + { + if( index == 0 ) + return this; + if( animationFrames == null ) + throw new ArrayIndexOutOfBoundsException("Only one image in file"); + return (GIFFile)animationFrames.elementAt( index - 1 ); + } + + /** + * Return the image's raw image data. + * If the color depth is 1,2 or 4 bits per pixel the pixels are packed + * and the scanlines padded up to the nearest byte if needed. + */ + public byte[] getRawImage() + { + return raster; + } + + /** + * Return the number of images in the GIF file + */ + public int nImages() + { + if( animationFrames != null ) + return 1 + animationFrames.size(); + return 1; + } + + /** + * Handles extension blocks. + */ + private void readExtension(InputStream in) throws IOException, GIFException + { + int functionCode = in.read(); + byte[] data = readData(in); + switch( functionCode ) + { + case EXTENSION_COMMENT: // comment block + comment = new String(data, "8859_1"); + break; + + case EXTENSION_GCONTROL: // Graphics control extension + undraw = (data[0] & 0x1C) >> 2; + // allegedly there can be bad values of this. + if( undraw < 1 && undraw > 3 ) undraw = 1; + hasTransparency = ((data[0] & 0x01) == 1); + transparentIndex = (data[3] & 0xFF); + duration = ((data[2] & 0xFF) << 8) | (data[1] & 0xFF); + break; + + // Application extension. We only parse the Netscape animation + // extension here. Which is the only one most use anyway. + case EXTENSION_APPLICATION: + boolean isNS = true; + for(int i = 0; i < nsBlock.length; i++ ) + if( nsBlock[i] != data[i] ) + isNS = false; + if( isNS ) + { + isLooped = true; + loops = ((data[12] & 0xFF) << 8) | (data[13] & 0xFF); + } + break; + + default: + break; + } + } + + /** + * Reads a series of data blocks and merges them into a single one. + */ + private byte[] readData(InputStream in) throws IOException + { + Vector v = new Vector(); + int totalBytes = 0; + + int n = in.read(); + do + { + totalBytes += n; + byte[] block = new byte[ n ]; + in.read(block); + v.add(block); + n = in.read(); + } + while( n > 0 ); + + n = 0; + byte[] bigBuffer = new byte[ totalBytes ]; + for( int i = 0; i < v.size(); i++ ) + { + byte[] block = (byte[])v.elementAt(i); + System.arraycopy(block, 0, bigBuffer, n, block.length); + n += block.length; + } + return bigBuffer; + } + + /** + * Loads a compressed image block and decompresses it. + */ + private void decodeRaster(InputStream in) throws IOException + { + int initialCodeSize = in.read(); + compressedData = readData( in ); + dataBlockIndex = 0; + + int rasterIndex = 0; // Index into the raster + int clearCode = (1 << initialCodeSize); // 256 usually + int endCode = clearCode + 1; // The stop code. + + raster = new byte[ width * height ]; + + int codeSize = initialCodeSize + 1; + int code = getBits( codeSize ); // = clear + int nextCode = endCode + 1; + + /* + * Initialize LZW dictionary + * + * First index - code # + * Second index: + * 0 = color index + * 1 = parent (-1 - no parent) + * 2 = first value + * 3 - depth + * The latter two aren't strictly necessary but make things faster, since + * copying the values forward is faster than going back and looking. + */ + short[][] dictionary = new short[ 4096 ][ 4 ]; + + for(short i = 0; i < nColors; i ++ ) + { + dictionary[i][0] = i; // color index + dictionary[i][1] = -1; // parent + dictionary[i][2] = i; // first + dictionary[i][3] = 1; // depth + } + + code = getBits( codeSize ); // get second code + raster[ rasterIndex++ ] = (byte)dictionary[code][0]; + int old = code; + code = getBits( codeSize ); // start at the third code + int c; + + do + { + if( code == clearCode ) + { + codeSize = initialCodeSize + 1; + nextCode = endCode + 1; + // get and output second code + code = getBits( codeSize ); + raster[ rasterIndex++ ] = (byte)dictionary[code][0]; + old = code; + } + else + { + dictionary[nextCode][1] = (short)old; // parent = old + dictionary[nextCode][2] = dictionary[old][2]; // first pixel + dictionary[nextCode][3] = (short)(dictionary[old][3] + 1); // depth + + // appended pixel = first pixel of c + if( code < nextCode ) + { + dictionary[nextCode][0] = dictionary[code][2]; + old = code; + } + else // first of old + { + dictionary[nextCode][0] = dictionary[old][2]; + old = nextCode; + } + + c = old; + // output the code c + int depth = dictionary[c][3]; + for( int i = depth - 1; i >= 0; i-- ) + { + raster[ rasterIndex + i ] = (byte)dictionary[c][0]; + c = dictionary[c][1]; // go to parent. + } + rasterIndex += depth; + nextCode ++; + + if( codeSize < 12 && nextCode >= (1 << codeSize) ) + codeSize++; + } + code = getBits( codeSize ); + } + while( code != endCode && dataBlockIndex < compressedData.length ); + + compressedData = null; // throw away compressed data. + } + + /** + * Returns nbits number of bits (in the LSBs) from compressedData + */ + private int getBits( int nbits ) + { + while( nbits > remainingBits ) + { + int c = (compressedData[ dataBlockIndex++ ] & 0xFF) << remainingBits; + currentBits |= c; + remainingBits += 8; + } + int rval = (currentBits & ((1 << nbits) - 1)); + currentBits = (currentBits >> nbits); + remainingBits -= nbits; + return rval; + } + + /** + * Generic exception used by GIFFile to report decoding errors. + */ + public static class GIFException extends Exception + { + public GIFException(String message) + { + super(message); + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/gif/GIFImageReader.java b/libjava/classpath/gnu/javax/imageio/gif/GIFImageReader.java new file mode 100644 index 000000000..2cb59226b --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/gif/GIFImageReader.java @@ -0,0 +1,241 @@ +/* GIFImageReader.java -- + 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.gif; + +import gnu.javax.imageio.IIOInputStream; + +import java.io.IOException; +import java.io.InputStream; +import javax.imageio.*; +import javax.imageio.spi.*; +import javax.imageio.metadata.*; +import javax.imageio.stream.ImageInputStream; +import java.util.Iterator; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.awt.image.SampleModel; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; + +public class GIFImageReader extends ImageReader +{ + private GIFFile file; + + protected GIFImageReader(ImageReaderSpi originatingProvider) + { + super( originatingProvider ); + file = null; + } + + private void readImage() throws IOException + { + if( file != null ) + return; + + try + { + if( input instanceof InputStream ) + file = new GIFFile( (InputStream)input ); + else + file = new GIFFile( new IIOInputStream((ImageInputStream)input) ); + } + catch(GIFFile.GIFException ge) + { + throw new IIOException(ge.getMessage()); + } + } + + /** + * Returns the Global/Local palette as an IndexColorModel + */ + private IndexColorModel getPalette(int index) + { + GIFFile f = file.getImage( index ); + byte[] data = f.getRawPalette(); + int nc = f.getNColors(); + byte[] r = new byte[nc]; + byte[] g = new byte[nc]; + byte[] b = new byte[nc]; + + for(int i = 0; i < nc; i ++ ) + { + r[i] = data[ i * 3 ]; + g[i] = data[ i * 3 + 1 ]; + b[i] = data[ i * 3 + 2 ]; + } + + if( f.hasTransparency() ) + { + byte[] a = new byte[nc]; + for(int i = 0; i < nc; i ++ ) + a[i] = (byte)0xFF; + a[f.getTransparentIndex()] = 0; + return new IndexColorModel(8, nc, r, g, b, a); + } + + return new IndexColorModel(8, nc, r, g, b); + } + + private void validateIndex(int imageIndex) + throws IndexOutOfBoundsException + { + if( imageIndex < 0 || imageIndex >= getNumImages(false) ) + throw new IndexOutOfBoundsException("Invalid image index."); + } + + public void setInput(Object input) + { + super.setInput(input); + } + + public void setInput(Object input, + boolean seekForwardOnly, + boolean ignoreMetadata) + { + super.setInput(input, seekForwardOnly, ignoreMetadata); + } + + public void setInput(Object input, boolean isStreamable) + { + super.setInput(input, isStreamable); + + if (!(input instanceof ImageInputStream) && + !(input instanceof InputStream)) + throw new IllegalArgumentException("Input not an ImageInputStream."); + } + + private void checkStream() throws IOException + { + if (!(input instanceof ImageInputStream) && + !(input instanceof InputStream)) + throw new IllegalStateException("Input not an ImageInputStream or InputStream."); + + if(input == null) + throw new IllegalStateException("No input stream."); + } + + public int getWidth(int imageIndex) throws IOException + { + validateIndex( imageIndex ); + return file.getImage( imageIndex ).getWidth(); + } + + public int getHeight(int imageIndex) throws IOException + { + validateIndex( imageIndex ); + return file.getImage( imageIndex ).getHeight(); + } + + public Iterator getImageTypes(int imageIndex) + { + validateIndex( imageIndex ); + return null; + } + + /** + * Returns the number of images. + */ + public int getNumImages(boolean allowSearch) + { + try // Image should be loaded here already. But just in case: + { + readImage(); + } + catch(IOException ioe) + { + return 0; // Well, now we're in trouble. But return something anyway. + } + return file.nImages(); + } + + + // FIXME: Support metadata + public IIOMetadata getImageMetadata(int imageIndex) + { + validateIndex( imageIndex ); + return null; + } + + // FIXME: Support metadata + public IIOMetadata getStreamMetadata() + { + return null; + } + + /** + * Reads the image indexed by imageIndex and returns it as + * a complete BufferedImage, using a supplied ImageReadParam. + */ + public BufferedImage read(int imageIndex, ImageReadParam param) + throws IOException, IIOException + { + validateIndex( imageIndex ); + GIFFile f = file.getImage( imageIndex ); + int width = f.getWidth(); + int height = f.getHeight(); + SampleModel sm; + switch( f.getNColors() ) + { + case 16: + sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, 4); + break; + case 4: + sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, 2); + break; + case 2: + sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, 1); + break; + default: + sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, + new int[] {0xFF}); + break; + } + DataBuffer db = new DataBufferByte(f.getRawImage(), width * height, 0); + WritableRaster raster = Raster.createWritableRaster(sm, db, null); + + return new BufferedImage(getPalette( imageIndex ), raster, false, null); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/gif/GIFImageReaderSpi.java b/libjava/classpath/gnu/javax/imageio/gif/GIFImageReaderSpi.java new file mode 100644 index 000000000..285ca42e4 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/gif/GIFImageReaderSpi.java @@ -0,0 +1,124 @@ +/* GIFImageReaderSpi.java -- + 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.gif; + +import gnu.javax.imageio.IIOInputStream; + +import java.io.InputStream; +import java.io.IOException; +import java.util.Locale; +import javax.imageio.ImageReader; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; + +public class GIFImageReaderSpi extends ImageReaderSpi +{ + static final String vendorName = "GNU"; + static final String version = "0.1"; + static final String readerClassName = + "gnu.javax.imageio.gif.GIFImageReader"; + static final String[] names = { "Compuserve GIF" }; + static final String[] suffixes = { ".gif" }; + static final String[] MIMETypes = { + "image/gif", + "image/x-gif"}; // Not sure this is legal, but it seems to be used a bit + static final String[] writerSpiNames = null; + static final boolean supportsStandardStreamMetadataFormat = false; + static final String nativeStreamMetadataFormatName = null; + static final String nativeStreamMetadataFormatClassName = null; + static final String[] extraStreamMetadataFormatNames = null; + static final String[] extraStreamMetadataFormatClassNames = null; + static final boolean supportsStandardImageMetadataFormat = false; + static final String nativeImageMetadataFormatName = null; + static final String nativeImageMetadataFormatClassName = null; + static final String[] extraImageMetadataFormatNames = null; + static final String[] extraImageMetadataFormatClassNames = null; + + public GIFImageReaderSpi() + { + super(vendorName, version, + names, suffixes, MIMETypes, + readerClassName, + new Class[]{ ImageInputStream.class, InputStream.class }, + writerSpiNames, + supportsStandardStreamMetadataFormat, + nativeStreamMetadataFormatName, + nativeStreamMetadataFormatClassName, + extraStreamMetadataFormatNames, + extraStreamMetadataFormatClassNames, + supportsStandardImageMetadataFormat, + nativeImageMetadataFormatName, + nativeImageMetadataFormatClassName, + extraImageMetadataFormatNames, + extraImageMetadataFormatClassNames); + } + + public String getDescription(Locale locale) + { + return "Compuserve GIF"; + } + + public boolean canDecodeInput(Object input) + throws IOException + { + if( input == null ) + throw new IllegalArgumentException("Input object cannot be null."); + + if( !(input instanceof ImageInputStream) && + !(input instanceof InputStream)) + return false; + + boolean retval; + InputStream in; + if( input instanceof ImageInputStream ) + in = new IIOInputStream( (ImageInputStream)input ); + else + in = (InputStream)input; + + in.mark(10); // we read 6 bytes + retval = GIFFile.readSignature( in ); + in.reset(); + + return retval; + } + + public ImageReader createReaderInstance(Object extension) + { + return new GIFImageReader(this); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/DCT.java b/libjava/classpath/gnu/javax/imageio/jpeg/DCT.java new file mode 100644 index 000000000..fda52e5f5 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/DCT.java @@ -0,0 +1,347 @@ +/* DCT.java -- + Copyright (C) 2005 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.jpeg; + +/** + * Discrete Cosine Transformations. + */ +public class DCT +{ + + /** + * Cosine matrix + */ + public double c[][] = new double[8][8]; + + /** + * Transformed cosine matrix + */ + public double cT[][] = new double[8][8]; + + public DCT() + { + initMatrix(); + } + + /** + * Figure A.3.3 IDCT, Cu Cv on A-5 of the ISO DIS 10918-1. Requirements and + * Guidelines. + * + * @param u + * @return + */ + public static double C(int u) + { + return ((u == 0) ? (double) 1 / (double) Math.sqrt((double) 2) + : (double) 1); + } + + /** + * Initialize matrix values for the fast_idct function + */ + private void initMatrix() + { + for (int j = 0; j < 8; j++) + { + double nn = (double) (8); + c[0][j] = 1.0 / Math.sqrt(nn); + cT[j][0] = c[0][j]; + } + for (int i = 1; i < 8; i++) + { + for (int j = 0; j < 8; j++) + { + double jj = (double) j; + double ii = (double) i; + c[i][j] = + Math.sqrt(2.0 / 8.0) + * Math.cos(((2.0 * jj + 1.0) * ii * Math.PI) / (2.0 * 8.0)); + cT[j][i] = c[i][j]; + } + } + } + + /** + * slow_idct - Figure A.3.3 IDCT (informative) on A-5 of the ISO DIS + * 10918-1. Requirements and Guidelines. This is a slow IDCT, there are + * better algorithms to use, it's fairly expensive with processor speed. + * + * @param matrix + * @return + */ + public static double[][] slow_idct(double[][] matrix) + { + double[][] output = new double[matrix.length][matrix.length]; + for (int y = 0; y < 8; y++) + { + for (int x = 0; x < 8; x++) + { + double val = 0; + for (double v = 0; v < 8; v++) + { + double innerloop = 0; + for (double u = 0; u < 8; u++) + innerloop += (DCT.C((int) u) / (double) 2) + * matrix[(int) v][(int) u] + * Math.cos((2 * x + 1) * u * Math.PI / (double) 16) + * Math.cos((2 * y + 1) * v * Math.PI / (double) 16); + val += (DCT.C((int) v) / (double) 2) * innerloop; + } + output[y][x] = (val + 128); + } + } + return (output); + } + + public static float[][] slow_fdct(float[][] value) + { + float[][] buffer = new float[8][8]; + + for (int u = 0; u < 8; u++) + { + for (int v = 0; v < 8; v++) + { + buffer[u][v] = + (float) (1 / 4) * (float) C((int) u) * (float) C((int) v); + float innerval = 0; + for (int x = 0; x < 8; x++) + { + for (int y = 0; y < 8; y++) + { + innerval += value[y][x] + * Math.cos(((2 * x + 1) * u * Math.PI) / 16) + * Math.cos(((2 * y + 1) * v * Math.PI) / 16); + } + } + buffer[u][v] *= innerval; + } + } + return (buffer); + } + + public float[][] fast_fdct(float[][] input) + { + float output[][] = new float[8][8]; + double temp[][] = new double[8][8]; + double temp1; + int i; + int j; + int k; + + for (i = 0; i < 8; i++) + { + for (j = 0; j < 8; j++) + { + temp[i][j] = 0.0; + for (k = 0; k < 8; k++) + { + temp[i][j] += (((int) (input[i][k]) - 128) * cT[k][j]); + } + } + } + + for (i = 0; i < 8; i++) + { + for (j = 0; j < 8; j++) + { + temp1 = 0.0; + + for (k = 0; k < 8; k++) + { + temp1 += (c[i][k] * temp[k][j]); + } + + output[i][j] = (int) Math.round(temp1) * 8; + } + } + + return output; + } + + /** + * fast_idct - Figure A.3.3 IDCT (informative) on A-5 of the ISO DIS + * 10918-1. Requires and Guidelines. This is a fast IDCT, it much more + * effecient and only inaccurate at about 1/1000th of a percent of values + * analyzed. Cannot be static because initMatrix must run before any + * fast_idct values can be computed. + * + * @param input + * @return + */ + public double[][] fast_idct(double[][] input) + { + double output[][] = new double[8][8]; + double temp[][] = new double[8][8]; + double temp1; + int i, j, k; + for (i = 0; i < 8; i++) + { + for (j = 0; j < 8; j++) + { + temp[i][j] = 0.0; + for (k = 0; k < 8; k++) + { + temp[i][j] += input[i][k] * c[k][j]; + } + } + } + for (i = 0; i < 8; i++) + { + for (j = 0; j < 8; j++) + { + temp1 = 0.0; + for (k = 0; k < 8; k++) + temp1 += cT[i][k] * temp[k][j]; + temp1 += 128.0; + if (temp1 < 0) + output[i][j] = 0; + else if (temp1 > 255) + output[i][j] = 255; + else + output[i][j] = (int) Math.round(temp1); + } + } + return output; + } + + public double[][] idj_fast_fdct(float input[][]) + { + double output[][] = new double[8][8]; + double tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + double tmp10, tmp11, tmp12, tmp13; + double z1, z2, z3, z4, z5, z11, z13; + int i; + int j; + + // Subtracts 128 from the input values + for (i = 0; i < 8; i++) + { + for (j = 0; j < 8; j++) + { + output[i][j] = ((double) input[i][j] - (double) 128.0); + // input[i][j] -= 128; + + } + } + + for (i = 0; i < 8; i++) + { + tmp0 = output[i][0] + output[i][7]; + tmp7 = output[i][0] - output[i][7]; + tmp1 = output[i][1] + output[i][6]; + tmp6 = output[i][1] - output[i][6]; + tmp2 = output[i][2] + output[i][5]; + tmp5 = output[i][2] - output[i][5]; + tmp3 = output[i][3] + output[i][4]; + tmp4 = output[i][3] - output[i][4]; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + output[i][0] = tmp10 + tmp11; + output[i][4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * (double) 0.707106781; + output[i][2] = tmp13 + z1; + output[i][6] = tmp13 - z1; + + tmp10 = tmp4 + tmp5; + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + z5 = (tmp10 - tmp12) * (double) 0.382683433; + z2 = ((double) 0.541196100) * tmp10 + z5; + z4 = ((double) 1.306562965) * tmp12 + z5; + z3 = tmp11 * ((double) 0.707106781); + + z11 = tmp7 + z3; + z13 = tmp7 - z3; + + output[i][5] = z13 + z2; + output[i][3] = z13 - z2; + output[i][1] = z11 + z4; + output[i][7] = z11 - z4; + } + + for (i = 0; i < 8; i++) + { + tmp0 = output[0][i] + output[7][i]; + tmp7 = output[0][i] - output[7][i]; + tmp1 = output[1][i] + output[6][i]; + tmp6 = output[1][i] - output[6][i]; + tmp2 = output[2][i] + output[5][i]; + tmp5 = output[2][i] - output[5][i]; + tmp3 = output[3][i] + output[4][i]; + tmp4 = output[3][i] - output[4][i]; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + output[0][i] = tmp10 + tmp11; + output[4][i] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * (double) 0.707106781; + output[2][i] = tmp13 + z1; + output[6][i] = tmp13 - z1; + + tmp10 = tmp4 + tmp5; + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + z5 = (tmp10 - tmp12) * (double) 0.382683433; + z2 = ((double) 0.541196100) * tmp10 + z5; + z4 = ((double) 1.306562965) * tmp12 + z5; + z3 = tmp11 * ((double) 0.707106781); + + z11 = tmp7 + z3; + z13 = tmp7 - z3; + + output[5][i] = z13 + z2; + output[3][i] = z13 - z2; + output[1][i] = z11 + z4; + output[7][i] = z11 - z4; + } + + return output; + } + +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/HuffmanTable.java b/libjava/classpath/gnu/javax/imageio/jpeg/HuffmanTable.java new file mode 100644 index 000000000..78f3c1c4f --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/HuffmanTable.java @@ -0,0 +1,207 @@ +/* HuffmanTable.java -- + 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.jpeg; + +import java.io.IOException; + +import javax.imageio.plugins.jpeg.JPEGHuffmanTable; + + +/** + * This Object construct a JPEGHuffmanTable which can be used to encode/decode + * a scan from a JPEG codec stream. The table must be initalized with either a + * BITS byte amount and a Huffman Table Value for decoding or a Huffman Size + * and Huffman Code table for encoding. + */ +public class HuffmanTable +{ + public final static int HUFFMAN_MAX_TABLES = 4; + + private short[] huffcode = new short[256]; + private short[] huffsize = new short[256]; + private short[] EHUFCO; + private short[] EHUFSI; + private short[] valptr = new short[16]; + private short[] mincode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1,-1,-1}; + private short[] maxcode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1}; + private short[] huffval; + private short[] bits; + + static byte JPEG_DC_TABLE = 0; + static byte JPEG_AC_TABLE = 1; + + private short lastk = 0; + + public HuffmanTable(JPEGHuffmanTable table) + { + huffcode = table.getValues(); + bits = table.getLengths(); + } + + /** + * Generated from FIGURE C.1 - Generation of table of Huffman code sizes on + * ISO DIS 10918-1. Requirements and Guidelines + */ + private void generateSizeTable() + { + short index=0; + for(short i=0; i < bits.length ; i++) + { + for(short j=0; j < bits[i] ; j++) + { + huffsize[index] = (short) (i+1); + index++; + } + } + lastk = index; + } + + /** + * Generated from FIGURE C.2 - Generation of table of Huffman codes on + * ISO DIS 10918-1. Requirements and Guidelines + */ + private void generateCodeTable() + { + short k=0; + short si = huffsize[0]; + short code = 0; + for(short i=0; i < huffsize.length ; i++) + { + while(huffsize[k]==si) + { + huffcode[k] = code; + code++; + k++; + } + code <<= 1; + si++; + } + } + + /** + * Generated from FIGURE F.15 - Generation of decode table generation on + * ISO DIS 10918-1. Requirements and Guidelines + */ + private void generateDecoderTables() + { + short bitcount = 0; + for(int i=0; i < 16 ; i++) + { + if(bits[i]!=0) + valptr[i] = bitcount; + for(int j=0 ; j < bits[i] ; j++) + { + if(huffcode[j+bitcount] < mincode[i] || mincode[i] == -1) + mincode[i] = huffcode[j+bitcount]; + + if(huffcode[j+bitcount] > maxcode[i]) + maxcode[i] = huffcode[j+bitcount]; + } + if(mincode[i]!=-1) + valptr[i] = (short) (valptr[i] - mincode[i]); + bitcount += bits[i]; + } + } + + /** + * Generated from FIGURE C.3 - Generation of Order Codes and tables EHUFCO + * and EHUFSI from the ISO DIS 10918-1. Requirements and Guidelines + */ + public void orderCodes(boolean isDC) + { + EHUFCO = new short[isDC ? 15 : 255]; + EHUFSI = new short[isDC ? 15 : 255]; + + for (int p=0; p < lastk ; p++) + { + int i = huffval[p]; + if(i < 0 || i > EHUFCO.length || EHUFSI[i]!=0) + System.err.println("Error, bad huffman table."); + EHUFCO[i] = huffcode[p]; + EHUFSI[i] = huffsize[p]; + } + } + + /** + * Generated from FIGURE F.12 - Extending the sign bit of a decoded value in on + * ISO DIS 10918-1. Requirements and Guidelines<p> + * + * @param diff TODO + * @param t TODO + * @return TODO + */ + public static int extend(int diff, int t) + { + int Vt = (int)Math.pow(2,(t-1)); + if(diff<Vt) + { + Vt=(-1 << t)+1; + diff=diff+Vt; + } + return diff; + } + + /** + * Generated from FIGURE F.16 - Procedure for DECODE on + * ISO DIS 10918-1. Requirements and Guidelines<p> + * + * This function takes in a dynamic amount of bits and using the Huffman + * table returns information on how many bits must be read in to a byte in + * order to reconstruct said byte. + * + * @param JPEGStream the bits of the data stream. + */ + public int decode(JPEGImageInputStream JPEGStream) + throws IOException, JPEGException + { + int i=0; + short code = (short) JPEGStream.readBits(1); + while(code > maxcode[i]) + { + i++; + code <<= 1; + code |= JPEGStream.readBits(1); + } + int val = huffval[code+(valptr[i])]; + if(val < 0) + val = 256 + val; + return val; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGComponent.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGComponent.java new file mode 100644 index 000000000..7be67a02a --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGComponent.java @@ -0,0 +1,351 @@ +/* JPEGComponent.java -- + Copyright (C) 2005 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.jpeg; + +import java.util.ArrayList; +import java.io.IOException; +import java.awt.image.WritableRaster; + +import javax.imageio.plugins.jpeg.JPEGHuffmanTable; + +/** + * This class holds the methods to decode and write a component information to + * a raster. + */ +public class JPEGComponent +{ + public byte factorH, factorV, component_id, quant_id; + public int width = 0, height = 0, maxV = 0, maxH = 0; + public HuffmanTable ACTable; + public HuffmanTable DCTable; + public int[] quantizationTable; + public double previousDC = 0; + ArrayList data = new ArrayList(); + + /** + * Initializes the component + * + * @param id + * @param factorHorizontal + * @param factorVertical + * @param quantizationID + */ + public JPEGComponent(byte id, byte factorHorizontal, byte factorVertical, + byte quantizationID) + { + component_id = id; + factorH = factorHorizontal; + factorV = factorVertical; + quant_id = quantizationID; + } + + /** + * If a restart marker is found with too little of an MCU count (i.e. our + * Restart Interval is 63 and we have 61 we copy the last MCU until it's + * full) + * + * @param index + * @param length + */ + public void padMCU(int index, int length) + { + double[] src = (double[]) data.get(index - 1); + for (int i = 0; i < length; i++) + data.add(index, src); + } + + /** + * Reset the interval by setting the previous DC value + */ + public void resetInterval() + { + previousDC = 0; + } + + /** + * Run the Quantization backward method on all of the block data. + */ + public void quantitizeData() + { + for (int i = 0; i < data.size(); i++) + { + double[] mydata = (double[]) data.get(i); + for (int j = 0; j < mydata.length; j++) + mydata[j] *= quantizationTable[j]; + } + } + + public void setDCTable(JPEGHuffmanTable table) + { + DCTable = new HuffmanTable(table); + } + + public void setACTable(JPEGHuffmanTable table) + { + ACTable = new HuffmanTable(table); + } + + /** + * Run the Inverse DCT method on all of the block data + */ + public void idctData(DCT myDCT) + { + for (int i = 0; i < data.size(); i++) + data.add(i,myDCT.fast_idct(ZigZag.decode8x8_map((double[]) data.remove(i)))); + } + + /** + * This scales up the component size based on the factor size. This + * calculates everyting up automatically so it's simply ran at the end of + * the frame to normalize the size of all of the components. + */ + public void scaleByFactors() + { + int factorUpVertical = maxV / factorV; + int factorUpHorizontal = maxH / factorH; + + if (factorUpVertical > 1) + { + for (int i = 0; i < data.size(); i++) + { + double[][] src = (double[][]) data.remove(i); + double[][] dest = + new double[src.length * factorUpVertical][src[0].length]; + for (int j = 0; j < src.length; j++) + { + for (int u = 0; u < factorUpVertical; u++) + { + dest[j * factorUpVertical + u] = src[j]; + } + } + data.add(i, dest); + } + } + + if (factorUpHorizontal > 1) + { + for (int i = 0; i < data.size(); i++) + { + double[][] src = (double[][]) data.remove(i); + double[][] dest = + new double[src.length][src[0].length * factorUpHorizontal]; + for (int j = 0; j < src.length; j++) + { + for (int u = 0; u < src[0].length; u++) + { + for (int v = 0; v < factorUpHorizontal; v++) + dest[j][u * factorUpHorizontal + v] = src[j][u]; + } + } + data.add(i, dest); + } + } + } + + /** + * This write the block of data to the raster throwing out anything that + * spills over the raster width or height. + * + * @param raster + * @param data + * @param compIndex + * @param x + * @param y + */ + public void writeBlock(WritableRaster raster, double[][] data, + int compIndex, int x, int y) + { + for (int yIndex = 0; yIndex < data.length; yIndex++) + { + for (int xIndex = 0; xIndex < data[yIndex].length; xIndex++) + { + // The if statement is needed because blocks can spill over the + // frame width because they are padded to make sure we keep the + // height of the block the same as the width of the block + if (x + xIndex < raster.getWidth() + && y + yIndex < raster.getHeight()) + raster.setSample(x + xIndex, y + yIndex, compIndex, + data[yIndex][xIndex]); + } + } + } + + /** + * This writes data to a raster block, so really it's reading not writing + * but it writes the data to the raster block by factor size in a zig zag + * fashion. This has the helper function writeBlock which does the actual + * writing. + * + * @param raster + * @param componentIndex + */ + public void writeData(WritableRaster raster, int componentIndex) + { + int x = 0, y = 0, lastblockheight = 0, incrementblock = 0; + + // Keep looping through all of the blocks until there are no more. + while(data.size() > 0) + { + int blockwidth = 0; + int blockheight = 0; + + if (x >= raster.getWidth()) + { + x = 0; + y += incrementblock; + } + + // Loop through the horizontal component blocks of the MCU first + // then for each horizontal line write out all of the vertical + // components + for (int factorVIndex = 0; factorVIndex < factorV; factorVIndex++) + { + blockwidth = 0; + + for (int factorHIndex = 0; factorHIndex < factorH; factorHIndex++) + { + // Captures the width of this block so we can increment the + // X coordinate + double[][] blockdata = (double[][]) data.remove(0); + + // Writes the data at the specific X and Y coordinate of + // this component + writeBlock(raster, blockdata, componentIndex, x, y); + blockwidth += blockdata[0].length; + x += blockdata[0].length; + blockheight = blockdata.length; + } + y += blockheight; + x -= blockwidth; + lastblockheight += blockheight; + } + y -= lastblockheight; + incrementblock = lastblockheight; + lastblockheight = 0; + x += blockwidth; + } + } + + /** + * Set the quantization table for this component. + * + * @param quanttable + */ + public void setQuantizationTable(int[] quanttable) + { + quantizationTable = quanttable; + } + + /** + * Read in a partial MCU for this component + * + * @param stream TODO + * @throws JPEGException TODO + * @throws IOException TODO + */ + public void readComponentMCU(JPEGImageInputStream stream) + throws JPEGException, IOException + { + for (int i = 0; i < factorH * factorV; i++) + { + double dc = decode_dc_coefficient(stream); + double[] datablock = decode_ac_coefficients(stream); + datablock[0] = dc; + data.add(datablock); + } + } + + /** + * Generated from text on F-22, F.2.2.1 - Huffman decoding of DC + * coefficients on ISO DIS 10918-1. Requirements and Guidelines. + * + * @param JPEGStream TODO + * + * @return TODO + * @throws JPEGException TODO + * @throws IOException TODO + */ + public double decode_dc_coefficient(JPEGImageInputStream JPEGStream) + throws JPEGException, IOException + { + int t = DCTable.decode(JPEGStream); + double diff = JPEGStream.readBits(t); + diff = HuffmanTable.extend((int) diff, t); + diff = (previousDC + diff); + previousDC = diff; + return diff; + } + + /** + * Generated from text on F-23, F.13 - Huffman decoded of AC coefficients + * on ISO DIS 10918-1. Requirements and Guidelines. + * + * @param JPEGStream TODO + * @return TODO + * + * @throws JPEGException TODO + * @throws IOException TODO + */ + public double[] decode_ac_coefficients(JPEGImageInputStream JPEGStream) + throws JPEGException, IOException + { + double[] zz = new double[64]; + + for (int k = 1; k < 64; k++) + { + int s = ACTable.decode(JPEGStream); + int r = s >> 4; + s &= 15; + + if (s != 0) + { + k += r; + r = (int) JPEGStream.readBits(s); + s = HuffmanTable.extend(r, s); + zz[k] = s; + } + else + { + if (r != 15) + return (zz); + k += 15; + } + } + return zz; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGDecoder.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGDecoder.java new file mode 100644 index 000000000..11d547f4d --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGDecoder.java @@ -0,0 +1,625 @@ +/* JPEGDecoder.java -- + 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.jpeg; + +import java.io.IOException; +import java.nio.ByteOrder; + +import javax.imageio.plugins.jpeg.JPEGHuffmanTable; +import javax.imageio.plugins.jpeg.JPEGQTable; +import javax.imageio.stream.ImageInputStream; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.awt.Point; +import java.awt.Transparency; +import java.awt.color.ColorSpace; +import java.awt.image.BufferedImage; +import java.awt.image.ComponentColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.Raster; +import java.awt.image.WritableRaster; + +public class JPEGDecoder +{ + byte majorVersion; + byte minorVersion; + byte units; + short Xdensity; + short Ydensity; + byte Xthumbnail; + byte Ythumbnail; + byte[] thumbnail; + BufferedImage image; + int width; + int height; + + byte marker; + + /** + * This decoder expects JFIF 1.02 encoding. + */ + public static final byte MAJOR_VERSION = (byte) 1; + public static final byte MINOR_VERSION = (byte) 2; + + /** + * The length of the JFIF field not including thumbnail data. + */ + public static final short JFIF_FIXED_LENGTH = 16; + + /** + * The length of the JFIF extension field not including extension + * data. + */ + public static final short JFXX_FIXED_LENGTH = 8; + + private JPEGImageInputStream jpegStream; + + ArrayList jpegFrames = new ArrayList(); + + JPEGHuffmanTable[] dcTables = new JPEGHuffmanTable[4]; + JPEGHuffmanTable[] acTables = new JPEGHuffmanTable[4]; + JPEGQTable[] qTables = new JPEGQTable[4]; + + public int getHeight() + { + return height; + } + + public int getWidth() + { + return width; + } + public JPEGDecoder(ImageInputStream in) + throws IOException, JPEGException + { + jpegStream = new JPEGImageInputStream(in); + jpegStream.setByteOrder(ByteOrder.LITTLE_ENDIAN); + + if (jpegStream.findNextMarker() != JPEGMarker.SOI) + throw new JPEGException("Failed to find SOI marker."); + + if (jpegStream.findNextMarker() != JPEGMarker.APP0) + throw new JPEGException("Failed to find APP0 marker."); + + int length = jpegStream.readShort(); + if (!(length >= JFIF_FIXED_LENGTH)) + throw new JPEGException("Failed to find JFIF field."); + + byte[] identifier = new byte[5]; + jpegStream.read(identifier); + if (identifier[0] != JPEGMarker.JFIF_J + || identifier[1] != JPEGMarker.JFIF_F + || identifier[2] != JPEGMarker.JFIF_I + || identifier[3] != JPEGMarker.JFIF_F + || identifier[4] != JPEGMarker.X00) + throw new JPEGException("Failed to read JFIF identifier."); + + majorVersion = jpegStream.readByte(); + minorVersion = jpegStream.readByte(); + if (majorVersion != MAJOR_VERSION + || (majorVersion == MAJOR_VERSION + && minorVersion < MINOR_VERSION)) + throw new JPEGException("Unsupported JFIF version."); + + units = jpegStream.readByte(); + if (units > (byte) 2) + throw new JPEGException("Units field is out of range."); + + Xdensity = jpegStream.readShort(); + Ydensity = jpegStream.readShort(); + Xthumbnail = jpegStream.readByte(); + Ythumbnail = jpegStream.readByte(); + + // 3 * for RGB data + int thumbnailLength = 3 * Xthumbnail * Ythumbnail; + if (length > JFIF_FIXED_LENGTH + && thumbnailLength != length - JFIF_FIXED_LENGTH) + throw new JPEGException("Invalid length, Xthumbnail" + + " or Ythumbnail field."); + + if (thumbnailLength > 0) + { + thumbnail = new byte[thumbnailLength]; + if (jpegStream.read(thumbnail) != thumbnailLength) + throw new IOException("Failed to read thumbnail."); + } + } + + public void decode() + throws IOException + { + System.out.println ("DECODE!!!"); + // The frames in this jpeg are loaded into a list. There is + // usually just one frame except in heirarchial progression where + // there are multiple frames. + JPEGFrame frame = null; + + // The restart interval defines how many MCU's we should have + // between the 8-modulo restart marker. The restart markers allow + // us to tell whether or not our decoding process is working + // correctly, also if there is corruption in the image we can + // recover with these restart intervals. (See RSTm DRI). + int resetInterval = 0; + + // The JPEGDecoder constructor parses the JFIF field. At this + // point jpegStream points to the first byte after the JFIF field. + + // Find the first marker after the JFIF field. + byte marker = jpegStream.findNextMarker(); + + // Check for a JFIF extension field directly following the JFIF + // header and advance the current marker to the next marker in the + // stream, if necessary. + decodeJFIFExtension(); + + // Loop through until there are no more markers to read in, at + // that point everything is loaded into the jpegFrames array and + // can be processed. + while (true) + { + switch (marker) + { + // APPn Application Reserved Information - Just throw this + // information away because we wont be using it. + case JPEGMarker.APP0: + case JPEGMarker.APP1: + case JPEGMarker.APP2: + case JPEGMarker.APP3: + case JPEGMarker.APP4: + case JPEGMarker.APP5: + case JPEGMarker.APP6: + case JPEGMarker.APP7: + case JPEGMarker.APP8: + case JPEGMarker.APP9: + case JPEGMarker.APP10: + case JPEGMarker.APP11: + case JPEGMarker.APP12: + case JPEGMarker.APP13: + case JPEGMarker.APP14: + case JPEGMarker.APP15: + jpegStream.skipBytes(jpegStream.readShort() - 2); + break; + + case JPEGMarker.SOF0: + // SOFn Start of Frame Marker, Baseline DCT - This is the start + // of the frame header that defines certain variables that will + // be carried out through the rest of the encoding. Multiple + // frames are used in a heirarchiel system, however most JPEG's + // only contain a single frame. + jpegFrames.add(new JPEGFrame()); + frame = (JPEGFrame) jpegFrames.get(jpegFrames.size() - 1); + // Skip the frame length. + jpegStream.readShort(); + // Bits percision, either 8 or 12. + frame.setPrecision(jpegStream.readByte()); + // Scan lines = to the height of the frame. + frame.setScanLines(jpegStream.readShort()); + // Scan samples per line = to the width of the frame. + frame.setSamplesPerLine(jpegStream.readShort()); + // Number of Color Components (or channels). + frame.setComponentCount(jpegStream.readByte()); + + // Set the color mode for this frame, so far only 2 color + // modes are supported. + if (frame.getComponentCount() == 1) + frame.setColorMode(JPEGFrame.JPEG_COLOR_GRAY); + else + frame.setColorMode(JPEGFrame.JPEG_COLOR_YCbCr); + // Add all of the necessary components to the frame. + for (int i = 0; i < frame.getComponentCount(); i++) + frame.addComponent(jpegStream.readByte(), jpegStream.readByte(), + jpegStream.readByte()); + break; + + case JPEGMarker.SOF2: + jpegFrames.add(new JPEGFrame()); + frame = (JPEGFrame) jpegFrames.get(jpegFrames.size() - 1); + // Skip the frame length. + jpegStream.readShort(); + // Bits percision, either 8 or 12. + frame.setPrecision(jpegStream.readByte()); + // Scan lines = to the height of the frame. + frame.setScanLines(jpegStream.readShort()); + // Scan samples per line = to the width of the frame. + frame.setSamplesPerLine(jpegStream.readShort()); + // Number of Color Components (or channels). + frame.setComponentCount(jpegStream.readByte()); + + // Set the color mode for this frame, so far only 2 color + // modes are supported. + if (frame.getComponentCount() == 1) + frame.setColorMode(JPEGFrame.JPEG_COLOR_GRAY); + else + frame.setColorMode(JPEGFrame.JPEG_COLOR_YCbCr); + + // Add all of the necessary components to the frame. + for (int i = 0; i < frame.getComponentCount(); i++) + frame.addComponent(jpegStream.readByte(), jpegStream.readByte(), + jpegStream.readByte()); + break; + + case JPEGMarker.DHT: + // DHT non-SOF Marker - Huffman Table is required for decoding + // the JPEG stream, when we receive a marker we load in first + // the table length (16 bits), the table class (4 bits), table + // identifier (4 bits), then we load in 16 bytes and each byte + // represents the count of bytes to load in for each of the 16 + // bytes. We load this into an array to use later and move on 4 + // huffman tables can only be used in an image. + int huffmanLength = (jpegStream.readShort() - 2); + + // Keep looping until we are out of length. + int index = huffmanLength; + + // Multiple tables may be defined within a DHT marker. This + // will keep reading until there are no tables left, most + // of the time there are just one tables. + while (index > 0) + { + // Read the identifier information and class + // information about the Huffman table, then read the + // 16 byte codelength in and read in the Huffman values + // and put it into table info. + byte huffmanInfo = jpegStream.readByte(); + byte tableClass = (byte) (huffmanInfo >> 4); + byte huffmanIndex = (byte) (huffmanInfo & 0x0f); + short[] codeLength = new short[16]; + jpegStream.readFully(codeLength, 0, codeLength.length); + int huffmanValueLen = 0; + for (int i = 0; i < 16; i++) + huffmanValueLen += codeLength[i]; + index -= (huffmanValueLen + 17); + short[] huffmanVal = new short[huffmanValueLen]; + for (int i = 0; i < huffmanVal.length; i++) + huffmanVal[i] = jpegStream.readByte(); + // Assign DC Huffman Table. + if (tableClass == HuffmanTable.JPEG_DC_TABLE) + dcTables[(int) huffmanIndex] = new JPEGHuffmanTable(codeLength, + huffmanVal); + // Assign AC Huffman Table. + else if (tableClass == HuffmanTable.JPEG_AC_TABLE) + acTables[(int) huffmanIndex] = new JPEGHuffmanTable(codeLength, + huffmanVal); + } + break; + case JPEGMarker.DQT: + // DQT non-SOF Marker - This defines the quantization + // coeffecients, this allows us to figure out the quality of + // compression and unencode the data. The data is loaded and + // then stored in to an array. + short quantizationLength = (short) (jpegStream.readShort() - 2); + for (int j = 0; j < quantizationLength / 65; j++) + { + byte quantSpecs = jpegStream.readByte(); + int[] quantData = new int[64]; + if ((byte) (quantSpecs >> 4) == 0) + // Precision 8 bit. + { + for (int i = 0; i < 64; i++) + quantData[i] = jpegStream.readByte(); + + } + else if ((byte) (quantSpecs >> 4) == 1) + // Precision 16 bit. + { + for (int i = 0; i < 64; i++) + quantData[i] = jpegStream.readShort(); + } + qTables[(int) (quantSpecs & 0x0f)] = new JPEGQTable (quantData); + } + break; + case JPEGMarker.SOS: + // SOS non-SOF Marker - Start Of Scan Marker, this is where the + // actual data is stored in a interlaced or non-interlaced with + // from 1-4 components of color data, if three components most + // likely a YCrCb model, this is a fairly complex process. + + // Read in the scan length. + jpegStream.readShort(); + // Number of components in the scan. + byte numberOfComponents = jpegStream.readByte(); + byte[] componentSelector = new byte[numberOfComponents]; + for (int i = 0; i < numberOfComponents; i++) + { + // Component ID, packed byte containing the Id for the + // AC table and DC table. + byte componentID = jpegStream.readByte(); + byte tableInfo = jpegStream.readByte(); + frame.setHuffmanTables(componentID, + acTables[(byte) (tableInfo >> 4)], + dcTables[(byte) (tableInfo & 0x0f)]); + componentSelector[i] = componentID; + } + byte startSpectralSelection = jpegStream.readByte(); + byte endSpectralSelection = jpegStream.readByte(); + byte successiveApproximation = jpegStream.readByte(); + + int mcuIndex = 0; + int mcuTotalIndex = 0; + // This loops through until a MarkerTagFound exception is + // found, if the marker tag is a RST (Restart Marker) it + // simply skips it and moves on this system does not handle + // corrupt data streams very well, it could be improved by + // handling misplaced restart markers. + while (true) + { + try + { + // Loop though capturing MCU, instruct each + // component to read in its necessary count, for + // scaling factors the components automatically + // read in how much they need + for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) + { + JPEGComponent comp = frame.components.getComponentByID(componentSelector[compIndex]); + comp.readComponentMCU(jpegStream); + } + mcuIndex++; + mcuTotalIndex++; + } + // We've found a marker, see if the marker is a restart + // marker or just the next marker in the stream. If + // it's the next marker in the stream break out of the + // while loop, if it's just a restart marker skip it + catch (JPEGMarkerFoundException bse) + { + // Handle JPEG Restart Markers, this is where the + // count of MCU's per interval is compared with + // the count actually obtained, if it's short then + // pad on some MCU's ONLY for components that are + // greater than one. Also restart the DC prediction + // to zero. + if (marker == JPEGMarker.RST0 + || marker == JPEGMarker.RST1 + || marker == JPEGMarker.RST2 + || marker == JPEGMarker.RST3 + || marker == JPEGMarker.RST4 + || marker == JPEGMarker.RST5 + || marker == JPEGMarker.RST6 + || marker == JPEGMarker.RST7) + { + for (int compIndex = 0; compIndex < numberOfComponents; compIndex++) + { + JPEGComponent comp = frame.components.getComponentByID(componentSelector[compIndex]); + if (compIndex > 1) + comp.padMCU(mcuTotalIndex, resetInterval - mcuIndex); + comp.resetInterval(); + } + mcuTotalIndex += (resetInterval - mcuIndex); + mcuIndex = 0; + } + else + { + // We're at the end of our scan, exit out. + break; + } + } + } + break; + case JPEGMarker.DRI: + // DRI - This defines the restart interval, if we have a + // restart interval when we reach our restart modulo calculate + // whether the count of MCU's specified in the restart + // interval have been reached, if they havent then pad with + // whatever MCU was last used, this is supposed to be a form of + // error recovery but it turns out that some JPEG encoders + // purposely cause missing MCU's on repeating MCU's to compress + // data even more (even though it adds an extra layer of + // complexity.. But since when is JPEG easy? + jpegStream.skipBytes(2); + resetInterval = jpegStream.readShort(); + break; + case JPEGMarker.COM: + // COM - This is a comment that was inserted into the JPEG, we + // simply skip over the comment because it's really of no + // importance, usually contains a verbal description of the + // application or author who created the JPEG. + jpegStream.skipBytes(jpegStream.readShort() - 2); + break; + case JPEGMarker.DNL: + // DNL - This sets the height of the image. This is the Define + // Number Lines for the image, I'm not sure exactly why we need + // this but, whatever we'll abide. + frame.setScanLines(jpegStream.readShort()); + break; + case JPEGMarker.EOI: + // EOI - End of Image, this processes the frames and turns the + // frames into a buffered image. + + if (jpegFrames.size() == 0) + { + return; + } + else if (jpegFrames.size() == 1) + { + // Only one frame, JPEG Non-Heirarchial Frame. + + DCT myDCT = new DCT(); + WritableRaster raster = + Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + frame.width, + frame.height, + frame.getComponentCount(), + new Point(0, 0)); + + // Unencode the data. + for (int i = 0; i < frame.getComponentCount(); i++) + { + JPEGComponent comp = frame.components.get(i); + comp.setQuantizationTable(qTables[comp.quant_id].getTable()); + comp.quantitizeData(); + comp.idctData(myDCT); + } + // Scale the image and write the data to the raster. + for (int i = 0; i < frame.getComponentCount(); i++) + { + JPEGComponent comp = frame.components.get(i); + comp.scaleByFactors(); + comp.writeData(raster, i); + // Ensure garbage collection. + comp = null; + } + // Grayscale Color Image (1 Component). + if (frame.getComponentCount() == 1) + { + ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); + ComponentColorModel ccm = + new ComponentColorModel(cs, false, false, + Transparency.OPAQUE, + DataBuffer.TYPE_BYTE); + image = new BufferedImage(ccm, raster, false, + new Hashtable()); + } + // YCbCr Color Image (3 Components). + else if (frame.getComponentCount() == 3) + { + ComponentColorModel ccm = + new ComponentColorModel(new YCbCr_ColorSpace(), false, + false, Transparency.OPAQUE, + DataBuffer.TYPE_BYTE); + image = new BufferedImage(ccm, raster, false, + new Hashtable()); + } + // Possibly CMYK or RGBA ? + else + { + throw new JPEGException("Unsupported Color Mode: 4 " + + "Component Color Mode found."); + } + height = frame.height; + width = frame.width; + } + else + { + //JPEG Heirarchial Frame (progressive or baseline). + throw new JPEGException("Unsupported Codec Type:" + + " Hierarchial JPEG"); + } + break; + case JPEGMarker.SOF1: + // ERROR - If we encounter any of the following marker codes + // error out with a codec exception, progressive, heirarchial, + // differential, arithmetic, lossless JPEG's are not supported. + // This is where enhancements can be made for future versions. + // Thankfully 99% of all JPEG's are baseline DCT. + throw new JPEGException("Unsupported Codec Type: Extended " + + "Sequential DCT JPEG's Not-Supported"); + //case JPEGMarker.SOF2: + // throw new JPEGException("Unsupported Codec Type: Progressive DCT JPEG's Not-Supported"); + case JPEGMarker.SOF3: + throw new JPEGException("Unsupported Codec Type:" + + " Lossless (sequential)"); + case JPEGMarker.SOF5: + throw new JPEGException("Unsupported Codec Type:" + + " Differential sequential DCT"); + case JPEGMarker.SOF6: + throw new JPEGException("Unsupported Codec Type:" + + " Differential progressive DCT"); + case JPEGMarker.SOF7: + throw new JPEGException("Unsupported Codec Type:" + + " Differential lossless"); + case JPEGMarker.SOF9: + case JPEGMarker.SOF10: + case JPEGMarker.SOF11: + case JPEGMarker.SOF13: + case JPEGMarker.SOF14: + case JPEGMarker.SOF15: + throw new JPEGException("Unsupported Codec Type:" + + " Arithmetic Coding Frame"); + default: + // Unknown marker found, ignore it. + } + marker = jpegStream.findNextMarker(); + } + } + + // If the current marker is APP0, tries to decode a JFIF extension + // and advances the current marker to the next marker in the stream. + private void decodeJFIFExtension() throws IOException + { + if (marker == JPEGMarker.APP0) + { + int length = jpegStream.readShort(); + + if (length >= JFXX_FIXED_LENGTH) + { + byte[] identifier = new byte[5]; + jpegStream.read(identifier); + if (identifier[0] != JPEGMarker.JFIF_J + || identifier[1] != JPEGMarker.JFIF_F + || identifier[2] != JPEGMarker.JFIF_X + || identifier[3] != JPEGMarker.JFIF_X + || identifier[4] != JPEGMarker.X00) + // Not a JFXX field. Ignore it and continue. + jpegStream.skipBytes(length - 7); + else + { + byte extension_code = jpegStream.readByte(); + + switch (extension_code) + { + case JPEGMarker.JFXX_JPEG: + // FIXME: add support for JFIF Extension: + // Thumbnail coded using JPEG. + jpegStream.skipBytes(length - 8); + case JPEGMarker.JFXX_ONE_BPP: + // FIXME: add support for JFIF Extension: + // Thumbnail stored using 1 byte/pixel. + jpegStream.skipBytes(length - 8); + case JPEGMarker.JFXX_THREE_BPP: + // FIXME: add support for JFIF Extension: + // Thumbnail stored using 3 bytes/pixel. + jpegStream.skipBytes(length - 8); + } + } + } + else + { + // Unknown APP0 marker. Ignore it and continue. + jpegStream.skipBytes(length - 2); + } + marker = jpegStream.findNextMarker(); + } + } + + public BufferedImage getImage() + { + return image; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGException.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGException.java new file mode 100644 index 000000000..a2c06e27e --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGException.java @@ -0,0 +1,48 @@ +/* JPEGException.java -- + 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.jpeg; + +import javax.imageio.*; + +public class JPEGException extends IIOException +{ + public JPEGException(String message) + { + super(message); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGFrame.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGFrame.java new file mode 100644 index 000000000..35aed728a --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGFrame.java @@ -0,0 +1,108 @@ +/* JPEGFrame.java -- + Copyright (C) 2005 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.jpeg; + +import javax.imageio.plugins.jpeg.JPEGHuffmanTable; + +public class JPEGFrame +{ + public final static byte JPEG_COLOR_GRAY = 1; + public final static byte JPEG_COLOR_RGB = 2; + public final static byte JPEG_COLOR_YCbCr = 3; + public final static byte JPEG_COLOR_CMYK = 4; + + public byte precision = 8; + public byte colorMode = JPEGFrame.JPEG_COLOR_YCbCr; + public byte componentCount = 0; + + public short width=0, height=0; + + public JPEGScan components; + + public JPEGFrame() + { + components = new JPEGScan(); + } + + public void addComponent(byte componentID, byte sampleFactors, + byte quantizationTableID) + { + byte sampleHorizontalFactor = (byte)(sampleFactors >> 4); + byte sampleVerticalFactor = (byte)(sampleFactors & 0x0f); + components.addComponent(componentID, sampleHorizontalFactor, + sampleVerticalFactor, quantizationTableID); + } + + public void setPrecision(byte data) + { + precision = data; + } + + public void setScanLines(short data) + { + height = data; + } + + public void setSamplesPerLine(short data) + { + width = data; + } + + public void setColorMode(byte data) + { + colorMode = data; + } + + public void setComponentCount(byte data) + { + componentCount = data; + } + + public byte getComponentCount() + { + return componentCount; + } + + public void setHuffmanTables(byte componentID, JPEGHuffmanTable ACTable, + JPEGHuffmanTable DCTable) + { + JPEGComponent comp = components.getComponentByID(componentID); + comp.setACTable(ACTable); + comp.setDCTable(DCTable); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageInputStream.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageInputStream.java new file mode 100644 index 000000000..f2c26d9d5 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageInputStream.java @@ -0,0 +1,188 @@ +/* JPEGImageInputStream.java -- + 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.jpeg; + +import java.io.IOException; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageInputStreamImpl; + +public class JPEGImageInputStream + extends ImageInputStreamImpl +{ + private ImageInputStream in; + + byte marker; + + public JPEGImageInputStream(ImageInputStream in) + { + super(); + + this.in = in; + } + + public int read() + throws IOException + { + setBitOffset(0); + return in.read(); + } + + public int read(byte[] data, int offset, int len) + throws IOException + { + setBitOffset(0); + return in.read(data, offset, len); + } + + /** + * Pull a byte from the stream, this checks to see if the byte is 0xff + * and if the next byte isn't 0x00 (stuffed byte) it errors out. If it's + * 0x00 then it simply ignores the byte. + * + * @return the next byte in the buffer + * + * @throws IOException TODO + * @throws BitStreamException TODO + */ + private byte pullByte() throws IOException, JPEGMarkerFoundException + { + byte mybyte = readByte(); + // FIXME: handle multiple 0xff in a row + if(mybyte==(byte)(0xff)) + { + byte secondbyte = readByte(); + if(secondbyte != (byte)(0x00)) + { + marker = secondbyte; + throw new JPEGMarkerFoundException(); + } + } + return mybyte; + } + + /** + * This returns the marker that was last encountered. This should only be + * used if removeBit() throws a MarkerTagFound exception. + * + * @return marker as byte + */ + public byte getMarker() + { + return marker; + } + + /** + * Removes a bit from the buffer. (Removes from the top of a queue). This + * also checks for markers and throws MarkerTagFound exception if it does. + * If MarkerTagFound is thrown you can use getMarker() method to get the + * marker that caused the throw. + * + * @param l specifies how many bits you want to remove and add to the + * integer + * @return the amount of bits specified by l as an integer + * + * @throws IOException TODO + * @throws JPEGMarkerFoundException + * @throws BitStreamException TODO + */ + public int readBit() + throws IOException, JPEGMarkerFoundException +{ + checkClosed(); + + // Calc new bit offset here, readByte resets it. + int newOffset = (bitOffset + 1) & 0x7; + + byte data = pullByte(); + + if (bitOffset != 0) + { + seek(getStreamPosition() - 1); + data = (byte) (data >> (8 - newOffset)); + } + + bitOffset = newOffset; + return data & 0x1; +} + + + /** + * This method skips over the the data and finds the next position + * in the bit sequence with a X'FF' X'??' sequence. Multiple X'FF + * bytes in sequence are considered padding and interpreted as one + * X'FF byte. + * + * @return the next marker byte in the stream + * @throws IOException if the end of the stream is reached + * unexpectedly + */ + public byte findNextMarker() + throws IOException + { + boolean marked0xff = false; + byte byteinfo = JPEGMarker.X00; + + setBitOffset(0); + while (true) + { + byteinfo = readByte(); + if (!marked0xff) + { + if (byteinfo == JPEGMarker.XFF) + marked0xff = true; + } + else + { + if (byteinfo == JPEGMarker.XFF) + // Ignore the value 0xff when it is immediately + // followed by another 0xff byte. + continue; + else if (byteinfo == JPEGMarker.X00) + // The sequence 0xff 0x00 is used to encode the + // actual value 0xff. So restart our search for a + // marker. + marked0xff = false; + else + // One or more 0xff values were follwed by a + // non-0x00, non-0xff value so return this as the + // marker byte. + return byteinfo; + } + } + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReader.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReader.java new file mode 100644 index 000000000..5ecbe0f8c --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReader.java @@ -0,0 +1,141 @@ +/* JPEGImageReader.java -- + 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.jpeg; + +import java.io.IOException; +import javax.imageio.*; +import javax.imageio.spi.*; +import javax.imageio.metadata.*; +import javax.imageio.stream.ImageInputStream; +import java.util.Iterator; +import java.awt.image.BufferedImage; + +public class JPEGImageReader extends ImageReader +{ + JPEGDecoder decoder; + + protected JPEGImageReader(ImageReaderSpi originatingProvider) + { + super(originatingProvider); + System.out.println("JPEGIMAGEREADER!!!"); + } + + // Abstract ImageReader methods. + public int getHeight(int imageIndex) + throws IOException + { + checkIndex(imageIndex); + decodeStream(); + return decoder.getHeight(); + } + + public IIOMetadata getImageMetadata(int imageIndex) + throws IOException + { + // FIXME: handle metadata + checkIndex(imageIndex); + return null; + } + + public Iterator getImageTypes(int imageIndex) + throws IOException + { + return null; + } + + public int getNumImages(boolean allowSearch) + throws IOException + { + return 1; + } + + public IIOMetadata getStreamMetadata() + throws IOException + { + // FIXME: handle metadata + return null; + } + + public int getWidth(int imageIndex) + throws IOException + { + checkIndex(imageIndex); + decodeStream(); + return decoder.getWidth(); + } + + public BufferedImage read(int imageIndex, ImageReadParam param) + throws IOException + { + checkIndex(imageIndex); + decodeStream(); + return decoder.getImage(); + } + + // private helper methods + private void checkIndex(int imageIndex) + throws IndexOutOfBoundsException + { + if (imageIndex != 0) + throw new IndexOutOfBoundsException(); + } + + private void checkStream() throws IOException + { + if (!(input instanceof ImageInputStream)) + throw new IllegalStateException("Input not an ImageInputStream."); + if(input == null) + throw new IllegalStateException("No input stream."); + } + + private void decodeStream() + throws IOException, IIOException + { + System.out.println("DECONDING 1"); + if (decoder != null) + return; + + System.out.println("DECONDING 2"); + checkStream(); + + System.out.println("DECONDING 3"); + decoder = new JPEGDecoder((ImageInputStream)input); + System.out.println("DECONDING 4"); + decoder.decode(); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReaderSpi.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReaderSpi.java new file mode 100644 index 000000000..c45b818c7 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGImageReaderSpi.java @@ -0,0 +1,137 @@ +/* JPEGImageReaderSpi.java -- + 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.jpeg; + +import java.io.IOException; +import java.util.Locale; +import javax.imageio.ImageReader; +import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.spi.IIORegistry; +import javax.imageio.stream.ImageInputStream; + +public class JPEGImageReaderSpi extends ImageReaderSpi +{ + static final String vendorName = "GNU"; + static final String version = "0.1"; + static final String readerClassName = + "gnu.javax.imageio.jpeg.JPEGImageReader"; + static final String[] names = { "JPEG" }; + static final String[] suffixes = { ".jpeg", ".jpg", ".jpe" }; + static final String[] MIMETypes = { "image/jpeg" }; + static final String[] writerSpiNames = + { "gnu.javax.imageio.jpeg.JPEGImageWriterSpi" }; + + static final boolean supportsStandardStreamMetadataFormat = false; + static final String nativeStreamMetadataFormatName = null; + static final String nativeStreamMetadataFormatClassName = null; + static final String[] extraStreamMetadataFormatNames = null; + static final String[] extraStreamMetadataFormatClassNames = null; + static final boolean supportsStandardImageMetadataFormat = false; + static final String nativeImageMetadataFormatName = null; + static final String nativeImageMetadataFormatClassName = null; + static final String[] extraImageMetadataFormatNames = null; + static final String[] extraImageMetadataFormatClassNames = null; + + private static JPEGImageReaderSpi readerSpi; + + public JPEGImageReaderSpi() + { + super(vendorName, version, + names, suffixes, MIMETypes, + readerClassName, + STANDARD_INPUT_TYPE, // Accept ImageInputStreams + writerSpiNames, + supportsStandardStreamMetadataFormat, + nativeStreamMetadataFormatName, + nativeStreamMetadataFormatClassName, + extraStreamMetadataFormatNames, + extraStreamMetadataFormatClassNames, + supportsStandardImageMetadataFormat, + nativeImageMetadataFormatName, + nativeImageMetadataFormatClassName, + extraImageMetadataFormatNames, + extraImageMetadataFormatClassNames); + System.out.println ("JPEGImageReaderSPI!!!"); + } + + public String getDescription(Locale locale) + { + return "JPEG ISO 10918-1, JFIF V1.02"; + } + + public boolean canDecodeInput(Object input) + throws IOException + { + if (!(input instanceof ImageInputStream)) + return false; + + ImageInputStream in = (ImageInputStream) input; + boolean retval; + + in.mark(); + try + { + new JPEGDecoder(in); + retval = true; + } + catch(JPEGException e) + { + retval = false; + } + in.reset(); + + return retval; + } + + public ImageReader createReaderInstance(Object extension) + { + return new JPEGImageReader(this); + } + + public static void registerSpis(IIORegistry reg) + { + reg.registerServiceProvider(getReaderSpi(), ImageReaderSpi.class); + } + + public static synchronized JPEGImageReaderSpi getReaderSpi() + { + if (readerSpi == null) + readerSpi = new JPEGImageReaderSpi(); + return readerSpi; + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarker.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarker.java new file mode 100644 index 000000000..bc6350fbc --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarker.java @@ -0,0 +1,205 @@ +/* JPEGMarker.java -- + 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.jpeg; + +public class JPEGMarker +{ + /** + * JFIF identifiers. + */ + public final static byte JFIF_J = (byte) 0x4a; + public final static byte JFIF_F = (byte) 0x46; + public final static byte JFIF_I = (byte) 0x49; + public final static byte JFIF_X = (byte) 0x46; + + /** + * JFIF extension codes. + */ + public final static byte JFXX_JPEG = (byte) 0x10; + public final static byte JFXX_ONE_BPP = (byte) 0x11; + public final static byte JFXX_THREE_BPP = (byte) 0x13; + + /** + * Marker prefix byte. + */ + public final static byte XFF = (byte) 0xff; + + /** + * Marker byte that represents a literal 0xff. + */ + public final static byte X00 = (byte) 0x00; + + /** + * Application Reserved Keyword. + */ + public final static byte APP0 = (byte) 0xe0; + + public final static byte APP1 = (byte) 0xe1; + public final static byte APP2 = (byte) 0xe2; + public final static byte APP3 = (byte) 0xe3; + public final static byte APP4 = (byte) 0xe4; + public final static byte APP5 = (byte) 0xe5; + public final static byte APP6 = (byte) 0xe6; + public final static byte APP7 = (byte) 0xe7; + public final static byte APP8 = (byte) 0xe8; + public final static byte APP9 = (byte) 0xe9; + public final static byte APP10 = (byte) 0xea; + public final static byte APP11 = (byte) 0xeb; + public final static byte APP12 = (byte) 0xec; + public final static byte APP13 = (byte) 0xed; + public final static byte APP14 = (byte) 0xee; + public final static byte APP15 = (byte) 0xef; + + /** + * Modulo Restart Interval. + */ + public final static byte RST0 = (byte) 0xd0; + + public final static byte RST1 = (byte) 0xd1; + public final static byte RST2 = (byte) 0xd2; + public final static byte RST3 = (byte) 0xd3; + public final static byte RST4 = (byte) 0xd4; + public final static byte RST5 = (byte) 0xd5; + public final static byte RST6 = (byte) 0xd6; + public final static byte RST7 = (byte) 0xd7; + + /** + * Nondifferential Huffman-coding frame (baseline dct). + */ + public final static byte SOF0 = (byte) 0xc0; + + /** + * Nondifferential Huffman-coding frame (extended dct). + */ + public final static byte SOF1 = (byte) 0xc1; + + /** + * Nondifferential Huffman-coding frame (progressive dct). + */ + public final static byte SOF2 = (byte) 0xc2; + + /** + * Nondifferential Huffman-coding frame Lossless (Sequential). + */ + public final static byte SOF3 = (byte) 0xc3; + + /** + * Differential Huffman-coding frame Sequential DCT. + */ + public final static byte SOF5 = (byte) 0xc5; + + /** + * Differential Huffman-coding frame Progressive DCT. + */ + public final static byte SOF6 = (byte) 0xc6; + + /** + * Differential Huffman-coding frame lossless. + */ + public final static byte SOF7 = (byte) 0xc7; + + /** + * Nondifferential Arithmetic-coding frame (extended dct). + */ + public final static byte SOF9 = (byte) 0xc9; + + /** + * Nondifferential Arithmetic-coding frame (progressive dct). + */ + public final static byte SOF10 = (byte) 0xca; + + /** + * Nondifferential Arithmetic-coding frame (lossless). + */ + public final static byte SOF11 = (byte) 0xcb; + + /** + * Differential Arithmetic-coding frame (sequential dct). + */ + public final static byte SOF13 = (byte) 0xcd; + + /** + * Differential Arithmetic-coding frame (progressive dct). + */ + public final static byte SOF14 = (byte) 0xce; + + /** + * Differential Arithmetic-coding frame (lossless). + */ + public final static byte SOF15 = (byte) 0xcf; + + /** + * Huffman Table. + */ + public final static byte DHT = (byte) 0xc4; + + /** + * Quantization Table. + */ + public final static byte DQT = (byte) 0xdb; + + /** + * Start of Scan. + */ + public final static byte SOS = (byte) 0xda; + + /** + * Defined Restart Interval. + */ + public final static byte DRI = (byte) 0xdd; + + /** + * Comment in JPEG. + */ + public final static byte COM = (byte) 0xfe; + + /** + * Start of Image. + */ + public final static byte SOI = (byte) 0xd8; + + /** + * End of Image. + */ + public final static byte EOI = (byte) 0xd9; + + /** + * Define Number of Lines. + */ + public final static byte DNL = (byte) 0xdc; +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarkerFoundException.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarkerFoundException.java new file mode 100644 index 000000000..2e72d495b --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGMarkerFoundException.java @@ -0,0 +1,50 @@ +/* JPEGMarkerFoundException.java -- FIXME: briefly describe file purpose + 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.jpeg; + +import java.io.IOException; + +public class JPEGMarkerFoundException + extends IOException +{ + public JPEGMarkerFoundException() + { + super(""); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/JPEGScan.java b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGScan.java new file mode 100644 index 000000000..e07251021 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/JPEGScan.java @@ -0,0 +1,151 @@ +/* JPEGScan.java -- + Copyright (C) 2005 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.jpeg; + +import java.util.ArrayList; + +public class JPEGScan +{ + private int maxHeight = 0, maxWidth = 0, maxV = 0, maxH = 0; + private int numOfComponents = 0, numOfComponentBlocks = 0; + private ArrayList components = new ArrayList(); + + public JPEGScan() + { + // Nothing to do here. + } + + public JPEGScan(int h, int w) + { + maxHeight=h; + maxWidth=w; + } + + private void recalculateDimensions() + { + JPEGComponent comp; + + // Compute the maximum H, maximum V factors defined in Annex A of the ISO + // DIS 10918-1. + for(int i=0; i < components.size() ; i++) + { + comp = (JPEGComponent)components.get(i); + if(comp.factorH > maxH) + maxH=comp.factorH; + if(comp.factorV > maxV) + maxV=comp.factorV; + } + + for(int i=0; i < components.size() ; i++) + { + comp = (JPEGComponent)components.get(i); + comp.maxH = maxH; + comp.maxV = maxV; + } + + } + + public void addComponent(byte id, byte factorHorizontal, byte factorVertical, + byte quantizationID) + { + JPEGComponent component = new JPEGComponent(id, factorHorizontal, factorVertical, quantizationID); + components.add((Object)component); + recalculateDimensions(); + numOfComponents++; + numOfComponentBlocks += factorHorizontal*factorVertical; + } + + public JPEGComponent getComponentByID(byte id) + { + JPEGComponent comp = (JPEGComponent)components.get(0); + for(int i=0; i < components.size() ; i++) + { + comp=(JPEGComponent)components.get(i); + if(comp.component_id==id) + break; + } + return(comp); + } + + public JPEGComponent get(int id) + { + return((JPEGComponent)components.get(id)); + } + + public int getX(byte id) + { + JPEGComponent comp = getComponentByID(id); + return(comp.width); + } + + public int getY(byte id) + { + JPEGComponent comp = getComponentByID(id); + return(comp.height); + } + + public int getMaxV() + { + return(maxV); + } + + public int getMaxH() + { + return(maxH); + } + + public void setWidth(int w) + { + maxWidth=w; + } + + public void setHeight(int h) + { + maxHeight=h; + } + + public int size() + { + return(numOfComponents); + } + + public int sizeComponentBlocks() + { + return(numOfComponentBlocks); + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/YCbCr_ColorSpace.java b/libjava/classpath/gnu/javax/imageio/jpeg/YCbCr_ColorSpace.java new file mode 100644 index 000000000..a3970b7fa --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/YCbCr_ColorSpace.java @@ -0,0 +1,113 @@ +/* YCbCr_ColorSpace.java -- + Copyright (C) 2005 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.jpeg; + +import java.awt.color.ColorSpace; + +public class YCbCr_ColorSpace extends ColorSpace { + public YCbCr_ColorSpace() { + super(ColorSpace.TYPE_YCbCr, 3); + } + + public float[] fromCIEXYZ(float[] data) { + return(new float[data.length]); + } + + public float[] toCIEXYZ(float[] data) { + return(new float[data.length]); + } + + public float[] fromRGB(float[] data) { + return(new float[data.length]); + } + + /* YCbCr to RGB range 0 to 1 */ + public float[] toRGB(float[] data) { + float[] dest = new float[3]; + + data[0] *= 255; + data[1] *= 255; + data[2] *= 255; + + dest[0] = (float)data[0] + (float)1.402*((float)data[2]-(float)128); + dest[1] = (float)data[0] - (float)0.34414*((float)data[1]-(float)128) - (float)0.71414*((float)data[2]-(float)128); + dest[2] = (float)data[0] + (float)1.772*((float)data[1]-(float)128); + + dest[0] /= 255; + dest[1] /= 255; + dest[2] /= 255; + + //dest[0] = ((float)1.164*((float)data[0]*(float)255 - (float)16) + (float)1.596*((float)data[2]*(float)255 - (float)128))/(float)255; + //dest[1] = ((float)1.164*((float)data[0]*(float)255 - (float)16) - (float)0.813*((float)data[2]*(float)255 - (float)128) - (float)0.392*(data[1]*255 - 128))/(float)255; + //dest[2] = ((float)1.164*((float)data[0]*(float)255 - (float)16) + (float)2.017*((float)data[1]*(float)255 - (float)128))/(float)255; + + //System.err.println("toRGB values received: 0: "+data[0]+" 1: "+data[1]+" 2: "+data[2]+" sent: 0: "+dest[0]+" 1: "+dest[1]+" 2: "+dest[2]); + if(dest[0] < (float)0) + dest[0] = 0; + if(dest[1] < (float)0) + dest[1] = 0; + if(dest[2] < (float)0) + dest[2] = 0; + + if(dest[0] > (float)1) + dest[0] = 1; + if(dest[1] > (float)1) + dest[1] = 1; + if(dest[2] > (float)1) + dest[2] = 1; + + + return(dest); + } + + /* RGB to YCbCr range 0-255 */ + public static float[] toYCbCr(float[] data) { + float[] dest = new float[3]; + //dest[0] = (float)0.257*data[0] + (float)0.504*data[1] + (float)0.098*data[2] + 16; + //dest[1] = (float)-0.148*data[0] - (float)0.291*data[1] + (float)0.439*data[2] + 128; + //dest[2] = (float)0.439*data[0] - (float)0.368*data[1] - (float)0.071*data[2] + 128; + + dest[0] = (float)((0.299 * (float)data[0] + 0.587 * (float)data[1] + 0.114 * (float)data[2])); + dest[1] = 128 + (float)((-0.16874 * (float)data[0] - 0.33126 * (float)data[1] + 0.5 * (float)data[2])); + dest[2] = 128 + (float)((0.5 * (float)data[0] - 0.41869 * (float)data[1] - 0.08131 * (float)data[2])); + + + return(dest); + + } +} diff --git a/libjava/classpath/gnu/javax/imageio/jpeg/ZigZag.java b/libjava/classpath/gnu/javax/imageio/jpeg/ZigZag.java new file mode 100644 index 000000000..9aac0df40 --- /dev/null +++ b/libjava/classpath/gnu/javax/imageio/jpeg/ZigZag.java @@ -0,0 +1,520 @@ +/* ZigZag.java -- + Copyright (C) 2005 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.jpeg; + +/** + * This class implements the Zig Zag Algorithm on any array with + * the same amount of rows and columns. It takes a matrix and in turn builds an + * encoded byte array (or double array) from it. The adverse is also true, this + * will take a byte or double array and build a matrix based on the zig zag + * algorithm. + * <p>This is used exclusively in the JPEG DCT encoding.</p> + */ +public class ZigZag +{ + public final static boolean ZIGZAG_FORWARD = true; + public final static boolean ZIGZAG_BACKWARD = false; + public final static int ZIGZAG_8X8_MAP[] = + { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 + }; + + /** + * Encodes a matrix of equal width and height to a byte array. + * + * @param matrix + * + * @return + */ + public static byte[] encode(byte[][] matrix) + { + byte[] buffer = new byte[matrix.length ^ 2]; + boolean direction = ZigZag.ZIGZAG_FORWARD; + int x = 0, y = 0, index = 0; + for (int zigIndex = 0; zigIndex < (matrix.length * 2 - 1); + zigIndex++, direction = !direction) + { + if (direction == ZigZag.ZIGZAG_FORWARD) + { + while (x >= 0 && y != matrix.length) + { + if (x == matrix.length) + { + x--; + y++; + } + buffer[index] = matrix[x][y]; + y++; + x--; + index++; + } + x++; + } + else + { + while (y >= 0 && x != matrix.length) + { + if (y == matrix.length) + { + y--; + x++; + } + buffer[index] = matrix[x][y]; + y--; + x++; + index++; + } + y++; + } + } + return (buffer); + } + + /** + * Encodes a matrix of equal width and height to a double array + * + * @param matrix + * + * @return + */ + public static double[] encode(double[][] matrix) + { + double[] buffer = new double[matrix.length * matrix.length]; + boolean direction = ZigZag.ZIGZAG_FORWARD; + int x = 0, y = 0, index = 0; + for (int zigIndex = 0; zigIndex < (matrix.length * 2 - 1); + zigIndex++, direction = !direction) + { + if (direction == ZigZag.ZIGZAG_FORWARD) + { + while (x >= 0 && y != matrix.length) + { + if (x == matrix.length) + { + x--; + y++; + } + buffer[index] = matrix[x][y]; + y++; + x--; + index++; + } + x++; + } + else + { + while (y >= 0 && x != matrix.length) + { + if (y == matrix.length) + { + y--; + x++; + } + buffer[index] = matrix[x][y]; + y--; + x++; + index++; + } + y++; + } + } + return (buffer); + } + + /** + * Encodes a matrix of equal width and height to a float array + * + * @param matrix + * + * @return + */ + public static float[] encode(float[][] matrix) + { + float[] buffer = new float[matrix.length * matrix.length]; + boolean direction = ZigZag.ZIGZAG_FORWARD; + int x = 0, y = 0, index = 0; + for (int zigIndex = 0; zigIndex < (matrix.length * 2 - 1); + zigIndex++, direction = !direction) + { + if (direction == ZigZag.ZIGZAG_FORWARD) + { + while (x >= 0 && y != matrix.length) + { + if (x == matrix.length) + { + x--; + y++; + } + buffer[index] = matrix[x][y]; + y++; + x--; + index++; + } + x++; + } + else + { + while (y >= 0 && x != matrix.length) + { + if (y == matrix.length) + { + y--; + x++; + } + buffer[index] = matrix[x][y]; + y--; + x++; + index++; + } + y++; + } + } + return (buffer); + } + + /** + * Encodes a matrix of equal width and height to a float array + * + * @param matrix + * + * @return + */ + public static short[] encode(short[][] matrix) + { + short[] buffer = new short[matrix.length * matrix.length]; + boolean direction = ZigZag.ZIGZAG_FORWARD; + int x = 0, y = 0, index = 0; + for (int zigIndex = 0; zigIndex < (matrix.length * 2 - 1); + zigIndex++, direction = !direction) + { + if (direction == ZigZag.ZIGZAG_FORWARD) + { + while (x >= 0 && y != matrix.length) + { + if (x == matrix.length) + { + x--; + y++; + } + buffer[index] = matrix[x][y]; + y++; + x--; + index++; + } + x++; + } + else + { + while (y >= 0 && x != matrix.length) + { + if (y == matrix.length) + { + y--; + x++; + } + buffer[index] = matrix[x][y]; + y--; + x++; + index++; + } + y++; + } + } + return (buffer); + } + + /** + * Convert a double array into a matrix with the same amount of columns and + * rows with length sqrt(double array length) + * + * @param data + * + * @return + */ + public static double[][] decode(double[] data) + { + return decode(data, (int) Math.sqrt(data.length), + (int) Math.sqrt(data.length)); + } + + /** + * Convert a byte array into a matrix with the same amount of columns and + * rows with length sqrt(double array length) + * + * @param data + * + * @return + */ + public static byte[][] decode(byte[] data) + { + return decode(data, (int) Math.sqrt(data.length), + (int) Math.sqrt(data.length)); + } + + public static int[][] decode(int[] data) + { + return decode(data, (int) Math.sqrt(data.length), + (int) Math.sqrt(data.length)); + } + + public static byte[][] decode(byte[] data, int width, int height) + { + byte[][] buffer = new byte[height][width]; + + for (int v = 0; v < height; v++) + for (int z = 0; z < width; z++) + buffer[v][z] = 11; + + boolean dir = ZigZag.ZIGZAG_FORWARD; + int xindex = 0, yindex = 0, dataindex = 0; + + while (xindex < width && yindex < height && dataindex < data.length) + { + buffer[yindex][xindex] = data[dataindex]; + dataindex++; + + if (dir == ZigZag.ZIGZAG_FORWARD) + { + if (yindex == 0 || xindex == (width - 1)) + { + dir = ZigZag.ZIGZAG_BACKWARD; + if (xindex == (width - 1)) + yindex++; + else + xindex++; + } + else + { + yindex--; + xindex++; + } + } + else + { /* Backwards */ + if (xindex == 0 || yindex == (height - 1)) + { + dir = ZigZag.ZIGZAG_FORWARD; + if (yindex == (height - 1)) + xindex++; + else + yindex++; + } + else + { + yindex++; + xindex--; + } + } + } + return (buffer); + } + + public static double[][] decode(double[] data, int width, int height) + { + double[][] buffer = new double[height][width]; + + for (int v = 0; v < height; v++) + for (int z = 0; z < width; z++) + buffer[v][z] = 11; + + boolean dir = ZigZag.ZIGZAG_FORWARD; + int xindex = 0, yindex = 0, dataindex = 0; + + while (xindex < width && yindex < height && dataindex < data.length) + { + buffer[yindex][xindex] = data[dataindex]; + dataindex++; + System.err.println("Setting " + dataindex + " to row: " + yindex + + " column: " + xindex + " yourval:" + + (yindex*8+xindex)); + if (dir == ZigZag.ZIGZAG_FORWARD) + { + if (yindex == 0 || xindex == (width - 1)) + { + dir = ZigZag.ZIGZAG_BACKWARD; + if (xindex == (width - 1)) + yindex++; + else + xindex++; + } + else + { + yindex--; + xindex++; + } + } + else + { /* Backwards */ + if (xindex == 0 || yindex == (height - 1)) + { + dir = ZigZag.ZIGZAG_FORWARD; + if (yindex == (height - 1)) + xindex++; + else + yindex++; + } + else + { + yindex++; + xindex--; + } + } + } + return (buffer); + } + + public static float[][] decode(float[] data, int width, int height) + { + float[][] buffer = new float[height][width]; + + for (int v = 0; v < height; v++) + for (int z = 0; z < width; z++) + buffer[v][z] = 11; + + boolean dir = ZigZag.ZIGZAG_FORWARD; + int xindex = 0, yindex = 0, dataindex = 0; + + while (xindex < width && yindex < height && dataindex < data.length) + { + buffer[yindex][xindex] = data[dataindex]; + dataindex++; + + if (dir == ZigZag.ZIGZAG_FORWARD) + { + if (yindex == 0 || xindex == (width - 1)) + { + dir = ZigZag.ZIGZAG_BACKWARD; + if (xindex == (width - 1)) + yindex++; + else + xindex++; + } + else + { + yindex--; + xindex++; + } + } + else + { /* Backwards */ + if (xindex == 0 || yindex == (height - 1)) + { + dir = ZigZag.ZIGZAG_FORWARD; + if (yindex == (height - 1)) + xindex++; + else + yindex++; + } + else + { + yindex++; + xindex--; + } + } + } + return (buffer); + } + + public static int[][] decode(int[] data, int width, int height) + { + int[][] buffer = new int[height][width]; + + for (int v = 0; v < height; v++) + for (int z = 0; z < width; z++) + buffer[v][z] = 11; + + boolean dir = ZigZag.ZIGZAG_FORWARD; + int xindex = 0, yindex = 0, dataindex = 0; + + while (xindex < width && yindex < height && dataindex < data.length) + { + buffer[yindex][xindex] = data[dataindex]; + dataindex++; + + if (dir == ZigZag.ZIGZAG_FORWARD) + { + if (yindex == 0 || xindex == (width - 1)) + { + dir = ZigZag.ZIGZAG_BACKWARD; + if (xindex == (width - 1)) + yindex++; + else + xindex++; + } + else + { + yindex--; + xindex++; + } + } + else + { /* Backwards */ + if (xindex == 0 || yindex == (height - 1)) + { + dir = ZigZag.ZIGZAG_FORWARD; + if (yindex == (height - 1)) + xindex++; + else + yindex++; + } + else + { + yindex++; + xindex--; + } + } + } + return (buffer); + } + + public static double[][] decode8x8_map(double input[]) + { + double[][] output = new double[8][8]; + for(int i=0; i < 64 ; i++) + output[ZIGZAG_8X8_MAP[i]/8][ZIGZAG_8X8_MAP[i]%8] = input[i]; + return (output); + } + +} 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; + } +} |