Skip to content

Instantly share code, notes, and snippets.

@huangxiangdan
Created July 4, 2012 02:13
Show Gist options
  • Save huangxiangdan/3044804 to your computer and use it in GitHub Desktop.
Save huangxiangdan/3044804 to your computer and use it in GitHub Desktop.
textify.js
/**
* @author Hakim El Hattab
*
* Recreates bitmap images using HTML text. Images are
* drawn onto a canvas element so that the pixels can
* be read. Letters, with colors matching the image pixels,
* are then placed at random locations on the screen.
*/
var Textify = function () {function w() {
b = new DAT.GUI({
width: 320
});
a = K(C.ABC);
a.redraw = function () {
x && y()
};
a.save = function () {
x && D()
};
a.image = function () {
p.click()
};
z = b.add(a, "preset").name("Preset").options("ABC", "Pointillism", "Mosaic", "Stitch", "@#%", "Bubbles", "StarStruck", "Pixelate", "Binary", "Snow", "Dash").onChange(function (g) {
z.removeOption(A);
g = C[g];
a.filter = g.filter;
a.backgroundColor = g.backgroundColor;
a.characterSet = g.characterSet;
a.characterLimit = g.characterLimit;
a.characterScale = g.characterScale;
a.characterFontFamily = g.characterFontFamily;
a.characterFontWeight = g.characterFontWeight;
b.listen()
});
b.add(a, "filter").name("Filter").options("None", "Black & White", "Sepia").listen().onChange(m);
b.add(a, "backgroundColor").name("Background").options({
"Dark Grey": "#333",
"Light Grey": "#888",
Black: "#000",
White: "#fff",
Red: "#c21a08",
Green: "#54ad3c",
Blue: "#6c94d2",
Transparent: "transparent",
"Source Image": "image"
}).listen().onChange(m);
b.add(a, "characterSet").name("Character Set").listen().onChange(m);
b.add(a, "characterLimit").name("Character Quantity").min(1E3).max(1E5).step(500).listen().onChange(m);
b.add(a, "characterScale").name("Font Scale").min(0.1).max(5).step(0.1).listen().onChange(m);
b.add(a, "characterFontFamily").name("Font Family").options({
Arial: "Arial",
"Comic Sans MS": "Comic Sans MS",
Helvetica: "Helvetica",
monospace: "monospace",
"Times New Roman": "Times New Roman"
}).listen().onChange(m);
guiFontWeight = b.add(a, "characterFontWeight").name("Font Weight").options("normal", "bold", "bolder").listen().onChange(m);
b.add(a, "useCanvas").name("Draw on Canvas (<strong>faster</strong>)").listen().onChange(m);
L === !1 && (b.add(a, "image").name("Browse for Image"), B = b.add(a, "save").name("Save Image"));
E = b.add(a, "redraw").name("Apply Settings");
E.domElement.className += " apply-button";
b.domElement.style.position = "absolute";
b.domElement.style.top = "0px";
b.domElement.style.right = "-20px";
document.querySelector(".guidat-controllers").style.height = "auto";
DAT.GUI.autoPlace = !1;
b.autoListen = !1
}function m() {
z.prependOption(A, !0);
a.preset = A
}function K(a) {
var l = {},
d;
for (d in a) l[d] = a[d];
return l
}function F() {
k.style.left = (window.innerWidth - j) * 0.5 + "px";
k.style.top = (window.innerHeight - i) * 0.5 + 16 + "px";
f.style.left = (window.innerWidth - f.width) * 0.5 + "px";
f.style.top = (window.innerHeight - f.height) * 0.5 + 16 + "px"
}function M() {
this.files.length && G(this.files[0])
}function N(a) {
a.stopPropagation();
a.preventDefault();
a = a.dataTransfer.files;
a.length && G(a[0])
}function G(a) {
var l = new FileReader;
l.onloadend = O;
l.readAsDataURL(a)
}function O(g) {
g.target.result.match(/^data:image/) ? (a.imageURL = P, c.src = g.target.result, setTimeout(y, 100)) : alert("Unexpected file format, dude.")
}function Q(a) {
c.onload = function () {
x = !0;
y()
};
c.onerror = function () {
alert("Failed to load image with URL " + c.src)
};
c.src = a
}function y() {
s = a.useCanvas;
if (a.backgroundColor === "transparent") document.querySelector("html").style.background = 'url("assets/images/transparent-pattern.png")';
else if (a.backgroundColor !== "image") document.querySelector("html").style.background = a.backgroundColor;
j = c.width;
i = c.height;
var g = window.innerWidth * 0.8,
l = window.innerHeight * 0.8,
d = 1;
if (j > g || i > l) d = Math.min(g / j, l / i), j = Math.floor(j * d), i = Math.floor(i * d);
k.innerHTML = "";
k.style.width = j + "px";
k.style.height = i + "px";
k.style.fontFamily = a.characterFontFamily;
k.style.fontWeight = a.characterFontWeight;
o = H * a.characterScale * 1.5;
h.restore();
h.clearRect(0, 0, f.width, f.height);
h.save();
f.width = j + o * 2;
f.height = i + o * 2;
if (s) if (a.backgroundColor === "image") h.save(), h.translate(o, o), h.scale(j / c.width, i / c.height), h.drawImage(c, 0, 0, c.width, c.height), h.restore();
else if (a.backgroundColor !== "transparent") h.fillStyle = a.backgroundColor, h.fillRect(0, 0, f.width, f.height);
h.translate(o, o);
u.width = j;
u.height = i;
q.save();
q.scale(d, d);
q.drawImage(c, 0, 0, c.width, c.height);
q.restore();
r = q.getImageData(0, 0, j, i).data;
I = r.length / 4;
t = [];
B && B.name(s ? "Save Image" : "View Source");
F();
J()
}function J() {
for (var g = a.backgroundColor === "transparent", l = 0; l < R; l++) {
var d = Math.floor(Math.random() * I),
b = d * 4,
c = Math.floor(d / j),
d = Math.round((d / j - c) * j),
f = Math.round(S + Math.random() * H) * a.characterScale,
i = a.characterSet[Math.floor(Math.random() * a.characterSet.length)],
e = {
r: r[b],
g: r[b + 1],
b: r[b + 2],
a: (0.3 + Math.random() * 0.7).toFixed(2)
},
b = r[b + 3] / 255;
if (g && b === 0) e.a = 0;
if (a.filter === "Black & White") e.r = e.g = e.b = Math.round((e.r + e.g + e.b) / 3);
else if (a.filter === "Sepia") e.r = e.g = e.b = Math.round((e.r + e.g + e.b) / 3), e.b = Math.round(e.b * 0.85);
s ? (d -= f / 2, c += f / 2, h.save(), h.font = a.characterFontWeight + " " + f + "px " + a.characterFontFamily, h.fillStyle = "rgba(" + e.r + "," + e.g + "," + e.b + ", " + e.a + ")", h.fillText(i, d, c), h.restore(), t.push(i)) : (d -= f / 2, c -= f / 2, b = document.createElement("p"), b.style.left = d + "px", b.style.top = c + "px", b.style.color = "rgba(" + e.r + "," + e.g + "," + e.b + ", " + e.a + ")", b.style.fontSize = f + "px", b.innerHTML = i, k.appendChild(b), t.push(b))
}
t.length < a.characterLimit ? (n.style.visibility = "visible", v.style.width = Math.min(t.length / a.characterLimit, 1) * n.offsetWidth + "px", requestAnimFrame(J)) : (n.style.visibility = "hidden", v.style.width = "0px")
}function D() {
if (s) {
var b = window.open("Textify Source", "height=400, width=700, toolbar=no, scrollbars=no, menubar=no");
b.document.write('<img src="' + f.toDataURL() + '"/>')
} else {
var b = window.open("", "Textify Source", "height=400, width=700, toolbar=no, scrollbars=no, menubar=no"),
c = b.document.createElement("textarea");
c.setAttribute("cols", "92");
c.setAttribute("rows", "27");
c.innerHTML += "<style>\n";
c.innerHTML += "\t.textify-output p {\n";
c.innerHTML += "\t\tposition: absolute;\n";
c.innerHTML += "\t}\n";
c.innerHTML += "</style>\n";
var d = b.document.createElement("div");
d.setAttribute("class", "textify-output");
d.style.fontFamily = a.characterFontFamily;
d.style.fontWeight = a.characterFontWeight;
d.innerHTML += k.innerHTML;
c.innerHTML += d.outerHTML;
b.document.write(c.outerHTML)
}
}
var R = 1E3,
T = ["image1.jpg", "image2.jpg", "image3.jpg", "image4.jpg", "image5.jpg"][Math.floor(Math.random() * 5)],
P = "(Drag and drop works too)",
A = "Custom",
S = 10,
H = 15,
C = {
ABC: {
preset: "ABC",
filter: "None",
useCanvas: !0,
characterSet: "ABC",
characterLimit: 13E3,
characterScale: 1.2,
characterFontFamily: "AppleGothic",
characterFontWeight: "bold",
backgroundColor: "#333"
},
Pointillism: {
preset: "Pointillism",
filter: "None",
useCanvas: !0,
characterSet: "\u2022",
characterLimit: 18E3,
characterScale: 2.5,
characterFontFamily: "Comic Sans MS",
characterFontWeight: "bold",
backgroundColor: "#333"
},
Mosaic: {
preset: "Mosaic",
filter: "None",
useCanvas: !0,
characterSet: "\u25b2\u25bc\u25c0\u25ba\u25c6",
characterLimit: 13E3,
characterScale: 1.5,
characterFontFamily: "Helvetica",
characterFontWeight: "normal",
backgroundColor: "#333"
},
Bubbles: {
preset: "Bubbles",
filter: "None",
useCanvas: !0,
characterSet: "oO\u25cc\u25ce",
characterLimit: 16E3,
characterScale: 1.5,
characterFontFamily: "Arial",
characterFontWeight: "normal",
backgroundColor: "#333"
},
"@#%": {
preset: "@#%",
filter: "None",
useCanvas: !0,
characterSet: "@#%",
characterLimit: 16E3,
characterScale: 1.5,
characterFontFamily: "monospace",
characterFontWeight: "normal",
backgroundColor: "#333"
},
Pixelate: {
preset: "Pixelate",
filter: "None",
useCanvas: !0,
characterSet: "\u25fc",
characterLimit: 12E3,
characterScale: 1.1,
characterFontFamily: "Arial",
characterFontWeight: "normal",
backgroundColor: "#333"
},
Binary: {
preset: "Binary",
filter: "None",
useCanvas: !0,
characterSet: "01",
characterLimit: 1E4,
characterScale: 1.5,
characterFontFamily: "Arial",
characterFontWeight: "normal",
backgroundColor: "#333"
},
StarStruck: {
preset: "StarStruck",
filter: "None",
useCanvas: !0,
characterSet: "\u2726\u2729\u272a\u272d",
characterLimit: 12E3,
characterScale: 2,
characterFontFamily: "Helvetica",
characterFontWeight: "normal",
backgroundColor: "#333"
},
Snow: {
preset: "Snow",
filter: "None",
useCanvas: !0,
characterSet: "\u2746\u2747\u274b",
characterLimit: 12E3,
characterScale: 2,
characterFontFamily: "Arial",
characterFontWeight: "normal",
backgroundColor: "#333"
},
Dash: {
preset: "Dash",
filter: "None",
useCanvas: !0,
characterSet: "/\\",
characterLimit: 17E3,
characterScale: 2,
characterFontFamily: "Arial",
characterFontWeight: "normal",
backgroundColor: "#333"
},
Stitch: {
preset: "Stitch",
filter: "None",
useCanvas: !0,
characterSet: "\u2716\u2715",
characterLimit: 9E3,
characterScale: 2,
characterFontFamily: "Helvetica",
characterFontWeight: "normal",
backgroundColor: "#333"
}
},
a = {},
b, z, B, E, n, v, p, u, q, k, f, h, o = 0,
c, r, I, t, j = 1,
i = 1,
x = !1,
s = !1;
navigator.userAgent.toLowerCase().match(/ipod/gi);
navigator.userAgent.toLowerCase().match(/ipad/gi);
navigator.userAgent.toLowerCase().match(/iphone/gi);
var L = !! navigator.userAgent.toLowerCase().match(/ipod|ipad|iphone/gi);
return {
initialize: function () {
c = document.createElement("img");
u = document.createElement("canvas");
q = u.getContext("2d");
f = document.createElement("canvas");
f.setAttribute("class", "textify-output-canvas");
h = f.getContext("2d");
k = document.createElement("div");
k.setAttribute("class", "textify-output-html");
n = document.createElement("div");
n.setAttribute("class", "textify-progress");
v = document.createElement("div");
n.appendChild(v);
progressText = document.createElement("p");
n.appendChild(progressText);
p = document.createElement("input");
p.setAttribute("type", "file");
p.style.visibility = "hidden";
document.body.appendChild(p);
document.body.appendChild(f);
document.body.appendChild(k);
document.body.appendChild(n);
window.addEventListener("resize", F, !1);
document.addEventListener("dragover", function (a) {
a.preventDefault()
}, !1);
document.addEventListener("dragenter", function (a) {
a.preventDefault()
}, !1);
document.addEventListener("dragexit", function (a) {
a.preventDefault()
}, !1);
document.addEventListener("drop", N, !1);
p.addEventListener("change", M, !1);
w();
Q(T)
},
viewSource: D
}
}();
window.requestAnimFrame = function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (w) {
window.setTimeout(w, 1E3 / 60)
}
}();
Textify.initialize();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment