/* Reorganize (c) 2006 Bjørn Lindeijer * License: GPL, v2 or later */ import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.util.Vector; import java.io.IOException; import java.io.File; import javax.imageio.ImageIO; /** * Tool to reorganize the headgears. */ public class Reorganize { private static final int SPRITE_WIDTH = 60; private static final int SPRITE_HEIGHT = 60; private static final int FRAMES = 10; private static final int DIRECTIONS = 4; private static final int HAIR_COLORS = 10; private static final int HAIR_FRAMES = 9; private static final int HAIR_SPRITE_WIDTH = 40; private static final int HAIR_SPRITE_HEIGHT = 40; private static final int TRANSPARENT = new Color(255, 0, 255).getRGB(); public static void main(String[] arg) { if (arg.length != 2) { System.out.println("Usage:\n java Reorganize [source] [target]"); return; } BufferedImage source = null; try { source = ImageIO.read(new File(arg[0])); } catch (IOException e) { System.out.println("Error while trying to read " + arg[0] + "."); e.printStackTrace(); System.exit(1); } // Read the existing frames into a vector Vector spriteSet = gridCut(source, HAIR_SPRITE_WIDTH, HAIR_SPRITE_HEIGHT, HAIR_FRAMES, 1); // Determine minimal rectangle that can still contain the contents of // any frame /* Rectangle cropRect = minimumCropRect(spriteSet); if (cropRect == null) { System.out.println( "Error: no optimal crop rect could be determined."); System.exit(1); } System.out.println(arg[0] + ": width=\"" + cropRect.width + "\" height=\"" + cropRect.height + "\""); */ filterHeadgear(spriteSet); BufferedImage target = gridDraw( spriteSet, new Rectangle(0, 0, HAIR_SPRITE_WIDTH, HAIR_SPRITE_HEIGHT), HAIR_FRAMES - 4, 1); // Save the target image try { ImageIO.write(target, "png", new File(arg[1])); } catch (IOException e) { System.out.println("Error while trying to write " + arg[1] + "."); e.printStackTrace(); System.exit(1); } } private static Vector gridCut( BufferedImage source, int width, int height, int xFrames, int yFrames) { Vector spriteSet = new Vector(); for (int y = 0; y < yFrames; y++) { for (int x = 0; x < xFrames; x++) { BufferedImage sprite = source.getSubimage( x * width, y * height, width, height); spriteSet.add(sprite); } } return spriteSet; } private static BufferedImage gridDraw(Vector spriteSet, Rectangle cropRect, int xFrames, int yFrames) { // Create a new image BufferedImage target = new BufferedImage( xFrames * cropRect.width, yFrames * cropRect.height, BufferedImage.TYPE_INT_ARGB); // Draw the frames onto the target image Graphics g = target.getGraphics(); for (int y = 0; y < yFrames; y++) { for (int x = 0; x < xFrames; x++) { g.drawImage( spriteSet.get(x + xFrames * y).getSubimage( cropRect.x, cropRect.y, cropRect.width, cropRect.height), x * cropRect.width, y * cropRect.height, null); } } return target; } private static Rectangle minimumCropRect(Vector spriteSet) { Rectangle cropRect = null; for (BufferedImage sprite : spriteSet) { Rectangle frameCropRect = determineCropRect(sprite); if (cropRect == null) { cropRect = frameCropRect; } else { cropRect.add(frameCropRect); } } // Make crop rect one pixel larger (since we want an inclusive rect) if (cropRect != null) { cropRect.add( cropRect.x + cropRect.width + 1, cropRect.y + cropRect.height + 1); } return cropRect; } private static Rectangle determineCropRect(BufferedImage image) { // Loop through all the pixels, ignoring transparent ones. Rectangle rect = null; for (int y = 0; y < image.getHeight(); y++) { for (int x = 0; x < image.getWidth(); x++) { int color = image.getRGB(x, y); if (color != TRANSPARENT && (color & 0xFF000000) != 0) { if (rect == null) { rect = new Rectangle(x, y, 0, 0); } else { rect.add(x, y); } } } } return rect; } private static void filterHairstyle(Vector spriteSet) { // Remove frame 1, 2, 6 and 7 from each color for (int i = HAIR_COLORS - 1; i >= 0; i--) { spriteSet.remove(i * HAIR_FRAMES + 7); spriteSet.remove(i * HAIR_FRAMES + 6); spriteSet.remove(i * HAIR_FRAMES + 2); spriteSet.remove(i * HAIR_FRAMES + 1); } } private static void filterHeadgear(Vector spriteSet) { // Remove frame 1, 2, 6 and 7 spriteSet.remove(7); spriteSet.remove(6); spriteSet.remove(2); spriteSet.remove(1); } }