Last active
August 20, 2016 00:47
-
-
Save tako2/981ba0b09a119908fc0442d84acfb250 to your computer and use it in GitHub Desktop.
Convert Image to Arduboy Bitmap
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
#!/usr/bin/env python | |
# coding: UTF-8 | |
from PIL import Image, ImageEnhance | |
import Tkinter | |
from ScrolledText import * | |
############################################################################### | |
def draw_bitmap(canvas, rgb, max_xy, bmp_xy, start_xy, mask): | |
max_x = max_xy[0] | |
max_y = max_xy[1] | |
for y in range(max_y): | |
for x in range(max_x): | |
r,g,b,a = rgb.getpixel((x, y)) | |
ofs_x = 4 * x + start_xy[0] | |
ofs_y = 4 * y + start_xy[1] | |
if mask: | |
if r == 0 and g == 0 and b == 0: | |
if a == 0: | |
canvas.create_rectangle(ofs_x, ofs_y, | |
(ofs_x + 3), (ofs_y + 3), | |
fill='black') | |
else: | |
canvas.create_rectangle(ofs_x, ofs_y, | |
(ofs_x + 3), (ofs_y + 3), | |
fill='white') | |
else: | |
canvas.create_rectangle(ofs_x, ofs_y, | |
(ofs_x + 3), (ofs_y + 3), | |
fill='black') | |
else: | |
if r == 0 and g == 0 and b == 0: | |
canvas.create_rectangle(ofs_x, ofs_y, | |
(ofs_x + 3), (ofs_y + 3), | |
fill='black') | |
else: | |
canvas.create_rectangle(ofs_x, ofs_y, | |
(ofs_x + 3), (ofs_y + 3), | |
fill='white') | |
for y in range(0, max_y+1, bmp_xy[1]): | |
canvas.create_line(start_xy[0], y * 4 + start_xy[1], | |
max_x * 4 + start_xy[0], y * 4 + start_xy[1], | |
fill='blue', width=2) | |
for x in range(0, max_x+1, bmp_xy[0]): | |
canvas.create_line(x * 4 + start_xy[0], start_xy[1], | |
x * 4 + start_xy[0], max_y * 4 + start_xy[1], | |
fill='blue', width=2) | |
############################################################################### | |
def show_bitmap(title, rgb, max_xy, bmp_xy, bitmaps, mask=False): | |
root = Tkinter.Tk() | |
root.title(title) | |
root.geometry('640x480') | |
max_x = max_xy[0] | |
max_y = max_xy[1] | |
# | |
# make image | |
# | |
canvas = Tkinter.Canvas(root, width=4*128, height=4*64 * 2) | |
draw_bitmap(canvas, rgb, max_xy, bmp_xy, (4, 4), False) | |
if mask: | |
draw_bitmap(canvas, rgb, max_xy, bmp_xy, (4, max_y * 4 + 4), True) | |
canvas.place(x=0,y=0) | |
lcd_text = '' | |
for bmp in bitmaps: | |
for data in bmp: | |
lcd_text += '0x%02x,' % data | |
lcd_text += '\n' | |
text_box = ScrolledText(width=84, height=8, bd=4) | |
text_box.insert('end', lcd_text) | |
text_box.place(x=0,y=280) | |
def copy(event): | |
root.clipboard_clear() | |
root.clipboard_append(lcd_text) | |
btn_copy = Tkinter.Button(text='Copy') | |
btn_copy.bind('<Button-1>', copy) | |
btn_copy.place(x=20,y=440) | |
def done(event): | |
root.quit() | |
btn_done = Tkinter.Button(text='Done') | |
btn_done.bind('<Button-1>', done) | |
btn_done.place(x=100,y=440) | |
root.mainloop() | |
############################################################################### | |
def img2bmp(rgb, bmp_xy, ofs_xy, mask=False): | |
bmp = [] | |
for y in range(ofs_xy[1], ofs_xy[1] + bmp_xy[1], 8): | |
for x in range(ofs_xy[0], ofs_xy[0] + bmp_xy[0]): | |
data = 0 | |
for bit in range(y, y+8): | |
r,g,b,a = rgb.getpixel((x, bit)) | |
data >>= 1 | |
if mask: | |
if r == 0 and g == 0 and b == 0: | |
if a == 0: | |
data |= 0x00 | |
else: | |
data |= 0x80 | |
else: | |
data |= 0x00 | |
else: | |
if r == 0 and g == 0 and b == 0: | |
data |= 0x00 | |
else: | |
data |= 0x80 | |
bmp.append(data) | |
return bmp | |
############################################################################### | |
def trans_images(rgb, max_xy, bmp_xy, mask=False): | |
bitmaps = [] | |
for ofs_y in range(0, max_xy[1], bmp_xy[1]): | |
for ofs_x in range(0, max_xy[0], bmp_xy[0]): | |
bmp = img2bmp(rgb, bmp_xy, (ofs_x, ofs_y)) | |
if bmp is not None: | |
bitmaps.append(bmp) | |
if mask: | |
bmp = img2bmp(rgb, bmp_xy, (ofs_x, ofs_y), mask) | |
if bmp is not None: | |
bitmaps.append(bmp) | |
return bitmaps | |
############################################################################### | |
from optparse import OptionParser | |
import sys | |
import os.path | |
if __name__ == '__main__': | |
parser = OptionParser('usage: %prog (options) [Image File]') | |
parser.add_option('-v', '--verbose', | |
action='store_true', dest='verbose', default=False, | |
help='verbose mode') | |
parser.add_option('-x', '--width', | |
type='int', dest='bmp_w', default=0, metavar='WIDTH', | |
help='devide image to bitmap with WIDTH') | |
parser.add_option('-y', '--height', | |
type='int', dest='bmp_h', default=0, metavar='HEIGHT', | |
help='devide image to bitmap with HEIGHT') | |
parser.add_option('-f', '--fit', | |
action='store_true', dest='fit', default=False, | |
help='fit image size to (128x64)') | |
parser.add_option('-d', '--dither', | |
action='store_true', dest='dither', default=False, | |
help='use dither') | |
parser.add_option('-g', '--gui', | |
action='store_true', dest='gui', default=False, | |
help='show GUI') | |
parser.add_option('-2', '--two-dimension', | |
action='store_true', dest='two', default=False, | |
help='output two-dimensional array') | |
parser.add_option('-b', '--black', | |
action='store_true', dest='mask', default=False, | |
help='make black layer bitmap') | |
(options, args) = parser.parse_args() | |
if (len(args) < 1): | |
parser.error('need [Image File]') | |
quit() | |
# ---------------------------------------------------------- Load Image --- | |
im = Image.open(args[0]) | |
filename = os.path.basename(im.filename) | |
if options.fit: | |
im.thumbnail((128, im.size[1] / (im.size[0] / 128)), Image.ANTIALIAS) | |
if options.dither: | |
eim = ImageEnhance.Brightness(im) | |
rgb = eim.enhance(0.8).convert('1').convert('RGBA') | |
else: | |
rgb = im.convert('RGBA') | |
# ------------------------------------------------------------ Get Size --- | |
size = rgb.size | |
img_x = size[0] | |
img_y = size[1] | |
if (img_y % 8) != 0: | |
img_y -= (img_y % 8) | |
if img_x > 128: | |
img_x = 128 | |
if img_y > 64: | |
img_y = 64 | |
bmp_w = options.bmp_w | |
if bmp_w == 0: | |
bmp_w = img_x | |
bmp_h = options.bmp_h | |
if bmp_h == 0: | |
bmp_h = img_y | |
num_bmps = (img_x / bmp_w) * (img_y / bmp_h) | |
bitmaps = trans_images(rgb, (img_x, img_y), (bmp_w, bmp_h), options.mask) | |
# ------------------------------------------- Show Bitmap Data with GUI --- | |
if options.gui: | |
show_bitmap(filename, rgb, (img_x, img_y), (bmp_w, bmp_h), bitmaps, | |
options.mask) | |
# ------------------------------------------------------- Output Result --- | |
print '// %d bitmap(s) in this byte array' % num_bmps | |
print '// each bitmap size is (%d x %d)' % (bmp_w, bmp_h) | |
if options.two: | |
print 'PROGMEM const uint8_t %s_bmp[][%d] = {' % (filename.split('.')[0], bmp_w * bmp_h / 8) | |
else: | |
print 'PROGMEM const uint8_t %s_bmp[] = {' % filename.split('.')[0] | |
lcd_text = '' | |
for bmp in bitmaps: | |
lcd_text += ' ' | |
if options.two: | |
lcd_text += '{\n ' | |
for data in bmp: | |
lcd_text += '0x%02x,' % data | |
if options.two: | |
lcd_text += '\n },' | |
lcd_text += '\n' | |
print lcd_text, | |
print '};' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment