diff --git a/src/java/com/threerings/resource/FastImageIO.java b/src/java/com/threerings/resource/FastImageIO.java index 6be89e2d..f90ec501 100644 --- a/src/java/com/threerings/resource/FastImageIO.java +++ b/src/java/com/threerings/resource/FastImageIO.java @@ -24,9 +24,11 @@ package com.threerings.resource; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; +import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; @@ -39,6 +41,8 @@ import java.awt.image.IndexColorModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.WritableRaster; +import org.apache.commons.io.IOUtils; + /** * Provides routines for writing and reading uncompressed 8-bit color * mapped images in a manner that is extremely fast and generates a @@ -46,7 +50,9 @@ import java.awt.image.WritableRaster; */ public class FastImageIO { - /** A suffix for use when storing raw images in bundles or on the file system. */ + /** + * A suffix for use when storing raw images in bundles or on the file system. + */ public static final String FILE_SUFFIX = ".raw"; /** @@ -112,51 +118,74 @@ public class FastImageIO try { MappedByteBuffer mbuf = fchan.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); - - // read in our integer fields - IntBuffer ibuf = mbuf.asIntBuffer(); - int width = ibuf.get(); - int height = ibuf.get(); - /* int tpixel = */ ibuf.get(); - int msize = ibuf.get(); - - if (width > Short.MAX_VALUE || width < 0 || height > Short.MAX_VALUE || height < 0) { - throw new IOException("Bogus image size " + width + "x" + height); - } - - IndexColorModel cmodel; - synchronized (_origin) { // any old object will do - // make sure our colormap array is big enough - if (_cmap == null || _cmap.length < msize) { - _cmap = new int[msize]; - } - // read in the data and create our colormap - ibuf.get(_cmap, 0, msize); - cmodel = new IndexColorModel(8, msize, _cmap, 0, DataBuffer.TYPE_BYTE, null); - } - - // advance the byte buffer accordingly - mbuf.position(ibuf.position() * 4); - - // read in the image data itself - byte[] data = new byte[width*height]; - mbuf.get(data); - - // create the image from our component parts - DataBuffer dbuf = new DataBufferByte(data, data.length, 0); - int[] offsets = new int[] { 0 }; - PixelInterleavedSampleModel smodel = - new PixelInterleavedSampleModel( - DataBuffer.TYPE_BYTE, width, height, 1, width, offsets); - WritableRaster raster = WritableRaster.createWritableRaster(smodel, dbuf, _origin); - return new BufferedImage(cmodel, raster, false, null); - + return read(mbuf); } finally { fchan.close(); raf.close(); } } + /** + * Reads an image from the supplied input stream (which must return the image format previously + * written via a call to {@link #write}). + * + * @exception IOException thrown if an error occurs reading from the file. + */ + public static BufferedImage read (InputStream in) + throws IOException + { + return read(ByteBuffer.wrap(IOUtils.toByteArray(in))); + } + + /** + * Reads an image from the supplied byte buffer (which must return the image format previously + * written via a call to {@link #write}). + * + * @exception IOException thrown if an error occurs reading from the file. + */ + public static BufferedImage read (ByteBuffer byteBuffer) + throws IOException + { + // read in our integer fields + IntBuffer ibuf = byteBuffer.asIntBuffer(); + int width = ibuf.get(); + int height = ibuf.get(); + /* int tpixel = */ ibuf.get(); + int msize = ibuf.get(); + + if (width > Short.MAX_VALUE || width < 0 || height > Short.MAX_VALUE || height < 0) { + throw new IOException("Bogus image size " + width + "x" + height); + } + + IndexColorModel cmodel; + synchronized (_origin) { // any old object will do + // make sure our colormap array is big enough + if (_cmap == null || _cmap.length < msize) { + _cmap = new int[msize]; + } + // read in the data and create our colormap + ibuf.get(_cmap, 0, msize); + cmodel = new IndexColorModel( + 8, msize, _cmap, 0, DataBuffer.TYPE_BYTE, null); + } + + // advance the byte buffer accordingly + byteBuffer.position(ibuf.position() * 4); + + // read in the image data itself + byte[] data = new byte[width*height]; + byteBuffer.get(data); + + // create the image from our component parts + DataBuffer dbuf = new DataBufferByte(data, data.length, 0); + int[] offsets = new int[] { 0 }; + PixelInterleavedSampleModel smodel = + new PixelInterleavedSampleModel( + DataBuffer.TYPE_BYTE, width, height, 1, width, offsets); + WritableRaster raster = WritableRaster.createWritableRaster(smodel, dbuf, _origin); + return new BufferedImage(cmodel, raster, false, null); + } + /** Used when loading our color map. */ protected static int[] _cmap;