[vassalengine-svn-trunk] [vassalengine-svn] SF.net SVN: vassalengine:[4353] VASSAL-src/trunk/src/VA
Brought to you by:
rodneykinney,
uckelman
From: <uck...@us...> - 2008-10-27 12:17:41
|
Revision: 4353 http://vassalengine.svn.sourceforge.net/vassalengine/?rev=4353&view=rev Author: uckelman Date: 2008-10-27 12:17:29 +0000 (Mon, 27 Oct 2008) Log Message: ----------- Merged uckelman-work 4317, 4318, 4333, 4336. Refactored request path for memory-mapped images. Now use them only when requested (e.g., by Board). Modified Paths: -------------- VASSAL-src/trunk/src/VASSAL/build/module/map/boardPicker/Board.java VASSAL-src/trunk/src/VASSAL/tools/ImageUtils.java VASSAL-src/trunk/src/VASSAL/tools/SVGRenderer.java VASSAL-src/trunk/src/VASSAL/tools/imageop/Op.java VASSAL-src/trunk/src/VASSAL/tools/imageop/SourceOpBitmapImpl.java VASSAL-src/trunk/src/VASSAL/tools/memmap/MappedBufferedImage.java Added Paths: ----------- VASSAL-src/trunk/src/VASSAL/tools/imageop/SourceOpMappedBitmapImpl.java VASSAL-src/trunk/src/VASSAL/tools/memmap/MappedImageUtils.java Removed Paths: ------------- VASSAL-src/trunk/src/VASSAL/tools/imageop/OpErrorDialog.java Modified: VASSAL-src/trunk/src/VASSAL/build/module/map/boardPicker/Board.java =================================================================== --- VASSAL-src/trunk/src/VASSAL/build/module/map/boardPicker/Board.java 2008-10-27 10:48:19 UTC (rev 4352) +++ VASSAL-src/trunk/src/VASSAL/build/module/map/boardPicker/Board.java 2008-10-27 12:17:29 UTC (rev 4353) @@ -47,8 +47,8 @@ import org.jdesktop.animation.timing.Animator; import org.jdesktop.animation.timing.TimingTargetAdapter; - import VASSAL.build.AbstractConfigurable; +import VASSAL.build.BadDataReport; import VASSAL.build.Buildable; import VASSAL.build.Builder; import VASSAL.build.GameModule; @@ -66,7 +66,9 @@ import VASSAL.configure.SingleChildInstance; import VASSAL.configure.VisibilityCondition; import VASSAL.tools.ErrorDialog; +import VASSAL.tools.ErrorUtils; import VASSAL.tools.imageop.ImageOp; +import VASSAL.tools.imageop.MissingImageException; import VASSAL.tools.imageop.Op; import VASSAL.tools.imageop.OpErrorDialog; import VASSAL.tools.imageop.Repainter; @@ -223,7 +225,7 @@ } imageFile = (String) val; boardImageOp = imageFile == null || imageFile.trim().length() == 0 - ? null : Op.load(imageFile); + ? null : Op.loadLarge(imageFile); } else if (WIDTH.equals(key)) { if (val instanceof String) { @@ -287,6 +289,31 @@ } }; + protected void drawTile(Graphics g, Future<Image> fim, + int tx, int ty, Component obs) { + try { + g.drawImage(fim.get(), tx, ty, obs); + } + catch (CancellationException e) { + // FIXME: bug until we permit cancellation + ErrorDialog.bug(e); + } + catch (InterruptedException e) { + ErrorDialog.bug(e); + } + catch (ExecutionException e) { + final MissingImageException mie = + ErrorUtils.getAncestorOfClass(MissingImageException.class, e); + if (mie != null) { + ErrorDialog.dataError(new BadDataReport( + "Image not found", mie.getFile().getAbsolutePath(), mie)); + } + else { + ErrorDialog.bug(e); + } + } + } + public void drawRegion(final Graphics g, final Point location, Rectangle visibleRect, @@ -337,26 +364,12 @@ final Future<Image> fim = op.getFutureTile(tile.x, tile.y, rep); if (obs == null) { - try { - g.drawImage(fim.get(), tx, ty, obs); - } - catch (CancellationException e) { - // FIXME: bug until we permit cancellation - ErrorDialog.bug(e); - } - catch (InterruptedException e) { - ErrorDialog.bug(e); - } - catch (ExecutionException e) { -// FIXME: don't use this - OpErrorDialog.error(e, op); - } + drawTile(g, fim, tx, ty, obs); } else { if (fim.isDone()) { if (requested.containsKey(tile)) { requested.remove(tile); - final Point t = tile; final Animator a = new Animator(100, @@ -379,39 +392,12 @@ final Composite oldComp = g2d.getComposite(); g2d.setComposite( AlphaComposite.getInstance(AlphaComposite.SRC_OVER, a)); - - try { - g2d.drawImage(fim.get(), tx, ty, obs); - } - catch (CancellationException e) { - // FIXME: bug until we permit cancellation - ErrorDialog.bug(e); - } - catch (InterruptedException e) { - ErrorDialog.bug(e); - } - catch (ExecutionException e) { - OpErrorDialog.error(e, op); - } - + drawTile(g2d, fim, tx, ty, obs); g2d.setComposite(oldComp); } else { alpha.remove(tile); - - try { - g.drawImage(fim.get(), tx, ty, obs); - } - catch (CancellationException e) { - // FIXME: bug until we permit cancellation - ErrorDialog.bug(e); - } - catch (InterruptedException e) { - ErrorDialog.bug(e); - } - catch (ExecutionException e) { - OpErrorDialog.error(e, op); - } + drawTile(g, fim, tx, ty, obs); } } } @@ -420,7 +406,8 @@ } } } -// FIXME: should getTileFuture() throw these? +// FIXME: should getTileFuture() throw these? Yes, probably, because it's +// synchronous when obs is null. catch (CancellationException e) { // FIXME: bug until we permit cancellation ErrorDialog.bug(e); Modified: VASSAL-src/trunk/src/VASSAL/tools/ImageUtils.java =================================================================== --- VASSAL-src/trunk/src/VASSAL/tools/ImageUtils.java 2008-10-27 10:48:19 UTC (rev 4352) +++ VASSAL-src/trunk/src/VASSAL/tools/ImageUtils.java 2008-10-27 12:17:29 UTC (rev 4353) @@ -28,7 +28,6 @@ import java.awt.image.BufferedImage; import java.awt.image.ColorConvertOp; import java.awt.image.ColorModel; -import java.awt.image.SampleModel; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; @@ -38,9 +37,6 @@ import java.util.Map; import javax.imageio.ImageIO; import javax.imageio.ImageReader; -import javax.imageio.ImageReadParam; -import javax.imageio.ImageTypeSpecifier; -import javax.imageio.stream.FileCacheImageInputStream; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream; @@ -65,11 +61,15 @@ private static final ImageUtils instance = new ImageUtils(); public static final String PREFER_MEMORY_MAPPED = "preferMemoryMapped"; //$NON-NLS-1$ - public static final String SCALER_ALGORITHM = "scalerAlgorithm"; //$NON-NLS-1$ private static final int MAPPED = 0; private static final int RAM = 1; private int largeImageLoadMethod = RAM; + public static boolean useMappedImages() { + return instance.largeImageLoadMethod == MAPPED; + } + + public static final String SCALER_ALGORITHM = "scalerAlgorithm"; //$NON-NLS-1$ private static final int MEDIUM = 1; private static final int GOOD = 2; private int scalingQuality = GOOD; @@ -78,12 +78,12 @@ new HashMap<RenderingHints.Key,Object>(); private ImageUtils() { - // create configurer for memory-mappedf file preference + // create configurer for memory-mapped file preference final BooleanConfigurer mappedPref = new BooleanConfigurer( PREFER_MEMORY_MAPPED, "Prefer memory-mapped files for large images?", //$NON-NLS-1$ Boolean.FALSE); -//Resources.getString("GlobalOptions.smooth_scaling"), Boolean.TRUE); //$NON-NLS-1$ + mappedPref.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { largeImageLoadMethod = @@ -91,7 +91,7 @@ } }); - GameModule.getGameModule().getPrefs().addOption(mappedPref); + GameModule.getGameModule().getPrefs().addOption(mappedPref); // create configurer for scaling quality final BooleanConfigurer scalingPref = new BooleanConfigurer( @@ -303,113 +303,12 @@ } } - public static Image getImage(InputStream in) throws IOException { - return getSmallImage(in); - } - - public static Image getSmallImage(InputStream in) throws IOException { + public static BufferedImage getImage(InputStream in) throws IOException { final BufferedImage img = ImageIO.read(new MemoryCacheImageInputStream(in)); if (img == null) throw new IOException("Unrecognized image format"); - - return img.getType() != BufferedImage.TYPE_INT_ARGB - ? ImageUtils.toIntARGBSmall(img) : img; + return img.getType() != BufferedImage.TYPE_INT_ARGB ? toIntARGB(img) : img; } - public static Image getLargeImage(InputStream in) throws IOException { - final BufferedImage img = getLargeBufferedImage(in); - - return img.getType() != BufferedImage.TYPE_INT_ARGB ? - ImageUtils.toIntARGBLarge(img) : img; - } - - public static BufferedImage getLargeBufferedImage(InputStream in) - throws IOException { - BufferedImage img = null; - - // first try preferred storage type - int method = instance.largeImageLoadMethod; - done: - for (int tries = 0; tries < 2; ++tries, ++method) { - final ImageInputStream stream = new FileCacheImageInputStream( - in, TempFileManager.getInstance().getSessionRoot()); - try { - final Iterator<ImageReader> i = ImageIO.getImageReaders(stream); - if (!i.hasNext()) throw new IOException("Unrecognized image format"); - - final ImageReader reader = i.next(); - try { - reader.setInput(stream); - - final int w = reader.getWidth(0); - final int h = reader.getHeight(0); - - switch (method % 2) { - case MAPPED: - try { - final ImageTypeSpecifier type = reader.getImageTypes(0).next(); - - // get our ColorModel and SampleModel - final ColorModel cm = type.getColorModel(); - final SampleModel sm = - type.getSampleModel().createCompatibleSampleModel(w,h); - - img = MappedBufferedImage.createMemoryMappedImage(cm, sm); - - final ImageReadParam param = reader.getDefaultReadParam(); - param.setDestination(img); - reader.read(0, param); - break done; - } - catch (IOException e) { - // ignore, we throw an OutOfMemoryError at the bottom - Logger.log(e); - } - break; - case RAM: - try { - img = reader.read(0); - break done; - } - catch (OutOfMemoryError e) { - // ignore, we throw an OutOfMemoryError at the bottom - Logger.log(e); - } - break; - default: - assert false; - } - } - finally { - reader.dispose(); - } - - stream.close(); - } - finally { - IOUtils.closeQuietly(stream); - } - } - - if (img == null) throw new OutOfMemoryError(); - - return img; - } - - public static boolean isLargeImage(int w, int h) { - return 4*w*h > 1024*1024; - } - - private static BufferedImage rowByRowCopy(BufferedImage src, - BufferedImage dst) { - final int h = src.getHeight(); - final int[] row = new int[src.getWidth()]; - for (int y = 0; y < h; ++y) { - src.getRGB(0, y, row.length, 1, row, 0, row.length); - dst.setRGB(0, y, row.length, 1, row, 0, row.length); - } - return dst; - } - private static BufferedImage colorConvertCopy(BufferedImage src, BufferedImage dst) { final ColorConvertOp op = new ColorConvertOp( @@ -420,103 +319,13 @@ return dst; } - public static BufferedImage createEmptyLargeImage(int w, int h) { - int method = instance.largeImageLoadMethod; - for (int tries = 0; tries < 2; ++tries, ++method) { - switch (method % 2) { - case MAPPED: - try { - return MappedBufferedImage.createIntARGBMemoryMappedImage(w, h); - } - catch (IOException e) { - // ignore, we throw an OutOfMemoryError at bottom - Logger.log(e); - } - break; - case RAM: - try { - return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - } - catch (OutOfMemoryError e) { - // ignore, we throw an OutOfMemoryError at bottom - Logger.log(e); - } - break; - default: - assert false; - } - } - - throw new OutOfMemoryError(); - } - - public static BufferedImage toIntARGBLarge(BufferedImage src) { - final int w = src.getWidth(); - final int h = src.getHeight(); - - int method = instance.largeImageLoadMethod; - for (int tries = 0; tries < 2; ++tries, ++method) { - switch (method % 2) { - case MAPPED: - try { - return rowByRowCopy(src, - MappedBufferedImage.createIntARGBMemoryMappedImage(w, h)); - } - catch (IOException e) { - // ignore, we throw an OutOfMemoryError at bottom - Logger.log(e); - } - break; - case RAM: - try { - final BufferedImage dst = - new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - - return src instanceof MappedBufferedImage - ? rowByRowCopy(src, dst) : colorConvertCopy(src, dst); - } - catch (OutOfMemoryError e) { - // ignore, we throw an OutOfMemoryError at bottom - Logger.log(e); - } - break; - default: - assert false; - } - } - - throw new OutOfMemoryError(); - } - - public static BufferedImage toIntARGBSmall(BufferedImage src) { + public static BufferedImage toIntARGB(BufferedImage src) { final BufferedImage dst = new BufferedImage( src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_ARGB); return colorConvertCopy(src, dst); } - - public static BufferedImage toIntARGB(BufferedImage src) { - return toIntARGBSmall(src); - } - + /** - * Create a memory-mapped image from an existing image. - * - * @param src the source image - * @return a memory-mapped copy - * @throws IOException if the memory-mapped image cannot be created - */ - public static BufferedImage toMemoryMapped(Image src) throws IOException { - final BufferedImage dst = - MappedBufferedImage.createIntARGBMemoryMappedImage( - src.getWidth(null), src.getHeight(null)); - - final Graphics2D g = dst.createGraphics(); - g.drawImage(src, 0, 0, null); - g.dispose(); - return dst; - } - - /** * Transform an <code>Image</code> to a <code>BufferedImage</code>. * * @param src the <code>Image</code> to transform @@ -534,4 +343,8 @@ return bi; } + + public static BufferedImage createImage(int w, int h) { + return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + } } Modified: VASSAL-src/trunk/src/VASSAL/tools/SVGRenderer.java =================================================================== --- VASSAL-src/trunk/src/VASSAL/tools/SVGRenderer.java 2008-10-27 10:48:19 UTC (rev 4352) +++ VASSAL-src/trunk/src/VASSAL/tools/SVGRenderer.java 2008-10-27 12:17:29 UTC (rev 4353) @@ -242,7 +242,8 @@ BufferedImage rend = renderer.getOffScreen(); renderer = null; // We're done with it... - final BufferedImage dest = createImage(w, h); + final BufferedImage dest = + new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); final Graphics2D g2d = GraphicsUtil.createGraphics(dest); if (hints.containsKey(KEY_BACKGROUND_COLOR)) { @@ -261,12 +262,6 @@ writeImage(dest, output); } - private BufferedImage createImage(int w, int h) { - return ImageUtils.isLargeImage(w, h) ? - ImageUtils.createEmptyLargeImage(w, h) : - new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - } - private void writeImage(BufferedImage image, TranscoderOutput output) { this.image = image; } Modified: VASSAL-src/trunk/src/VASSAL/tools/imageop/Op.java =================================================================== --- VASSAL-src/trunk/src/VASSAL/tools/imageop/Op.java 2008-10-27 10:48:19 UTC (rev 4352) +++ VASSAL-src/trunk/src/VASSAL/tools/imageop/Op.java 2008-10-27 12:17:29 UTC (rev 4353) @@ -22,6 +22,7 @@ import java.awt.Image; import VASSAL.counters.GamePiece; +import VASSAL.tools.ImageUtils; public class Op { public static SourceOp load(String name) { @@ -34,7 +35,16 @@ public static SourceOp load(Image image) { return new ImageSourceOpBitmapImpl(image); } - + + public static SourceOp loadLarge(String name) { + if (name.endsWith(".svg")) + return new SourceOpSVGImpl(name); + else if (ImageUtils.useMappedImages()) + return new SourceOpMappedBitmapImpl(name); + else + return new SourceOpBitmapImpl(name); + } + public static ScaleOp scale(ImageOp sop, double scale) { if (sop instanceof SVGOp) return new RotateScaleOpSVGImpl((SVGOp) sop, 0.0, scale); Deleted: VASSAL-src/trunk/src/VASSAL/tools/imageop/OpErrorDialog.java =================================================================== --- VASSAL-src/trunk/src/VASSAL/tools/imageop/OpErrorDialog.java 2008-10-27 10:48:19 UTC (rev 4352) +++ VASSAL-src/trunk/src/VASSAL/tools/imageop/OpErrorDialog.java 2008-10-27 12:17:29 UTC (rev 4353) @@ -1,86 +0,0 @@ -/* - * $Id$ - * - * Copyright (c) 2008 by Joel Uckelman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License (LGPL) as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, copies are available - * at http://www.opensource.org. - */ - -package VASSAL.tools.imageop; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.concurrent.ExecutionException; - -import VASSAL.build.BadDataReport; -import VASSAL.i18n.Resources; -import VASSAL.tools.ErrorDialog; -import VASSAL.tools.ErrorUtils; - -/** - * @author Joel Uckelman - * @since 3.1.0 - */ -public class OpErrorDialog { - private OpErrorDialog() {} - - public static void error(ExecutionException e, ImageOp op) { - // unpack the exception - final IOException ioe = ErrorUtils.getAncestorOfClass(IOException.class, e); - if (ioe != null) { -// FIXME! - if (ioe instanceof FileNotFoundException) { - // the file doesn't exist - final SourceOp sop = findSourceOp(op); - final String filename = sop != null ? sop.getName() : ""; - - ErrorDialog.dataError( - new BadDataReport("Image not found", filename, ioe)); - - ErrorDialog.error( - Resources.getString("Error.file_not_found"), - Resources.getString("Error.file_not_found"), - e, - Resources.getString("Error.file_not_found_message", filename), - ioe.getMessage() - ); - } - else { - // otherwise we had some other kind of I/O problem - ErrorDialog.error( - Resources.getString("Error.io_error"), - Resources.getString("Error.io_error"), - e, - Resources.getString("Error.io_error_message"), - ioe.getMessage() - ); - } - } - else { - // otherwise this is a bug - ErrorDialog.bug(e); - } - } - - private static SourceOp findSourceOp(VASSAL.tools.opcache.Op<?> op) { - if (op instanceof SourceOp) return (SourceOp) op; - - for (VASSAL.tools.opcache.Op<?> src : op.getSources()) { - final SourceOp sop = findSourceOp(src); - if (sop != null) return sop; - } - - return null; - } -} Modified: VASSAL-src/trunk/src/VASSAL/tools/imageop/SourceOpBitmapImpl.java =================================================================== --- VASSAL-src/trunk/src/VASSAL/tools/imageop/SourceOpBitmapImpl.java 2008-10-27 10:48:19 UTC (rev 4352) +++ VASSAL-src/trunk/src/VASSAL/tools/imageop/SourceOpBitmapImpl.java 2008-10-27 12:17:29 UTC (rev 4353) @@ -80,15 +80,8 @@ * @throws IOException if the image cannot be loaded from the image file. */ public Image eval() throws IOException { - if (size == null) fixSize(); - try { - if (ImageUtils.isLargeImage(size.width, size.height)) { - return ImageUtils.getLargeImage(archive.getImageInputStream(name)); - } - else { - return ImageUtils.getSmallImage(archive.getImageInputStream(name)); - } + return ImageUtils.getImage(archive.getImageInputStream(name)); } catch (FileNotFoundException e) { throw new MissingImageException(name, e); Copied: VASSAL-src/trunk/src/VASSAL/tools/imageop/SourceOpMappedBitmapImpl.java (from rev 4333, VASSAL-src/branches/uckelman-work/src/VASSAL/tools/imageop/SourceOpMappedBitmapImpl.java) =================================================================== --- VASSAL-src/trunk/src/VASSAL/tools/imageop/SourceOpMappedBitmapImpl.java (rev 0) +++ VASSAL-src/trunk/src/VASSAL/tools/imageop/SourceOpMappedBitmapImpl.java 2008-10-27 12:17:29 UTC (rev 4353) @@ -0,0 +1,56 @@ +/* + * $Id: Board.java 4333 2008-10-26 14:13:58Z uckelman $ + * + * Copyright (c) 2008 by Joel Uckelman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License (LGPL) as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, copies are available + * at http://www.opensource.org. + */ +package VASSAL.tools.imageop; + +import java.awt.Image; +import java.io.FileNotFoundException; +import java.io.IOException; + +import VASSAL.tools.DataArchive; +import VASSAL.tools.memmap.MappedImageUtils; + +/** + * @author Joel Uckelman + * @since 3.1.0 + */ +public class SourceOpMappedBitmapImpl extends SourceOpBitmapImpl + implements SourceOp { + public SourceOpMappedBitmapImpl(String name) { + super(name); + } + + public SourceOpMappedBitmapImpl(String name, DataArchive archive) { + super(name, archive); + } + + /** + * {@inheritDoc} + * + * @throws IOException if the image cannot be loaded from the image file. + */ + @Override + public Image eval() throws IOException { + try { + return MappedImageUtils.getImage(archive.getImageInputStream(name)); + } + catch (FileNotFoundException e) { + throw new MissingImageException(name, e); + } + } +} Modified: VASSAL-src/trunk/src/VASSAL/tools/memmap/MappedBufferedImage.java =================================================================== --- VASSAL-src/trunk/src/VASSAL/tools/memmap/MappedBufferedImage.java 2008-10-27 10:48:19 UTC (rev 4352) +++ VASSAL-src/trunk/src/VASSAL/tools/memmap/MappedBufferedImage.java 2008-10-27 12:17:29 UTC (rev 4353) @@ -46,9 +46,9 @@ super(cm, raster, cm.isAlphaPremultiplied(), null); } - public static BufferedImage createMemoryMappedImage(ColorModel cm, - SampleModel sm) - throws IOException { + public static MappedBufferedImage createMemoryMappedImage(ColorModel cm, + SampleModel sm) + throws IOException { // determine how many banks the DataBuffer should have int maxBank = 0; if (sm instanceof ComponentSampleModel) { @@ -92,8 +92,8 @@ return new MappedBufferedImage(cm ,raster); } - public static BufferedImage createIntARGBMemoryMappedImage(int w, int h) - throws IOException { + public static MappedBufferedImage createIntARGBMemoryMappedImage(int w, int h) + throws IOException { return createMemoryMappedImage( new DirectColorModel( 32, Copied: VASSAL-src/trunk/src/VASSAL/tools/memmap/MappedImageUtils.java (from rev 4333, VASSAL-src/branches/uckelman-work/src/VASSAL/tools/memmap/MappedImageUtils.java) =================================================================== --- VASSAL-src/trunk/src/VASSAL/tools/memmap/MappedImageUtils.java (rev 0) +++ VASSAL-src/trunk/src/VASSAL/tools/memmap/MappedImageUtils.java 2008-10-27 12:17:29 UTC (rev 4353) @@ -0,0 +1,104 @@ +package VASSAL.tools.memmap; + +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.SampleModel; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.stream.FileCacheImageInputStream; +import javax.imageio.stream.ImageInputStream; + +import VASSAL.build.GameModule; +import VASSAL.tools.IOUtils; +import VASSAL.tools.TempFileManager; + + +public class MappedImageUtils { + + private MappedImageUtils() { } + + public static MappedBufferedImage getImage(InputStream in) + throws IOException { + final MappedBufferedImage img = loadImage(in); + return img.getType() != BufferedImage.TYPE_INT_ARGB ? toIntARGB(img) : img; + } + + private static MappedBufferedImage loadImage(InputStream in) + throws IOException { + MappedBufferedImage img = null; + ImageInputStream iis = null; + ImageReader reader = null; + try { + iis = new FileCacheImageInputStream( + in, TempFileManager.getInstance().getSessionRoot() + ); + + final Iterator<ImageReader> i = ImageIO.getImageReaders(iis); + if (!i.hasNext()) throw new IOException("Unrecognized image format"); + + reader = i.next(); + reader.setInput(iis); + + final int w = reader.getWidth(0); + final int h = reader.getHeight(0); + + final ImageTypeSpecifier type = reader.getImageTypes(0).next(); + + // get our ColorModel and SampleModel + final ColorModel cm = type.getColorModel(); + final SampleModel sm = + type.getSampleModel().createCompatibleSampleModel(w,h); + + img = MappedBufferedImage.createMemoryMappedImage(cm, sm); + + final ImageReadParam param = reader.getDefaultReadParam(); + param.setDestination(img); + reader.read(0, param); + + iis.close(); + in.close(); + + return img; + } + finally { + reader.dispose(); + IOUtils.closeQuietly(iis); + IOUtils.closeQuietly(in); + } + } + + private static MappedBufferedImage toIntARGB(MappedBufferedImage src) + throws IOException { + return rowByRowCopy( + src, + MappedBufferedImage.createIntARGBMemoryMappedImage( + src.getWidth(), src.getHeight()) + ); + } + + private static MappedBufferedImage rowByRowCopy(MappedBufferedImage src, + MappedBufferedImage dst) { + final int h = src.getHeight(); + final int[] row = new int[src.getWidth()]; + for (int y = 0; y < h; ++y) { + src.getRGB(0, y, row.length, 1, row, 0, row.length); + dst.setRGB(0, y, row.length, 1, row, 0, row.length); + } + return dst; + } + + public static MappedBufferedImage createImage(int w, int h) { + try { + return MappedBufferedImage.createIntARGBMemoryMappedImage(w, h); + } + catch (IOException e) { + throw (OutOfMemoryError) (new OutOfMemoryError().initCause(e)); + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ _______________________________________________ vassalengine-svn mailing list vas...@li... https://lists.sourceforge.net/lists/listinfo/vassalengine-svn |