new, improved and shiny version, courtesy of Jos Hirth

This commit is contained in:
Brian Matzon 2006-03-10 18:49:34 +00:00
parent e34ce0f20c
commit 0c539252b4
1 changed files with 126 additions and 85 deletions

View File

@ -1,12 +1,13 @@
package org.lwjgl.util; package org.lwjgl.util;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.HashMap; import java.util.HashMap;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -15,32 +16,41 @@ import java.util.StringTokenizer;
* <p> * <p>
* NOTE: This simple XPM reader does not support extensions nor hotspots * NOTE: This simple XPM reader does not support extensions nor hotspots
* </p> * </p>
*
* @author Brian Matzon <brian@matzon.dk> * @author Brian Matzon <brian@matzon.dk>
* @author Jos Hirth
* @version $Revision$ * @version $Revision$
*/ */
public class XPMFile { public class XPMFile {
/** Array of bytes (RGBA) */ /** Array of bytes (RGBA) */
private byte bytes[] = null; private byte bytes[] = null;
/** Height of image */ private final static int WIDTH = 0;
private int height = 0;
/** Width of image */ private final static int HEIGHT = 1;
private int width = 0;
private final static int NUMBER_OF_COLORS = 2;
private final static int CHARACTERS_PER_PIXEL = 3;
private static int[] format = new int[4];
/* /*
* Private constructor, use load(String filename) * Private constructor, use load(String filename)
*/ */
private XPMFile() { } private XPMFile() {
}
/** /**
* Loads the XPM file * Loads the XPM file
* *
* @param file path to file * @param file
* path to file
* @return XPMFile loaded, or exception * @return XPMFile loaded, or exception
* @throws IOException If any IO exceptions occurs while reading file * @throws IOException
* If any IO exceptions occurs while reading file
*/ */
public static XPMFile load(String file) throws IOException { public static XPMFile load(String file) throws IOException {
return load(new FileInputStream(new File(file))); return load(new FileInputStream(new File(file)));
@ -49,9 +59,11 @@ public class XPMFile {
/** /**
* Loads the XPM file * Loads the XPM file
* *
* @param is InputStream to read file from * @param is
* InputStream to read file from
* @return XPMFile loaded, or exception * @return XPMFile loaded, or exception
* @throws IOException If any IO exceptions occurs while reading file * @throws IOException
* If any IO exceptions occurs while reading file
*/ */
public static XPMFile load(InputStream is) throws IOException { public static XPMFile load(InputStream is) throws IOException {
XPMFile xFile = new XPMFile(); XPMFile xFile = new XPMFile();
@ -63,14 +75,14 @@ public class XPMFile {
* @return the height of the image. * @return the height of the image.
*/ */
public int getHeight() { public int getHeight() {
return height; return format[HEIGHT];
} }
/** /**
* @return the width of the image. * @return the width of the image.
*/ */
public int getWidth() { public int getWidth() {
return width; return format[WIDTH];
} }
/** /**
@ -83,101 +95,130 @@ public class XPMFile {
/** /**
* Read the image from the specified file. * Read the image from the specified file.
* *
* @throws IOException If any IO exceptions occurs while reading file * @throws IOException
* If any IO exceptions occurs while reading file
*/ */
private void readImage(InputStream is) throws IOException { private void readImage(InputStream is) throws IOException {
try { try {
BufferedReader br = new BufferedReader(new InputStreamReader(is)); LineNumberReader reader = new LineNumberReader(
new InputStreamReader(is));
HashMap colors = new HashMap(); HashMap colors = new HashMap();
String comment = br.readLine(); format = parseFormat(nextLineOfInterest(reader));
String typedef = br.readLine();
int[] format = parseFormat(br.readLine());
// setup color mapping // setup color mapping
for (int i = 0; i < format[2]; i++) { for (int i = 0; i < format[NUMBER_OF_COLORS]; i++) {
Object[] colorDefinition = parseColor(br.readLine()); Object[] colorDefinition = parseColor(nextLineOfInterest(reader));
colors.put(colorDefinition[0], colorDefinition[1]); colors.put(colorDefinition[0], colorDefinition[1]);
} }
// read actual image (convert to RGBA) // read actual image (convert to RGBA)
bytes = new byte[format[0] * format[1] * 4]; bytes = new byte[format[WIDTH] * format[HEIGHT] * 4];
for (int i = 0; i < format[1]; i++) { for (int i = 0; i < format[HEIGHT]; i++) {
parseImageLine(br.readLine(), format, colors, i); parseImageLine(nextLineOfInterest(reader), format, colors, i);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
throw new IllegalArgumentException("Unable to parse XPM File"); throw new IllegalArgumentException("Unable to parse XPM File");
} }
} }
/**
* Finds the next interesting line of text.
*
* @param reader
* The LineNumberReader to read from
* @return The next interesting String (with stripped quotes)
* @throws IOException
* If any IO exceptions occurs while reading file
*/
private String nextLineOfInterest(LineNumberReader reader)
throws IOException {
String ret;
do {
ret = reader.readLine();
} while (!ret.startsWith("\""));
// lacks sanity check
return ret.substring(1, ret.lastIndexOf('\"'));
}
/** /**
* Parses the format of the xpm file given a format string * Parses the format of the xpm file given a format string
* *
* @param format String to parse * @param format
* String to parse
* @return Array specifying width, height, colors, characters per pixel * @return Array specifying width, height, colors, characters per pixel
*/ */
private int[] parseFormat(String format) { private int[] parseFormat(String format) {
// format should look like this: // format should look like this:
// "16 16 122 2", // 16 16 122 2
// nuke first and last " and last ,
format = format.substring(1, format.length() - 2);
// tokenize it // tokenize it
StringTokenizer st = new StringTokenizer(format); StringTokenizer st = new StringTokenizer(format);
return new int[] { return new int[] { Integer.parseInt(st.nextToken()), /* width */
Integer.parseInt(st.nextToken()), /* width */ Integer.parseInt(st.nextToken()), /* height */
Integer.parseInt(st.nextToken()), /* height */ Integer.parseInt(st.nextToken()), /* colors */
Integer.parseInt(st.nextToken()), /* colors */ Integer.parseInt(st.nextToken()) /* chars per pixel */
Integer.parseInt(st.nextToken()) /* chars per pixel */
}; };
} }
/** /**
* Given a line defining a color/pixel, parses this into an array containing * Given a line defining a color/pixel, parses this into an array containing
* a key and a color * a key and a color
* @param line Line to parse *
* @param line
* Line to parse
* @return Array containing a key (String) and a color (Integer) * @return Array containing a key (String) and a color (Integer)
*/ */
private Object[] parseColor(String line) { private Object[] parseColor(String line) {
// line should look like this // line should look like this:
// "# c #0A0A0A", // # c #0A0A0A
// nuke first and last " // NOTE: will break if the color is something like "black" or "gray50"
line = line.substring(1, line.length() - 2); // etc (instead of #rrggbb).
String key = line.substring(0, 2); String key = line.substring(0, format[CHARACTERS_PER_PIXEL]);
String type = line.substring(3, 4); // since we always assume color as type we dont need to read it
String color = line.substring(6); // String type = line.substring(format[CHARACTERS_PER_PIXEL] + 1,
// format[CHARACTERS_PER_PIXEL] + 2);
String color = line.substring(format[CHARACTERS_PER_PIXEL] + 4);
// we always assume type is color, and supplied as #<r><g><b> // we always assume type is color, and supplied as #<r><g><b>
return new Object[] { key, new Integer(Integer.parseInt(color, 16))}; return new Object[] { key, new Integer(Integer.parseInt(color, 16)) };
} }
/** /**
* Parses an Image line into its byte values * Parses an Image line into its byte values
* @param line Line of chars to parse *
* @param format Format to expext it in * @param line
* @param colors Colors to lookup * Line of chars to parse
* @param index current index into lines, we've reached * @param format
* Format to expext it in
* @param colors
* Colors to lookup
* @param index
* current index into lines, we've reached
*/ */
private void parseImageLine(String line, int[] format, HashMap colors, int index) { private void parseImageLine(String line, int[] format, HashMap colors,
int index) {
// offset for next line // offset for next line
int offset = index * 4 * format[0]; int offset = index * 4 * format[WIDTH];
// nuke first " // read <format[CHARACTERS_PER_PIXEL]> characters <format[WIDTH]> times,
line = line.substring(1, line.length()); // each iteration equals one pixel
for (int i = 0; i < format[WIDTH]; i++) {
// read format[3] characters format[0] times, each iteration is one color String key = line
for (int i = 0; i < format[0]; i++) { .substring(
String key = line.substring(i * 2, (i * 2 + 2)); i * format[CHARACTERS_PER_PIXEL],
(i * format[CHARACTERS_PER_PIXEL] + format[CHARACTERS_PER_PIXEL]));
Integer color = (Integer) colors.get(key); Integer color = (Integer) colors.get(key);
bytes[offset + (i * 4) ] = (byte) ((color.intValue() & 0x00ff0000) >> 16); bytes[offset + (i * 4)] = (byte) ((color.intValue() & 0x00ff0000) >> 16);
bytes[offset + ((i * 4) + 1)] = (byte) ((color.intValue() & 0x0000ff00) >> 8); bytes[offset + ((i * 4) + 1)] = (byte) ((color.intValue() & 0x0000ff00) >> 8);
bytes[offset + ((i * 4) + 2)] = (byte) ((color.intValue() & 0x000000ff) >> 0); // looks better :) bytes[offset + ((i * 4) + 2)] = (byte) ((color.intValue() & 0x000000ff) >> 0); // looks
bytes[offset + ((i * 4) + 3)] = (byte) 0xff; // always 0xff alpha // better
// :)
bytes[offset + ((i * 4) + 3)] = (byte) 0xff; // always 0xff alpha
} }
} }
@ -192,16 +233,16 @@ public class XPMFile {
try { try {
String out = args[0].substring(0, args[0].indexOf(".")) + ".raw"; String out = args[0].substring(0, args[0].indexOf(".")) + ".raw";
XPMFile file = XPMFile.load(args[0]); XPMFile file = XPMFile.load(args[0]);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(out))); BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(new File(out)));
bos.write(file.getBytes()); bos.write(file.getBytes());
bos.close(); bos.close();
//showResult(file.getBytes()); // showResult(file.getBytes());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
/* /*
private static void showResult(byte[] bytes) { private static void showResult(byte[] bytes) {
final BufferedImage i = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); final BufferedImage i = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);