package org.artisanlogiciel.xpm; import java.awt.*; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.InputStream; import java.util.HashMap; import java.util.Scanner; public class Xpm { int width; int height; Color palette[] = null; HashMap charColorIndex = null; // reversed y,x ( since xpm is line based ). short pixels[][] = null; int colors; // current filling of pixels[cy][cx] int cx=0; int cy=0; // number of char for color name int chars; DataInputStream input = null; Scanner scanner = null; public int getWidth() { return width; } public int getHeight() { return height; } public Color getColor(int x, int y) { if ( ( x >= 0 ) && ( x < width ) && ( y >= 0 ) && ( y < height )) { return palette[pixels[y][x]]; } else { return palette[pixels[0][0]]; } } public Color parseColor(String pColor) { if ( pColor.substring(0,1).equals("#")) { String r = pColor.substring(1,3); String g = pColor.substring( 3,5); String b = pColor.substring( 5, 7); return new Color(Integer.parseInt(r,16),Integer.parseInt(g, 16),Integer.parseInt(b, 16)); } return null; } public Color parseColorLine(String pLine, int color) { // "charsc#RhexGhexBhex" int firsttab = pLine.indexOf('\t'); String charindex = pLine.substring(0,firsttab); charColorIndex.put(charindex, new Integer(color)); int space = pLine.lastIndexOf(' '); return parseColor(pLine.substring(space + 1)); } public boolean parseHeader(String pLine) { // "309 295 674 2" String words[] = pLine.split(" "); width = Integer.parseInt(words[0]); height = Integer.parseInt(words[1]); colors = Integer.parseInt(words[2]); chars = Integer.parseInt(words[3]); pixels = new short[height][width]; charColorIndex = new HashMap<>(colors); palette = new Color[colors]; return true; } int getIndexFromString(String pString) { Integer i = charColorIndex.get(pString); return i.intValue(); } Color getColorFromString(String pString) { return palette[getIndexFromString(pString)]; } void parseLine(String pLine) { for(int i = 0; i < pLine.length(); i+=2 ) { CharSequence seq = pLine.subSequence(i, i+chars); pixels[cy][cx++]= (short) getIndexFromString(seq.toString()); if ( cx >= width ) { cx = 0; cy++; } } } // get only lines containing full strings String readLine() { try { String line = scanner.nextLine(); while (line != null) { int first_space = line.indexOf('"'); int last_space = line.lastIndexOf('"'); if ((first_space >= 0) && (last_space > first_space + 1)) { String stripped = line.substring(first_space + 1, last_space); // System.out.println(stripped); return stripped; } System.out.println("!!" + line + "!!"); line = scanner.nextLine(); } } catch(Exception e) { System.err.println("!"); } return null; } public boolean parse(InputStream stream) { scanner = new Scanner(stream); String line = readLine(); if (line != null) { parseHeader(line); for (int l=0; l < colors; l++) { line = readLine(); if (line != null) { palette[l] = parseColorLine(line,l); } else { scanner = null; return false; } } for (int l=0; l< height; l++) { line = readLine(); if (line != null ) { parseLine(line); } else { scanner = null; return false; } } scanner = null; return true; } scanner = null; return false; } public String toString() { StringBuffer b = new StringBuffer(); for (int l = 0 ; l < palette.length; l++) { b.append( palette[l].toString()); } return b.toString(); } public static void main(String pArgs[]) { if (pArgs.length > 0) { try { String filename = pArgs[0]; System.out.println("PArsing xpm " + filename); FileInputStream f = new FileInputStream(filename); Xpm xpm = new Xpm(); if ( xpm.parse(f) ) { System.out.println(xpm.toString()); } else { System.err.println("Fail to parse " + filename); } } catch (Exception e) { e.printStackTrace(); } } } }