From c3c08a03b3eb956fdecf51cbbc73f1d3226c8737 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Fri, 21 Jun 2002 18:09:37 +0000 Subject: [PATCH] Refactored the tileset trimming code so that it can more easily be reused to trim object tilesets. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1524 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../bundle/tools/ComponentBundlerTask.java | 5 +- .../threerings/media/tile/TrimmedTileSet.java | 63 ++++++++++++---- .../media/tile/util/TileSetTrimmer.java | 72 +++++++++++-------- 3 files changed, 96 insertions(+), 44 deletions(-) diff --git a/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java b/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java index f453f5b51..340e72138 100644 --- a/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java +++ b/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java @@ -1,5 +1,5 @@ // -// $Id: ComponentBundlerTask.java,v 1.9 2002/06/19 08:33:14 mdb Exp $ +// $Id: ComponentBundlerTask.java,v 1.10 2002/06/21 18:09:37 mdb Exp $ package com.threerings.cast.bundle.tools; @@ -43,7 +43,6 @@ import com.threerings.media.tile.ImageProvider; import com.threerings.media.tile.TileSet; import com.threerings.media.tile.TrimmedTileSet; import com.threerings.media.tile.tools.xml.SwissArmyTileSetRuleSet; -import com.threerings.media.tile.util.TileSetTrimmer; import com.threerings.cast.ComponentIDBroker; import com.threerings.cast.bundle.BundleUtil; @@ -183,7 +182,7 @@ public class ComponentBundlerTask extends Task } }); TrimmedTileSet tset = - TileSetTrimmer.trimTileSet(aset, jout); + TrimmedTileSet.trimTileSet(aset, jout); tset.setImagePath(ipath); tset.setName(aset.getName()); diff --git a/src/java/com/threerings/media/tile/TrimmedTileSet.java b/src/java/com/threerings/media/tile/TrimmedTileSet.java index c097e0c86..bd5622f25 100644 --- a/src/java/com/threerings/media/tile/TrimmedTileSet.java +++ b/src/java/com/threerings/media/tile/TrimmedTileSet.java @@ -1,11 +1,16 @@ // -// $Id: TrimmedTileSet.java,v 1.1 2002/05/06 18:08:32 mdb Exp $ +// $Id: TrimmedTileSet.java,v 1.2 2002/06/21 18:09:34 mdb Exp $ package com.threerings.media.tile; import java.awt.Image; import java.awt.Rectangle; +import java.io.IOException; +import java.io.OutputStream; + +import com.threerings.media.tile.util.TileSetTrimmer; + /** * Contains the necessary information to create a set of trimmed tiles * from a base image and the associated trim metrics. @@ -18,17 +23,6 @@ public class TrimmedTileSet extends TileSet return _obounds.length; } - /** - * Provides this tileset with access to the trimmed tile metrics. This - * generally only is called when generating a trimmed tileset from a - * regular tileset. - */ - public void setTileMetrics (Rectangle[] obounds, Rectangle[] tbounds) - { - _obounds = obounds; - _tbounds = tbounds; - } - // documentation inherited protected Rectangle computeTileBounds (int tileIndex, Image tilesetImage) { @@ -43,6 +37,51 @@ public class TrimmedTileSet extends TileSet tilesetImage, _obounds[tileIndex], _tbounds[tileIndex]); } + /** + * Creates a trimmed tileset from the supplied source tileset. See + * {@link TileSetTrimmer#trimTileSet} for further information. + */ + public static TrimmedTileSet trimTileSet ( + TileSet source, OutputStream destImage) + throws IOException + { + final TrimmedTileSet tset = new TrimmedTileSet(); + int tcount = source.getTileCount(); + + // grab the dimensions of the original tiles + tset._obounds = new Rectangle[tcount]; + for (int ii = 0; ii < tcount; ii++) { + try { + Tile tile = source.getTile(ii); + tset._obounds[ii] = new Rectangle(); + tset._obounds[ii].width = tile.getWidth(); + tset._obounds[ii].height = tile.getHeight(); + } catch (NoSuchTileException nste) { + String errmsg = "Urk! TileSet is ill-behaved. " + + "Claimed to have " + tcount + " tiles, but choked when " + + "we asked for tile " + ii + " [tset=" + source + "]."; + throw new RuntimeException(errmsg); + } + } + tset._tbounds = new Rectangle[tcount]; + + // create the trimmed tileset image + TileSetTrimmer.TrimMetricsReceiver tmr = + new TileSetTrimmer.TrimMetricsReceiver() { + public void trimmedTile (int tileIndex, int imageX, int imageY, + int trimX, int trimY, + int trimWidth, int trimHeight) { + tset._obounds[tileIndex].x = imageX; + tset._obounds[tileIndex].y = imageY; + tset._tbounds[tileIndex] = + new Rectangle(trimX, trimY, trimWidth, trimHeight); + } + }; + TileSetTrimmer.trimTileSet(source, destImage, tmr); + + return tset; + } + /** The width and height of the untrimmed tile, and the x and y offset * of the trimmed image within our tileset image. */ protected Rectangle[] _obounds; diff --git a/src/java/com/threerings/media/tile/util/TileSetTrimmer.java b/src/java/com/threerings/media/tile/util/TileSetTrimmer.java index 96434ed7a..9fa788471 100644 --- a/src/java/com/threerings/media/tile/util/TileSetTrimmer.java +++ b/src/java/com/threerings/media/tile/util/TileSetTrimmer.java @@ -1,5 +1,5 @@ // -// $Id: TileSetTrimmer.java,v 1.1 2002/06/19 08:29:59 mdb Exp $ +// $Id: TileSetTrimmer.java,v 1.2 2002/06/21 18:09:37 mdb Exp $ package com.threerings.media.tile.util; @@ -21,18 +21,45 @@ import com.threerings.media.Log; import com.threerings.media.tile.NoSuchTileException; import com.threerings.media.tile.Tile; import com.threerings.media.tile.TileSet; -import com.threerings.media.tile.TrimmedTileSet; import com.threerings.media.util.ImageUtil; /** - * Contains routines for generating a trimmed tileset from an existing - * tileset. Both a {@link TrimmedTileSet} instance and the associated - * trimmed image are created. + * Contains routines for trimming the images from an existing tileset + * which means that each tile is converted to an image that contains the + * smallest rectangular region of the original image that contains all + * non-transparent pixels. These trimmed images are then written out to a + * single image, packed together left to right. */ public class TileSetTrimmer { /** - * Generates a {@link TrimmedTileSet} from the supplied source + * Used to communicate the metrics of the trimmed tiles back to the + * caller so that they can do what they like with them. + */ + public static interface TrimMetricsReceiver + { + /** + * Called for each trimmed tile. + * + * @param tileIndex the index of the tile in the original tileset. + * @param imageX the x offset into the newly created tileset image + * of the trimmed image data. + * @param imageY the y offset into the newly created tileset image + * of the trimmed image data. + * @param trimX the x offset into the untrimmed tile image where + * the trimmed data begins. + * @param trimY the y offset into the untrimmed tile image where + * the trimmed data begins. + * @param trimWidth the width of the trimmed tile image. + * @param trimHeight the height of the trimmed tile image. + */ + public void trimmedTile (int tileIndex, int imageX, int imageY, + int trimX, int trimY, + int trimWidth, int trimHeight); + } + + /** + * Generates a trimmed tileset image from the supplied source * tileset. The source tileset must be configured with an image * provider so that the tile images can be obtained. The tile images * will be trimmed and a new tileset image generated and written to @@ -41,19 +68,16 @@ public class TileSetTrimmer * @param source the source tileset. * @param destImage an output stream to which the new trimmed image * will be written. + * @param tmr a callback object that will be used to inform the caller + * of the trimmed tile metrics. */ - public static TrimmedTileSet trimTileSet ( - TileSet source, OutputStream destImage) + public static void trimTileSet ( + TileSet source, OutputStream destImage, TrimMetricsReceiver tmr) throws IOException { int tcount = source.getTileCount(); BufferedImage[] timgs = new BufferedImage[tcount]; - // these will contain the width and height of the untrimmed tile, - // but the x and y offset of the trimmed tile image in the - // supplied tileset source image - Rectangle[] obounds = new Rectangle[tcount]; - // these will contain the bounds of the trimmed image in the // coordinate system defined by the untrimmed image Rectangle[] tbounds = new Rectangle[tcount]; @@ -71,25 +95,18 @@ public class TileSetTrimmer } // figure out how tightly we can trim it - obounds[ii] = new Rectangle( - 0, 0, timgs[ii].getWidth(), timgs[ii].getHeight()); tbounds[ii] = new Rectangle(); ImageUtil.computeTrimmedBounds(timgs[ii], tbounds[ii]); - // assign it a location in the trimmed tile image - obounds[ii].x = nextx; - nextx += tbounds[ii].width; + // let our caller know what we did + tmr.trimmedTile(ii, nextx, 0, tbounds[ii].x, tbounds[ii].y, + tbounds[ii].width, tbounds[ii].height); + + // adjust the new tileset image dimensions maxy = Math.max(maxy, tbounds[ii].height); + nextx += tbounds[ii].width; } - // create our tileset object - TrimmedTileSet ttset = new TrimmedTileSet(); - ttset.setTileMetrics(obounds, tbounds); - -// Log.info("Trimming [obounds=" + StringUtil.toString(obounds) + -// ", tbounds=" + StringUtil.toString(tbounds) + -// ", nwidth=" + nextx + ", nheight=" + maxy + "]."); - // create the new tileset image BufferedImage image = ImageUtil.createCompatibleImage( (BufferedImage)source.getTileSetImage(), nextx, maxy); @@ -107,8 +124,5 @@ public class TileSetTrimmer // write out trimmed image ImageIO.write(image, "png", destImage); - - // we're good to go - return ttset; } }