Welcome to the Bookstract home page!

Bookstract is a simple program to provide a snapshot of the structure of a text document.

Here is an applet to let you play around with it:

No Java 2 SDK, Standard Edition v 1.4.2 support for Applet.

Try the Bookstract quiz


Bookstract is also available in command-line form as a Java program under the terms of the GNU Version 2 License.

/* Copyright 2006 by Dave Horlick Bookstract is free software; you can redistribute it and/or modify it under the terms of the version 2 GNU General Public License, published by the Free Software Foundation. Bookstract is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ package org.riverporpoise; import java.io.*; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.imageio.ImageIO; public class Bookstract { private int greatestWidth; private int lines; private List chars = new ArrayList(); public int spacesPerTab = 4; private int letterColor = 0; private int spaceColor = (246 << 16) | (246 << 8) | 246; private int backgroundColor = spaceColor; public static void main(String [] args) { if (args.length==2) { try { new Bookstract().go(new File(args[0]), new File(args[1])); } catch (IOException exception) { throw new RuntimeException(exception); } } else { System.out.println("usage: java org.riverporpoise.Bookstract input.txt new-image.png"); } } public void go(File input, File output) throws IOException { FileInputStream fileInputStream = new FileInputStream(input); // System.out.print("Reading "); // System.out.print(input.getName()); BufferedImage image = textToImage(new InputStreamReader(fileInputStream)); ImageIO.write(image, "png", output); } public BufferedImage textToImage(String text) { try { return textToImage(new StringReader(text)); } catch (IOException exception) { // I can't think of a scenario that would actually precipitate this. exception.printStackTrace(); return null; } } public BufferedImage textToImage(Reader reader) throws IOException { BufferedReader bufferedReader = null; if (reader instanceof BufferedReader) { bufferedReader = (BufferedReader) reader; } else { bufferedReader = new BufferedReader(reader); } String line = null; for (; (line = bufferedReader.readLine())!=null; lines++) { if (line.length()>greatestWidth) greatestWidth = line.length(); for (int index=0; index<=line.length()-1; index++) { switch (line.charAt(index)) { case '\t': for (int spaceLoop=0; spaceLoop<=spacesPerTab-1; spaceLoop++) chars.add(Boolean.FALSE); break; case ' ': chars.add(Boolean.FALSE); break; default: if (!Character.isISOControl(line.charAt(index))) chars.add(Boolean.TRUE); } } // System.out.print("."); chars.add(null); } // System.out.println(); bufferedReader.close(); final BufferedImage image = new BufferedImage(greatestWidth, (lines*2), BufferedImage.TYPE_BYTE_GRAY); int x = 0; int y = 0; Iterator walk = chars.iterator(); // System.out.println("image width = "+greatestWidth); // System.out.println("image height = "+lines); for (int col = 0; col <= greatestWidth-1; col++) { for (int row = 0; row <= (lines*2)-1; row++) { image.setRGB(col, row, backgroundColor); } } // System.out.print("Writing "); // System.out.print(output.getName()); while (walk.hasNext()) { Boolean theChar = (Boolean) walk.next(); // System.out.println("\twriting ("+x+", "+y+")"); if (theChar==Boolean.TRUE) { // System.out.print("b"); image.setRGB(x, y, letterColor); x++; } else if (theChar==Boolean.FALSE) { // System.out.print("w"); image.setRGB(x, y, spaceColor); x++; } else if (theChar==null) { // System.out.print("."); x=0; y++; y++; } walk.remove(); } // System.out.println(); return image; } }