From d756fa50cd5339206987731485b3342c4ce25f53 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Fri, 21 Jun 2002 18:53:13 +0000 Subject: [PATCH] Trimmed objects! The weight loss program proceeds apace. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1528 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../media/tile/TrimmedObjectTileSet.java | 117 ++++++++++++++++++ .../tile/bundle/tools/TileSetBundler.java | 74 ++++++++--- 2 files changed, 173 insertions(+), 18 deletions(-) create mode 100644 src/java/com/threerings/media/tile/TrimmedObjectTileSet.java diff --git a/src/java/com/threerings/media/tile/TrimmedObjectTileSet.java b/src/java/com/threerings/media/tile/TrimmedObjectTileSet.java new file mode 100644 index 000000000..eba5ba9c1 --- /dev/null +++ b/src/java/com/threerings/media/tile/TrimmedObjectTileSet.java @@ -0,0 +1,117 @@ +// +// $Id: TrimmedObjectTileSet.java,v 1.1 2002/06/21 18:53:13 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.samskivert.util.StringUtil; + +import com.threerings.media.Log; +import com.threerings.media.tile.util.TileSetTrimmer; + +/** + * An object tileset in which the objects have been trimmed to the + * smallest possible images that still contain all of their + * non-transparent pixels. The objects' origins are adjusted so that the + * objects otherwise behave exactly as the untrimmed objects and are thus + * interchangeable (and more memory efficient). + */ +public class TrimmedObjectTileSet extends TileSet +{ + // documentation inherited + public int getTileCount () + { + return _bounds.length; + } + + // documentation inherited + protected Rectangle computeTileBounds (int tileIndex, Image tilesetImage) + { + // N/A + return null; + } + + // documentation inherited + protected Tile createTile (int tileIndex, Image tilesetImage) + { + ObjectTile tile = new ObjectTile(tilesetImage, _bounds[tileIndex]); + tile.setBase(_ometrics[tileIndex].width, _ometrics[tileIndex].height); + tile.setOrigin(_ometrics[tileIndex].x, _ometrics[tileIndex].y); + return tile; + } + + // documentation inherited + protected void toString (StringBuffer buf) + { + super.toString(buf); + buf.append(", ometrics=").append(StringUtil.toString(_ometrics)); + buf.append(", bounds=").append(StringUtil.toString(_bounds)); + } + + /** + * Creates a trimmed object tileset from the supplied source object + * tileset. The image path must be set by hand to the appropriate path + * based on where the image data that is written to the + * destImage parameter is actually stored on the file + * system. See {@link TileSetTrimmer#trimTileSet} for further + * information. + */ + public static TrimmedObjectTileSet trimObjectTileSet ( + ObjectTileSet source, OutputStream destImage) + throws IOException + { + final TrimmedObjectTileSet tset = new TrimmedObjectTileSet(); + tset.setName(source.getName()); + int tcount = source.getTileCount(); + + // create our metrics arrays + tset._bounds = new Rectangle[tcount]; + tset._ometrics = new Rectangle[tcount]; + + // fill in the original object metrics + for (int ii = 0; ii < tcount; ii++) { + tset._ometrics[ii] = new Rectangle(); + if (source._xorigins != null) { + tset._ometrics[ii].x = source._xorigins[ii]; + } + if (source._yorigins != null) { + tset._ometrics[ii].y = source._yorigins[ii]; + } + tset._ometrics[ii].width = source._owidths[ii]; + tset._ometrics[ii].height = source._oheights[ii]; + } + + // 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._ometrics[tileIndex].x -= trimX; + tset._ometrics[tileIndex].y -= trimY; + tset._bounds[tileIndex] = + new Rectangle(imageX, imageY, trimWidth, trimHeight); + } + }; + TileSetTrimmer.trimTileSet(source, destImage, tmr); + +// Log.info("Trimmed object tileset " + +// "[bounds=" + StringUtil.toString(tset._bounds) + +// ", metrics=" + StringUtil.toString(tset._ometrics) + "]."); + + return tset; + } + + /** Contains the width and height of each object tile and the offset + * into the tileset image of their image data. */ + protected Rectangle[] _bounds; + + /** Contains the origin offset for each object tile and the object + * footprint width and height (in tile units). */ + protected Rectangle[] _ometrics; +} diff --git a/src/java/com/threerings/media/tile/bundle/tools/TileSetBundler.java b/src/java/com/threerings/media/tile/bundle/tools/TileSetBundler.java index ff9e64503..8bccba778 100644 --- a/src/java/com/threerings/media/tile/bundle/tools/TileSetBundler.java +++ b/src/java/com/threerings/media/tile/bundle/tools/TileSetBundler.java @@ -1,8 +1,11 @@ // -// $Id: TileSetBundler.java,v 1.6 2002/04/03 22:20:50 mdb Exp $ +// $Id: TileSetBundler.java,v 1.7 2002/06/21 18:53:13 mdb Exp $ package com.threerings.media.tile.bundle.tools; +import java.awt.Image; +import javax.imageio.ImageIO; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -28,8 +31,13 @@ import com.samskivert.io.NestableIOException; import com.samskivert.io.PersistenceException; import com.threerings.media.Log; + +import com.threerings.media.tile.ImageProvider; +import com.threerings.media.tile.ObjectTileSet; import com.threerings.media.tile.TileSet; import com.threerings.media.tile.TileSetIDBroker; +import com.threerings.media.tile.TrimmedObjectTileSet; + import com.threerings.media.tile.bundle.BundleUtil; import com.threerings.media.tile.bundle.TileSetBundle; import com.threerings.media.tile.tools.xml.TileSetRuleSet; @@ -202,7 +210,7 @@ public class TileSetBundler * or processing anything. */ public void createBundle ( - TileSetIDBroker idBroker, File bundleDesc, File target) + TileSetIDBroker idBroker, final File bundleDesc, File target) throws IOException { // stick an array list on the top of the stack into which we will @@ -270,18 +278,12 @@ public class TileSetBundler JarOutputStream jar = new JarOutputStream(fout, manifest); try { - // first write a serialized representation of the tileset - // bundle object to the bundle jar file - JarEntry entry = new JarEntry(BundleUtil.METADATA_PATH); - jar.putNextEntry(entry); - ObjectOutputStream oout = new ObjectOutputStream(jar); - oout.writeObject(bundle); - oout.flush(); - - // now write all of the image files to the bundle - Iterator setiter = bundle.enumerateTileSets(); - while (setiter.hasNext()) { - TileSet set = (TileSet)setiter.next(); + // write all of the image files to the bundle, converting the + // tilesets to trimmed tilesets in the process + Iterator iditer = bundle.enumerateTileSetIds(); + while (iditer.hasNext()) { + int tileSetId = ((Integer)iditer.next()).intValue(); + TileSet set = bundle.getTileSet(tileSetId); String imagePath = set.getImagePath(); // sanity checks @@ -291,13 +293,49 @@ public class TileSetBundler continue; } - // open the image and pipe it into the jar file - File imgfile = new File(bundleDesc.getParent(), imagePath); - FileInputStream imgin = new FileInputStream(imgfile); + // let the jar file know what's coming jar.putNextEntry(new JarEntry(imagePath)); - StreamUtils.pipe(imgin, jar); + + // if this is an object tileset, we can't trim it! + if (set instanceof ObjectTileSet) { + // set the tileset up with an image provider; we need to + // do this so that we can trim it! + set.setImageProvider(new ImageProvider() { + public Image loadImage (String path) + throws IOException { + File source = new File(bundleDesc.getParent(), + path); + return ImageIO.read(source); + } + }); + + // create a trimmed object tileset, which will write + // the trimmed tileset image to the jar output stream + TrimmedObjectTileSet tset = + TrimmedObjectTileSet.trimObjectTileSet( + (ObjectTileSet)set, jar); + tset.setImagePath(imagePath); + Log.info("Trimmed! " + tset); + // replace the original set with the trimmed tileset + // in the tileset bundle + bundle.addTileSet(tileSetId, tset); + + } else { + // open the image and pipe it into the jar file + File imgfile = new File(bundleDesc.getParent(), imagePath); + FileInputStream imgin = new FileInputStream(imgfile); + StreamUtils.pipe(imgin, jar); + } } + // now write a serialized representation of the tileset bundle + // object to the bundle jar file + JarEntry entry = new JarEntry(BundleUtil.METADATA_PATH); + jar.putNextEntry(entry); + ObjectOutputStream oout = new ObjectOutputStream(jar); + oout.writeObject(bundle); + oout.flush(); + // finally close up the jar file and call ourself done jar.close();