daily pastebin goal
70%
SHARE
TWEET

Generating Images from RegEx

a guest Mar 24th, 2014 312 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package com.ignatieff.rei;
  2.  
  3. import java.awt.Color;
  4. import java.awt.Graphics;
  5. import java.awt.Point;
  6. import java.awt.image.BufferedImage;
  7.  
  8. import java.io.File;
  9. import java.io.IOException;
  10.  
  11. import java.util.HashMap;
  12. import java.util.Map;
  13. import java.util.regex.Pattern;
  14.  
  15. import javax.imageio.ImageIO;
  16.  
  17. public class Generator {
  18.        
  19.         public static String TRIANGLE_FRACTAL = "(1+2+3)*0(1+3)*0(0+1+2+3)*";
  20.        
  21.         private int resolution, size;
  22.        
  23.         private Color WHITE = Color.white, BLACK = Color.black;
  24.        
  25.         /**
  26.          * Creates a new generator with as a high a resolution as possible.
  27.          * @param size The width / height of the image to create. This variable must be a power of 2.
  28.          */
  29.         public Generator(int size){
  30.                 this((int)log2(size), size);
  31.         }
  32.        
  33.         /**
  34.          * Creates new generator, for creating images based on regular expresions.
  35.          * Keep in mind that the size needs to be a power of 2, for this to work properly.
  36.          * If 'size' is not a power of 2, it'll be converted to the closest power of 2 relative to 'size.
  37.          *
  38.          * Also note that 'resolution' cannot exceed log2(size). If 'resolution' is higher than log2(size) it'll be changed to log2(size).
  39.          *
  40.          * @param resolution The resolution of the images to create. Higher resolution results in better image quality, but longer render time.
  41.          * @param size The width / height of the image to create. This variable must be a power of 2.
  42.          */
  43.         public Generator(int resolution, int size){
  44.  
  45.                 this.resolution = resolution;
  46.                 this.size = size;
  47.        
  48.                 if(!isPow2(size)){
  49.                         this.size = (int)Math.pow(2, Math.round(log2(size)));
  50.                         System.out.println("Error: size is not a power of 2, changing size to '"+this.size+"'.");
  51.                 }
  52.                
  53.                 if(Math.pow(2,resolution)>size){
  54.                         this.resolution = (int)log2(this.size);
  55.                         System.out.println("Error: resolution too large, changing resolution to '"+this.resolution+"'.");
  56.                 }
  57.         }
  58.        
  59.         private static char[] regExps = "!$%^&*_+|~-=`(){}[]:\";'<>?,./".toCharArray();
  60.         private static char[] valids = "!$%^&*_+|~-=`(){}[]:\";'<>?,./0123".toCharArray();
  61.        
  62.         /**
  63.          * Checks whether or not a character is a regular expression-symbol or a character.
  64.          * @param c The character to check.
  65.          * @return True, if it's a regular expression symbol, false if it's a character.
  66.          */
  67.         private static boolean isRegExp(char c){
  68.                 for(char k : regExps){
  69.                         if(k==c)return true;
  70.                 }
  71.                 return false;
  72.         }
  73.        
  74.         /**
  75.          * Will evaluate whether a regular expression is valid for this generator or not.
  76.          * @param regex The regex to evaluate.
  77.          * @return True, it it's valid. False, if it's invalid.
  78.          */
  79.         private static boolean isValid(String regex){
  80.                 char[] chars = regex.toCharArray();
  81.                 for(char c : chars){
  82.                         boolean valid = false;
  83.                         for(char k : valids){
  84.                                 if(k==c){
  85.                                         valid=true;
  86.                                         break;
  87.                                 }
  88.                         }
  89.                         if(!valid)return false;
  90.                 }
  91.                 return true;
  92.         }
  93.        
  94.         /*public static String getRegexFromImage(BufferedImage img){
  95.                
  96.         }*/
  97.        
  98.         /**
  99.          * Will clean an arbitrary regular expression, making it available to use for generating images,
  100.          * even though it was created for a different purpose.
  101.          *
  102.          * It works by mapping all the non-regular expression symbols (+, [, ], *) unto the characters 0, 1, 2, 3.
  103.          * @param regex The regular expression to clean.
  104.          * @return A cleaned regular expression.
  105.          */
  106.         private static String cleanRegEx(String regex){
  107.                
  108.                 if(isValid(regex))return regex;
  109.                
  110.                 int i = 0;
  111.                 Map<Character, Integer> map = new HashMap<Character, Integer>();
  112.                
  113.                 char[] regs = regex.toCharArray();
  114.                 char[] clean = new char[regs.length];
  115.                
  116.                 for(char c : regs){
  117.                         if(map.containsKey(c))continue;
  118.                         if(isRegExp(c))continue;
  119.                         map.put(c, i);
  120.                         i = (i + 1) % 4;
  121.                 }
  122.                
  123.                 for(int j=0; j<regs.length; j++){
  124.                         if(map.containsKey(regs[j])){
  125.                                 clean[j] = Integer.toString(map.get(regs[j])).charAt(0);
  126.                                 continue;
  127.                         }
  128.                         clean[j] = regs[j];
  129.                 }
  130.                 System.out.println(new String(clean));
  131.                 return new String(clean);
  132.         }
  133.        
  134.         /**
  135.          * Returns log2 of a double. Uses the identity log_b(x) = ln(x)/ln(b)
  136.          * @param d The double to get the log2 of.
  137.          * @return log2(d)
  138.          */
  139.         private static double log2(double d){
  140.                 return Math.log(d)/Math.log(2);
  141.         }
  142.        
  143.         /**
  144.          * Checks whether an integer is a power of 2.
  145.          * @param k The integer to perform the check on
  146.          * @return True if the integer is a power of 2, false otherwise.
  147.          */
  148.         private static boolean isPow2(int k){
  149.                 return (Math.pow(2, Math.floor(log2(k))) == k);
  150.         }
  151.        
  152.         /**
  153.          * Will change all (,{,< to [ and all ),},> to ] because Java thinks they are characters, not symbols.
  154.          * @param s
  155.          * @return
  156.          */
  157.         private static String removeParentheses(String s){
  158.                 return s.replace("(", "[")
  159.                                 .replace(")", "]")
  160.                                 .replace("{", "[")
  161.                                 .replace("}", "]")
  162.                                 .replace("<", "[")
  163.                                 .replace(">", "]");
  164.         }              
  165.        
  166.         /**
  167.          * Generate an image from a regular expressions and save it to the file system.
  168.          * @param regex The regular expression to use for generating the image.
  169.          * @param path The relative path to save the image to.
  170.          */
  171.         public void generateAndExport(String regex, String path){
  172.                 try {
  173.                         BufferedImage img = generate(regex);
  174.                         ImageIO.write(img, "png", new File(path));
  175.                 } catch (IOException e) {
  176.                         e.printStackTrace();
  177.                 }
  178.         }
  179.        
  180.         /**
  181.          * Generate an image from a regular expression and return it as a BufferedImage.
  182.          * @param regex The regular expression to use for generating the image.
  183.          * @return The image generated as a BufferedImage.
  184.          */
  185.         public BufferedImage generate(String regex){
  186.                 return generate(
  187.                                 Pattern.compile(
  188.                                                 cleanRegEx(
  189.                                                                 removeParentheses(regex))));
  190.         }
  191.        
  192.         /**
  193.          * Generate an image from a regular expression and return it as a BufferedImage.
  194.          * @param p The regular expression as a 'Pattern' to use for generating the image.
  195.          * If you're confused, just parse a string instead, it'll be handled anyway.
  196.          * @return The image generated as a BufferedImage.
  197.          */
  198.         public BufferedImage generate(Pattern p){
  199.                 BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
  200.                 Graphics g = img.createGraphics();
  201.                
  202.                 g.setColor(WHITE);
  203.                 g.fillRect(0, 0, size, size);
  204.                 g.setColor(BLACK);
  205.                
  206.                 int pointSize = (int) ((int) size/Math.pow(2, resolution));
  207.                
  208.                 String[] s = getAllStrings();
  209.                
  210.                 for(String q : s){
  211.                        
  212.                         if(!p.matcher(q).matches())continue;
  213.                
  214.                         Point x = stringToPoint(q, size);
  215.                         g.fillRect(x.x, x.y, pointSize, pointSize);
  216.                 }
  217.                
  218.                 return img;
  219.         }
  220.        
  221.         /**
  222.          * Pads a string with 0's to ensure that all strings are of equal length.
  223.          * @param s The string to pad.
  224.          * @param length The length the string must match.
  225.          * @return A padded version of 's' with length 'length'.
  226.          */
  227.         private String pad(String s, int length){
  228.                 StringBuilder sb = new StringBuilder();
  229.                 int dx = length - s.length();
  230.                 for(int i=0; i<dx; i++){
  231.                         sb.append("0");
  232.                 }
  233.                 sb.append(s);
  234.                 return sb.toString();
  235.         }
  236.        
  237.         /**
  238.          * Gets all strings of length 'size'. Depends on the generator.
  239.          * @return All strings of length 'size'.
  240.          */
  241.         private String[] getAllStrings(){
  242.                 int max = (int) Math.pow(4, resolution);
  243.                 String[] strings = new String[max];
  244.                 for(int i=0; i<max; i++){
  245.                         strings[i] = pad(Integer.toString(i, 4), resolution);
  246.                 }
  247.                 return strings;
  248.         }
  249.        
  250.         /**
  251.          * Gets the relative position of a character, only matches 0, 1, 2, 3.
  252.          *
  253.          * It uses the placement
  254.          *
  255.          * 1 2
  256.          * 0 3
  257.          *
  258.          * @param c The character to get the relative position of.
  259.          * @param size The width / height of the virtual frame.
  260.          * @return A point, representing the virtual position of the character. Will return null if the character isn't valid (0,1,2,3).
  261.          */
  262.         private static Point charToPoint(char c, int size){
  263.                
  264.                 int x = size/2;
  265.                
  266.                 switch(c){
  267.                         case '0':
  268.                                 return new Point(0, x);
  269.                         case '1':
  270.                                 return new Point(0, 0);
  271.                         case '2':
  272.                                 return new Point(x, 0);
  273.                         case '3':
  274.                                 return new Point(x, x);
  275.                 }
  276.                
  277.                 return null;
  278.         }
  279.        
  280.         /**
  281.          * Recursive function for finding the position (x,y) of a string.
  282.          * @param s The string to get the position of.
  283.          * @param size The width / height of the frame.
  284.          * @return A point representing the position of the string.
  285.          */
  286.         private static Point stringToPoint(String s, int size){
  287.                 if(s.length() == 1){
  288.                         return charToPoint(s.charAt(0), size);
  289.                 }
  290.                
  291.                 Point p = charToPoint(s.charAt(0), size);
  292.                 Point q = stringToPoint(s.substring(1), size/2);
  293.                
  294.                 return new Point(p.x + q.x, p.y + q.y);
  295.         }
  296.        
  297.         private static double decreaseAmount = 0.75;
  298.         private static double[] probs = {0.333, 0.333, 0.333};
  299.        
  300.         /**
  301.          * Generate a random regular expression.
  302.          * @param x The 'length' of the expression.
  303.          * @return A random regular expression.
  304.          */
  305.         public static String randomRegExp(double x){
  306.                 double newX = x * decreaseAmount;
  307.                 double s = Math.random();
  308.                
  309.                 if(s <= probs[0]*x){
  310.                         return randomRegExp(newX) + "+" + randomRegExp(newX);
  311.                 }
  312.                 s-= probs[0]*x;
  313.                
  314.                 if(s <= probs[1]*x){
  315.                         return "[" + randomRegExp(newX) + "][" + randomRegExp(newX) + "]";
  316.                 }
  317.                 s-= probs[1]*x;
  318.                
  319.                 if(s <= probs[2]*x){
  320.                         return "[" + randomRegExp(newX) + "]*";
  321.                 }
  322.                
  323.                 return Integer.toString((int)Math.floor(4*Math.random()));
  324.                
  325.         }
  326. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top