import java.util.*; import java.io.*; /******************************************************************************* Qt2Pbm: Converts from QuadTree format to PBM format. Note: Uses a Hashtable to store the information by label. Takes the quadtree from standard input and dumps the pbm to standard output. ******************************************************************************/ /* Class to store QuadTree data */ class QuadTree { public final static String ZERO = "0"; public final static String ONE = "1"; String element[] = new String[4]; //Name of quadtrees for top right, top left, bottom right and bottom left. public String toString(){ return("tl: " + element[0] + " tr: " + element[1] + " bl: " + element[2] + " br: " + element[3]); } } public class Qt2Pbm { int image[][]; int width; Hashtable quaddb; public Qt2Pbm(Reader in) throws IOException { quaddb = new Hashtable(); StreamTokenizer qtStrm = new StreamTokenizer(in); qtStrm.parseNumbers(); String qtName; QuadTree qt; //Read the width (which is the same as the height) of the image. qtStrm.nextToken(); if(qtStrm.ttype != qtStrm.TT_NUMBER){ throw new IOException("Was expecting the image size on line " +qtStrm.lineno() + " of input"); } width = (int) qtStrm.nval; image = new int[width][width]; // Now start reading individual lines qtStrm.nextToken(); while(qtStrm.ttype != qtStrm.TT_EOF ){ if(qtStrm.ttype != qtStrm.TT_WORD){ throw new IOException("Was expecting a label on line " +qtStrm.lineno() + " of input. Got " + qtStrm.sval); } qtName = qtStrm.sval; qt = new QuadTree(); qtStrm.nextToken(); if(qtStrm.ttype != ':'){ throw new IOException("Was expecting a colon on line " +qtStrm.lineno() + " of input"); } for(int i=0; i < 4; i++){ qtStrm.nextToken(); if(qtStrm.ttype == qtStrm.TT_NUMBER){ if(qtStrm.nval == 0){ qt.element[i] = QuadTree.ZERO; } else if(qtStrm.nval == 1){ qt.element[i] = QuadTree.ONE; } else { throw new IOException("Was expecting a 0 or 1 on line " +qtStrm.lineno() + " of input, not another number"); } } else if(qtStrm.ttype == '*'){ qtStrm.nextToken(); if(qtStrm.ttype != qtStrm.TT_WORD){ throw new IOException("Was expecting a label after the * on line " +qtStrm.lineno() + " of input"); } qt.element[i] = qtStrm.sval; } } qtStrm.nextToken(); quaddb.put(qtName, qt); } } void fillQuadrant(int depth, QuadTree qd, int top, int left) throws IOException { //System.err.println("Filling Quadrants. d = " + depth + " top = " + // top + " left = " + left + " qd = " + qd); //Note: the size to fill is the total width divided by 2^depth. //Do top left int quadrantsize = width/((int) Math.pow(2,(depth+1))); int starttop = 0; int startleft = 0; // For example, if the image size is 64, and this is depth zero, // each quadrant is 32 in size. for(int i = 0; i < 4; i++){ if(i == 0 || i == 2){ startleft = left; } else { startleft = left + quadrantsize; } if(i == 0 || i == 1){ starttop = top; } else { starttop = top + quadrantsize; } if(qd.element[i] == qd.ZERO){ for(int j = starttop; j < starttop+quadrantsize ; j++){ for(int k = startleft; k < startleft+quadrantsize; k++){ image[j][k] = 0; } } } else if(qd.element[i] == qd.ONE){ // System.err.println("This called. \n" + starttop + " " + startleft); for(int j = starttop; j < starttop+quadrantsize ; j++){ for(int k = startleft; k < startleft+quadrantsize; k++){ image[j][k] = 1; } } } else { QuadTree child = (QuadTree) quaddb.get(qd.element[i]); // System.err.println(child); if(child != null){ if(quadrantsize > 0){ fillQuadrant(depth+1,child, starttop, startleft); } } else { throw new IOException("Could not find the quadtree called: " + qd.element[i]); } } } } public void ConvertToImage() throws IOException { //Returns 0 if everything is cool. Some other number otherwise. QuadTree rootNode = (QuadTree) quaddb.get("root"); if(rootNode != null){ fillQuadrant(0, rootNode, 0, 0); } else{ throw new IOException("I could not find the root node."); } } public String toString(){ String retval = new String("Quadtree. Size: " + width + ". Contents: \n"); retval += quaddb.toString(); return retval; } public int WriteOutput(Writer out){ //Returns 0 if everything is cool; some other number otherwise PrintWriter pout = new PrintWriter(out); pout.print("P1\n"); pout.print(width + " " + width + "\n"); for(int i = 0; i < width; i++){ for(int j = 0; j < width; j++){ pout.print(image[i][j] +" "); } pout.println(); } pout.flush(); return 0; } public static void main(String args[]){ Qt2Pbm tree; try{ tree = new Qt2Pbm(new InputStreamReader(System.in)); //System.err.println(tree.toString()); tree.ConvertToImage(); tree.WriteOutput(new OutputStreamWriter(System.out)); } catch(IOException e){ System.err.println("Error occurred in trying to parse input"); System.err.println(e.getMessage()); } } }