replace manual image manipulation with our own new clj-image2ascii lib

This commit is contained in:
Gered 2014-04-03 21:32:49 -04:00
parent 7c29069559
commit aae01476a0
6 changed files with 19 additions and 1349 deletions

View file

@ -13,6 +13,7 @@
[environ "0.4.0"]
[clj-metasearch "0.1.1"]
[clj-figlet "0.1.1"]
[clj-image2ascii "0.1.0-SNAPSHOT"]
[com.cemerick/url "0.1.1"]
[criterium "0.4.3" :scope "test"]]
:source-paths ["src/clojure"]

View file

@ -1,57 +1,19 @@
(ns toascii.models.image
(:import (java.awt RenderingHints Graphics2D Image)
(java.awt.image BufferedImage Raster)
(javax.imageio ImageIO)
(java.io File)
(java.net URL)
(toascii.images ImageToAscii))
(:require [clojure.string :as str]
[cemerick.url :as url]
[toascii.util :refer [query-param-url->java-url]])
(:import (java.awt.image BufferedImage))
(:require [toascii.util :refer [query-param-url->java-url]]
[clj-image2ascii.core :as i2a])
(:use hiccup.core))
(defn get-image-by-url
(^BufferedImage [^String url]
(try
(let [java-url (query-param-url->java-url url)]
(ImageIO/read java-url))
(catch Exception ex))))
(defn get-image-by-file
"returns a BufferedImage loaded from the file specified, or null if an error occurs."
(^BufferedImage [^File file]
(try
(ImageIO/read file)
(catch Exception ex))))
(defn scale-image
"takes a source image specified by the uri (a filename or a URL) and scales it proportionally
using the new width, returning the newly scaled image."
(^BufferedImage [^BufferedImage image new-width]
(let [new-height (* (/ new-width (.getWidth image))
(.getHeight image))
scaled-image (BufferedImage. new-width new-height BufferedImage/TYPE_INT_RGB)
gfx2d (doto (.createGraphics scaled-image)
(.setRenderingHint RenderingHints/KEY_INTERPOLATION
RenderingHints/VALUE_INTERPOLATION_BILINEAR)
(.drawImage image 0 0 new-width new-height nil)
(.dispose))]
scaled-image)))
(defn convert-image
"converts the image to an ascii representation. a multiline string will be returned,
which will be formatted for html if color? is true, or plain text if false. if
scale-to-width is specified the resulting image will be scaled proportionally from
the source image."
([^BufferedImage image color?]
(convert-image image nil color?))
([^BufferedImage image scale-to-width color?]
(let [current-width (.getWidth image)
new-width (or scale-to-width current-width)
final-image (if-not (= new-width current-width)
(scale-image image new-width)
image)]
(ImageToAscii/convert final-image color?))))
(defn get-image [^String url]
(let [java-url (query-param-url->java-url url)]
(i2a/get-image-by-url java-url)))
(defn wrap-pre-tag [s]
(str "<pre style=\"font-size:6pt; letter-spacing:1px; line-height:5pt; font-weight:bold;\">" s "</pre>"))
(str "<pre style=\"font-size:6pt; letter-spacing:1px; line-height:5pt; font-weight:bold;\">" s "</pre>"))
(defn image->ascii [^BufferedImage image scale-to-width color? html?]
(let [converted (i2a/convert-image image scale-to-width color?)
ascii (:image converted)]
(if html?
(wrap-pre-tag ascii)
ascii)))

View file

@ -4,7 +4,7 @@
[liberator.core :refer [defresource]]
[compojure.core :refer [ANY]]
[toascii.route-utils :refer [register-routes]]
[toascii.models.image :refer [convert-image get-image-by-url wrap-pre-tag]]
[toascii.models.image :refer [image->ascii get-image]]
[toascii.util :refer [parse-int parse-boolean]]))
(defresource render-image [{:keys [url width color format] :as params}]
@ -26,21 +26,15 @@
(parse-boolean color)) {:error "Cannot output colored plain text version of image."}))
:exists?
(fn [_]
(if-let [image (get-image-by-url url)]
(if-let [image (get-image url)]
{:image image}
[false {:error "Image could not be loaded."}]))
:handle-ok
(fn [ctx]
(let [html? (= "text/html" (get-in ctx [:representation :media-type]))
color? (or (and html? (nil? color))
(parse-boolean color))
output (convert-image
(:image ctx)
(parse-int width)
color?)]
(if html?
(wrap-pre-tag output)
output)))
(parse-boolean color))]
(image->ascii (:image ctx) (parse-int width) color? html?)))
:handle-malformed
(fn [ctx]
(:error ctx))

View file

@ -1,83 +0,0 @@
package toascii.images;
import java.awt.image.BufferedImage;
public class ImageToAscii {
static final char[] asciiChars = {'#', 'A', '@', '%', '$', '+', '=', '*', ':', ',', '.', ' '};
static final int numAsciiChars = asciiChars.length - 1;
static final int spanLength = "<span style=\"color:#112233;\">X</span>".length();
static final int lineTerminatorLength = "<br>".length();
// copied from java.lang.Integer.digits (which is private so we can't just reference it, boourns)
static final char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};
// modification of java.lang.Integer.toUnsignedString -- no garbage generated, but limited to max value
// of 255 ...hence the 'unsigned byte' thing :)
private static void unsignedByteToHex(int unsignedByte, StringBuilder sb) {
for (int i = 0; i < 2; ++i) {
int index = sb.length + 1 - i;
if (unsignedByte != 0) {
sb.chars[index] = digits[unsignedByte & 15];
unsignedByte >>>= 4;
} else
sb.chars[index] = '0';
}
sb.length += 2;
}
public static String convert(BufferedImage image, boolean useColor) {
final int width = image.getWidth();
final int height = image.getHeight();
final int maxLength = (useColor ?
(width * height * spanLength) + (height * lineTerminatorLength) :
(width * height) + height);
final StringBuilder sb = new StringBuilder(maxLength);
final int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
final int argb = pixels[(y * width) + x];
final int r = (0x00ff0000 & argb) >> 16;
final int g = (0x0000ff00 & argb) >> 8;
final int b = (0x000000ff & argb);
final double brightness = Math.sqrt((r * r * 0.241f) +
(g * g * 0.691f) +
(b * b * 0.068f));
int charIndex;
if (brightness == 0.0f)
charIndex = numAsciiChars;
else
charIndex = (int)((brightness / 255.0f) * numAsciiChars);
final char pixelChar = asciiChars[charIndex > 0 ? charIndex : 0];
if (useColor) {
sb.append("<span style=\"color:#");
unsignedByteToHex(r, sb);
unsignedByteToHex(g, sb);
unsignedByteToHex(b, sb);
sb.append(";\">");
sb.append(pixelChar);
sb.append("</span>");
} else
sb.append(pixelChar);
}
if (useColor)
sb.append("<br>");
else
sb.append('\n');
}
return sb.toString();
}
}

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB