Last active
December 25, 2018 18:12
-
-
Save larshb/bd4d48bb65443f499b5d3ce36b64bb1c to your computer and use it in GitHub Desktop.
Convert bitmap images to ASCII-art
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
from struct import * | |
class Pixel: | |
def __init__(self, byte): | |
self.r = byte[0] | |
self.g = byte[1] | |
self.b = byte[2] | |
def bytestr(self, x): | |
return "{0:0{1}X}".format(x,2) | |
def __repr__(self): | |
return "#" + self.bytestr(self.r) + \ | |
self.bytestr(self.g) + \ | |
self.bytestr(self.b) | |
def __str__(self): | |
return str([hex(self.r), hex(self.g), hex(self.b)]) | |
class Bitmap: | |
def __init__(self, filename): | |
try: | |
# Read file | |
raw = open(filename, "rb").read() | |
# Unpack header | |
ID, self.size, _, _, offset, DIB_size, \ | |
self.width, self.height, color_planes, bits_per_pixel, \ | |
pixel_array_compression, self.data_size, \ | |
print_res_h, print_res_w, \ | |
palette_colors, important_colors \ | |
= unpack("=HIHHIIIIHHIIIIII", raw[0:0x36]) | |
# Validate format | |
assert( ID == 0x4d42 \ | |
and offset == 54 \ | |
and DIB_size == 40 \ | |
and color_planes == 1 \ | |
and bits_per_pixel == 24 \ | |
and pixel_array_compression == 0 \ | |
and palette_colors == 0 \ | |
and important_colors == 0) | |
# Parse pixel data | |
self.lines = [] | |
raw_data = raw[offset:] | |
bytes_per_pixel = int(bits_per_pixel/8) | |
padding_bytes = self.width*bytes_per_pixel%4 | |
for l in range(self.height): | |
start = l*padding_bytes + l*self.width*bytes_per_pixel | |
stop = start+self.width*bytes_per_pixel | |
self.lines.append([Pixel(raw_data[x:x+bytes_per_pixel]) for x in range(start, stop, bytes_per_pixel)]); | |
self.lines[0][0].r = 0xa | |
except AssertionError: | |
print("Unsupported format!") | |
raise |
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
from bitmap import * | |
from subprocess import call | |
import sys | |
class Parameters: | |
def __init__(self): | |
try: | |
self.zoom = 4 | |
self.brightness = 0 | |
self.contrast = 1 | |
self.invert = 0 | |
self.open_after = 0 | |
assert(len(sys.argv)%2 == 0) | |
for i in range(2, len(sys.argv), 2): | |
arg = sys.argv[i] | |
a = arg[1] | |
print(a) | |
val = int(sys.argv[i+1]) | |
if arg[0] != '-' or len(arg) < 2: | |
raise Exception("Invalid argument: " + arg) | |
elif a == 'z': self.zoom = val | |
elif a == 'b': self.brightness = val | |
elif a == 'c': self.contrast = val | |
elif a == 'i': self.invert = val | |
elif a == 'o': self.open_after = val | |
else: | |
raise Exception("Invalid argument: " + arg) | |
except Exception as e: | |
print(e) | |
print() | |
print("Arg Description Default") | |
print("---+---------------------+-------") | |
print(" -b Brightness ", self.brightness) | |
print(" -c Contrast ", self.contrast) | |
print(" -i Invert ", self.invert) | |
print(" -z Zoom ", self.zoom) | |
print(" -o Open after convertion", self.open_after) | |
raise | |
open_output_file = 0 | |
try: | |
# Check input arguments | |
p = Parameters() | |
bmp = Bitmap(sys.argv[1]) | |
wzoom = int(p.zoom/3*2) | |
invert_factor = -1 if p.invert else 1 | |
symbols = ["X","Y","x","y","+","-",",","-"," "] | |
thresholds = [ 10, 10, 5, 10, 5, 10, 5, 5] | |
top = 200 | |
f = open("output.txt", "w") | |
for y in reversed(range(0, bmp.height-p.zoom, p.zoom)): | |
line = bmp.lines[y] | |
str = "" | |
for i in range(0, bmp.width-wzoom, wzoom): | |
v = 0 | |
s = " " | |
for j in range(wzoom): | |
v += line[i+j].r | |
vt = top | |
for k in range(len(thresholds)): | |
if v > wzoom*vt*p.contrast+wzoom*p.brightness: | |
s=symbols[invert_factor*k-p.invert] | |
break | |
vt-=thresholds[k] | |
str+=s | |
print(str) | |
f.write(str) | |
f.write("\n") | |
f.close() | |
if p.open_after == 1: | |
call("start output.txt", shell=True) | |
except FileNotFoundError: | |
print("Please enter a valid filename") | |
except: | |
print("\nUh oh, something is wrong") | |
#print(bmp.data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment