Skip to content

Instantly share code, notes, and snippets.

@Sunjammer
Last active March 22, 2021 03:34
Show Gist options
  • Save Sunjammer/cf71dd5f956b6a509bab to your computer and use it in GitHub Desktop.
Save Sunjammer/cf71dd5f956b6a509bab to your computer and use it in GitHub Desktop.
Naive bitmap to ascii converter
package;
/**
* Mostly stolen from http://www.codeproject.com/Articles/20435/Using-C-To-Generate-ASCII-Art-From-An-Image
* @author Andreas Rønning
*/
private typedef BMD = {
function getPixel(x:Int, y:Int):Int;
var width(default, never):Int;
var height(default, never):Int;
};
private typedef Vec3D = { x:Float, y:Float, z:Float };
class BitmapToAscii
{
static var grayVec:Vec3D = { x:0.2126, y:0.7152, z:0.0722 };
static inline var BLACK = "@";
static inline var CHARCOAL = "#";
static inline var DARKGRAY = "8";
static inline var MEDIUMGRAY = "&";
static inline var MEDIUM = "o";
static inline var GRAY = ":";
static inline var SLATEGRAY = "*";
static inline var LIGHTGRAY = ".";
static inline var WHITE = " ";
static inline var R = 1 / 255;
static inline function dot(a:Vec3D, b:Vec3D):Float {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
static inline function setFromHex(vec:Vec3D, color:Int) {
vec.x = (color >> 16) * R;
vec.y = (color >> 8 & 0xFF) * R;
vec.z = (color & 0xFF) * R;
}
static inline function desaturate(vec:Vec3D) {
var d = dot(grayVec, vec);
vec.x = vec.y = vec.z = d;
}
static function avgTile(bmd:BMD, ox:Int, oy:Int, width:Int, height:Int):Float {
var out = { x:0.0, y:0.0, z:0.0 };
var count = 0;
for (x in ox...ox + width) {
for (y in oy...oy + height) {
var c = bmd.getPixel(x, y);
out.x += c >> 16;
out.y += c >> 8 & 0xFF;
out.z += c & 0xFF;
count++;
}
}
var rec = 1 / count;
out.x = out.x * rec * R;
out.y = out.y * rec * R;
out.z = out.z * rec * R;
desaturate(out);
return out.x;
}
static inline function getGrayShade(value:Float):String
{
if (value >= .90) {
return WHITE;
}else if (value >= .78){
return LIGHTGRAY;
}else if (value >= .70){
return SLATEGRAY;
}else if (value >= .62){
return GRAY;
}else if (value >= .50){
return MEDIUM;
}else if (value >= .39){
return MEDIUMGRAY;
}else if (value >= .27){
return DARKGRAY;
}else if (value >= .19){
return CHARCOAL;
}else{
return BLACK;
}
}
public static function convert(bmp:BMD, strideX:Int = 8, strideY:Int = 16, invert:Bool = false, highQuality:Bool = true, linebreakchar:String = "\n"):String {
var temp:Vec3D = { x:0.0, y:0.0, z:0.0 };
var str = "";
var y = 0;
var v = 0.0;
while (y < bmp.height) {
var x = 0;
while (x < bmp.width) {
if (highQuality) {
v = avgTile(bmp, x, y, strideX, strideY);
}else {
setFromHex(temp, bmp.getPixel(x, y));
desaturate(temp);
v = temp.x;
}
if (invert) {
str += getGrayShade(1 - v);
}else {
str += getGrayShade(v);
}
x += strideX;
if (x >= bmp.width - 1) {
str += linebreakchar;
}
}
y += strideY;
}
return str;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment