package ru.technocore.icfpc2007.ocr; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.util.*; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * User: zee * Date: Jul 22, 2007 * Time: 4:39:14 AM */ public class OcrMain { private final static Pattern REPLACE_PATTERN = Pattern.compile("^([0-9A-Z]+) (.*)$"); public static void main(String[] args) throws IOException { if (args.length < 6) { usage(); } String workMode = args[0]; String imageFile = args[1]; BufferedImage image = ImageIO.read(new File(imageFile)); int xstart = Integer.parseInt(args[2]); int ystart = Integer.parseInt(args[3]); int xend = Integer.parseInt(args[4]); int yend = Integer.parseInt(args[5]); int width = Integer.parseInt(args[6]); int height = Integer.parseInt(args[7]); if (workMode.equalsIgnoreCase("grid")) { drawGrid(image, xstart, ystart, xend, yend, width, height); ImageIO.write(image, "png", new File(args[8])); } else { List blocks = splitImage(image, xstart, ystart, xend, yend, width, height); Set uniqueBlocks = new LinkedHashSet(blocks); System.out.println("got " + blocks.size() + " blocks, " + uniqueBlocks.size() + " unique"); if (workMode.equalsIgnoreCase("blockinfo")) { System.exit(0); } else { Map blockIds = new HashMap(); int i = 10; for (Block uniqueBlock : uniqueBlocks) { blockIds.put(uniqueBlock.getHash(), i++); } boolean isMD5 = false; if (args.length == 10 && args[9].equalsIgnoreCase("md5")) { isMD5 = true; } if (workMode.equalsIgnoreCase("blockdump")) { File targetDir = new File(args[8]); for (Block uniqueBlock : uniqueBlocks) { outputBlock(uniqueBlock, blockIds, targetDir, isMD5); } } else if (workMode.equalsIgnoreCase("replace")) { Map replacements = getReplacements(args[8]); for (int j = 0; j < blocks.size(); j++) { Block block = blocks.get(j); String replacement; if (isMD5) { replacement = replacements.get(block.getHash()); } else { replacement = replacements.get(String.valueOf(blockIds.get(block.getHash()))); } if (replacement == null) { replacement = " "; } System.out.print(replacement); if (j % 19 == 18) { System.out.println(); } } } } } } private static void usage() { System.out.println("Usage: java -jar ocr.jar grid image-file xstart ystart xend yend width height out-file\n" + " or: java -jar ocr.jar blockinfo image-file xstart ystart xend yend width height \n" + " or: java -jar ocr.jar blockdump image-file xstart ystart xend yend width height output-dir [md5]\n" + " or: java -jar orc.jar replace image-file xstart ystart xend yend width height replace-file [md5]"); System.exit(-1); } private static Map getReplacements(String replacePath) throws IOException { Map result = new HashMap(); BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(replacePath))); String s; do { s = reader.readLine(); if (s != null) { Matcher m = REPLACE_PATTERN.matcher(s); m.find(); String n = m.group(1); String replace = m.group(2); result.put(n, replace); } } while (s != null); return result; } private static void outputBlock(Block block, Map blockIds, File targetDir, boolean md5) throws IOException { String filename; if (md5) { filename = block.getHash(); } else { filename = String.valueOf(blockIds.get(block.getHash())); } ImageIO.write(block.toImage(), "png", new File(targetDir, filename + ".png")); } private static List splitImage(BufferedImage image, int xstart, int ystart, int xend, int yend, int width, int height) { List result = new ArrayList(); int cy = ystart; while (image.getHeight() - cy >= xend) { int cx = xstart; while (image.getWidth() - cx >= yend) { int[][] imageBlock = new int[width][height]; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { imageBlock[i][j] = image.getRGB(cx + i, cy + j); } } result.add(new Block(imageBlock, width, height)); cx += width; } cy += height; } return result; } private static void drawGrid(BufferedImage image, int xs, int ys, int xend, int yend, int width, int height) { Graphics g = image.getGraphics(); g.setColor(Color.WHITE); for (int cx = xs; cx <= xend; cx += width) { for (int cy = ys; cy <= yend; cy += height) { g.drawLine(cx, cy, image.getWidth(), cy); g.drawLine(cx, cy, cx, image.getHeight()); } } } }