Last active
October 11, 2015 19:00
-
-
Save timyates/7234c83d9e7df39e5a09 to your computer and use it in GitHub Desktop.
First pass at a Groovy clone of ASCIImage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.bloidonia.asciiimage | |
import java.awt.* | |
import java.awt.geom.* | |
import java.awt.image.BufferedImage | |
import java.util.List | |
class AsciImage { | |
static enum Type { POINT, PATH, LINE, ELLIPSE } | |
static class Element { | |
Type type | |
List<Point2D> points | |
} | |
final List<String> TOKENS = ['1'..'9', 'A'..'Z', 'a'..'n', 'p'..'z'].flatten() as List<String> | |
private parse(String lines) { | |
parse(lines.split(/\n/).findAll { it.trim().length() != 0 }) | |
} | |
private List<Element> generate(Map<String,List<Point2D>> marks) { | |
[null, *TOKENS, null].collate(3, 1, false) | |
.collect { a, b, c -> [ previous:a, current:b, next:c ] } | |
.inject([]) { elements, pcn -> | |
if(marks[pcn.current]) { | |
if (marks[pcn.previous]) { | |
elements[-1].type = Type.PATH | |
elements[-1].points.addAll(marks[pcn.current]) | |
} | |
else { | |
elements << new Element(points:marks[pcn.current], type: marks[pcn.current].size() == 1 ? Type.POINT : marks[pcn.current].size() == 2 ? Type.LINE : Type.ELLIPSE) | |
} | |
} | |
elements | |
} | |
} | |
private List<Element> parse(List<String> lines) { | |
if(lines == null) throw new RuntimeException("Lines cannot be null") | |
if(lines.size() == 0) throw new RuntimeException("Lines cannot be empty") | |
if(lines*.length().unique().size() != 1) throw new RuntimeException("Lines cannot be of different lengths") | |
lines = lines.collect { it.replaceAll(/\s+/, '') } | |
int rows = lines.size() | |
int columns = lines[0].length() | |
List<Integer> rowIdx = 0..<rows | |
def tokenMap = [:].withDefault {[]} | |
def tokens = [rowIdx,lines].transpose().inject(tokenMap) { marks, idxStrArr -> | |
idxStrArr[1].toList() | |
.eachWithIndex { entry, idx -> | |
if(TOKENS.contains(entry)) | |
marks[entry] << new Point2D.Double(idx / (columns - 1), idxStrArr[0] / (lines.size() - 1)) | |
} | |
marks | |
} | |
generate(tokens) | |
} | |
private generateBufferedImage(String lines, int width, int height) { | |
generateBufferedImage(lines.split(/\n/).findAll { it.trim().length() != 0 }, width, height) | |
} | |
private generateBufferedImage(List<String> lines, int width, int height) { | |
new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB).with { img -> | |
createGraphics().with {g -> | |
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON) | |
color = Color.WHITE | |
parse(lines).collect { element -> | |
if(element.type == Type.LINE) { | |
new Line2D.Double(element.points[0].x * width, element.points[0].y * height, element.points[1].x * width, element.points[0].y * height) | |
} | |
else if(element.type == Type.POINT) { | |
new Rectangle2D.Double(element.points[0].x * width - 0.5, element.points[0].y * height - 0.5, 0.5, 0.5) | |
} | |
else if(element.type == Type.PATH) { | |
new GeneralPath(GeneralPath.WIND_EVEN_ODD, element.points.size()).with { path -> | |
path.moveTo(element.points[0].x * width, element.points[0].y * height) | |
element.points.drop(1).each { Point2D pts -> | |
path.lineTo(pts.x * width, pts.y * height) | |
} | |
path.lineTo(element.points[0].x * width, element.points[0].y * height) | |
path | |
} | |
} | |
else if(element.type == Type.ELLIPSE) { | |
new Ellipse2D.Double(element.points.x.min() * width, | |
element.points.y.min() * height, | |
(element.points.x.max() - element.points.x.min()) * width, | |
(element.points.y.max() - element.points.y.min()) * height) | |
} | |
else { | |
throw new RuntimeException("Unknown type $element.type") | |
} | |
}.each { s -> | |
g.draw(s) | |
g.fill(s) | |
} | |
dispose() | |
} | |
img | |
} | |
} | |
} | |
new AsciImage().generateBufferedImage(''' | |
· · · · · · · · · · · · | |
· A · · · · · · · · A · | |
· · · · · · · · · · · · | |
· · · · · · 1 · · · · · | |
· · · · · · o o · · · · | |
· · · 6 o o 7 o o · · · | |
· · · o o o o o o 2 · · | |
· · · 5 o o 4 o o · · · | |
· · · · · · o o · · · · | |
· · · · · · 3 · · · · · | |
· · · · · · · F · · F · | |
· C · · · · · F · · F · | |
· · · · · · · · · · · · | |
''', 100, 100) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Idea stolen quite blatantly from here