Конвертер монохромных BMP файлов в формат файлов MKL
Программа "Китайский год" стимулировала меня посидеть пару вечеров с интернет-планшеткой.
В результате получился скрипт на языке Python (v2.7), преобразующий монохромный BMP файл в некое подобие исходного текста программы формата MKL программируемых калькуляторов МК-152/161.
#
# BMP to MKL converter.
# Version 1.0
#
#coding=ascii
import array
import sys
#When 1, extra dumps to console
debug_dump = 0
#1 - invert pixels
invert_pixel = 1
file_to_open = sys.argv[1]
file_to_write = file_to_open + ".txt"
print "--------------------------"
print "File to open: ", file_to_open
print "File to write: ", file_to_write
img_file = open(file_to_open,"rb")
values = array.array('B') #Array of unsigned char type
values.read(img_file, 60)
img_file.close()
s_of = 0x02 #Start of data size
d_of = 0x0A #Start of data offset
dib_of = 0x0E #Start of DIB header size
w_of = 0x12 #Width of BMP
h_of = 0x16 #Height of BMP
ncp_of = 0x1A #Number of color planes
nbpp_of = 0x1C #Number of bits per pixel
cmpr_of = 0x1E #Type of compression
is_of = 0x22 #Raw bitmap data size
num_col_pal_of = 0x2E #Number of colors in the palette
imp_col_of = 0x32 #Number of important colors used
color_tbl_of = 0x36 #Color table = 4 * colors_palette bytes. Present only if num_bpp <= 8
bmp_size = values[s_of]|(values[s_of+1]<<8)|(values[s_of+2]<<16)|(values[s_of+3]<<24)
data_start = values[d_of]|(values[d_of+1]<<8)|(values[d_of+2]<<16)|(values[d_of+3]<<24)
dib_size = values[dib_of]|(values[dib_of+1]<<8)|(values[dib_of+2]<<16)|(values[dib_of+3]<<24)
bmp_width = values[w_of]|(values[w_of+1]<<8)|(values[w_of+2]<<16)|(values[w_of+3]<<24)
bmp_height = values[h_of]|(values[h_of+1]<<8)|(values[h_of+2]<<16)|(values[h_of+3]<<24)
num_col_planes = values[ncp_of]|(values[ncp_of+1]<<8)
num_bpp = values[nbpp_of]|(values[nbpp_of+1]<<8)
compression_type = values[cmpr_of]|(values[cmpr_of+1]<<8)|(values[cmpr_of+2]<<16)|(values[cmpr_of+3]<<24)
raw_size = values[is_of]|(values[is_of+1]<<8)|(values[is_of+2]<<16)|(values[is_of+3]<<24)
colors_palette = values[num_col_pal_of]|(values[num_col_pal_of+1]<<8)|(values[num_col_pal_of+2]<<16)|(values[num_col_pal_of+3]<<24)
col_used = values[imp_col_of]|(values[imp_col_of+1]<<8)|(values[imp_col_of+2]<<16)|(values[imp_col_of+3]<<24)
print "BMP file size: ", bmp_size, " bytes"
print "Data start offset: ", data_start, " 0x%2X" % data_start
print "DIB header size: ", dib_size, " bytes"
print "BMP width: ", bmp_width, "pixels"
print "BMP height: ", bmp_height, "pixels"
print "Num of color planes: ", num_col_planes
print "Num of bits per pixel: ", num_bpp
print "Type of compression: ", compression_type
print "Raw bitmap size: ", raw_size, "bytes"
print "Colors in the palette: ", colors_palette
print "Colors used: ", col_used
txt_file = open(file_to_write, "w")
txt_file.write(";\n; BEGIN bitmap file: " + file_to_write.rstrip(".txt") + "\n;")
#Read bitmap data
img_file = open(file_to_open,"rb")
raw_values = array.array('B') #Array of unsigned char type
raw_values.read(img_file, bmp_size)
img_file.close()
cnt = 0
binl = bmp_width/8 #Bytes in line
for i in range (0, bmp_height): #For each line
str_out = "\n .DB "
for j in range (0, binl, 4): #For each 4 bytes in the line
off1 = data_start + raw_size
off2 = binl * i
if invert_pixel: #Invert pixel values
str_out = str_out + "%Xh," % (0xFF&(~raw_values[off1 - 4 - j - off2]))
str_out = str_out + "%Xh," % (0xFF&(~raw_values[off1 - 3 - j - off2]))
str_out = str_out + "%Xh," % (0xFF&(~raw_values[off1 - 2 - j - off2]))
str_out = str_out + "%Xh," % (0xFF&(~raw_values[off1 - 1 - j - off2]))
else:
str_out = str_out + "%Xh," % raw_values[off1 - 4 - j - off2]
str_out = str_out + "%Xh," % raw_values[off1 - 3 - j - off2]
str_out = str_out + "%Xh," % raw_values[off1 - 2 - j - off2]
str_out = str_out + "%Xh," % raw_values[off1 - 1 - j - off2]
if debug_dump:
print "-4 (%d) from[%Xh]: %Xh," % (cnt+0,off1 - 4 - j - off2,raw_values[off1 - 4 - j - off2])
print "-3 (%d) from[%Xh]: %Xh," % (cnt+1,off1 - 3 - j - off2,raw_values[off1 - 3 - j - off2])
print "-2 (%d) from[%Xh]: %Xh," % (cnt+2,off1 - 2 - j - off2,raw_values[off1 - 2 - j - off2])
print "-1 (%d) from[%Xh]: %Xh," % (cnt+3,off1 - 1 - j - off2,raw_values[off1 - 1 - j - off2])
cnt = cnt + 4
txt_file.write(str_out.rstrip(","))
txt_file.write("\n;\n; END bitmap file: " + file_to_write.rstrip(".txt") + "\n;")
txt_file.close()
print "-----"
print "File converted"
print "Ok"
Увеличенный в 4x4 раза исходный BMP файл bw_32x32_face.bmp
:
Для упрощения скрипта (а также из-за отсутствия времени) присутствует ряд ограничений:
- Ширина монохромного файла должна быть кратна 4;
- Минимальная ширина файла должна быть не меньше 16 пиксел (может, и при 16 будут глюки, не проверял)
Запускаем в консоли питон-скрипт:
> python bmp2mkl.py bw_32x32_face.bmp
--------------------------
File to open: bw_32x32_face.bmp
File to write: bw_32x32_face.bmp.txt
BMP file size: 190 bytes
Data start offset: 62 0x3E
DIB header size: 40 bytes
BMP width: 32 pixels
BMP height: 32 pixels
Num of color planes: 1
Num of bits per pixel: 1
Type of compression: 0
Raw bitmap size: 128 bytes
Colors in the palette: 0
Colors used: 0
-----
File converted
Ok
Скрипт создает текстовый файл bw_32x32_face.bmp.txt
;
; BEGIN bitmap file: bw_32x32_face.bmp
;
.DB FFh,FFh,FFh,FFh
.DB 80h,0h,0h,1h
.DB 80h,3Fh,E0h,1h
.DB 80h,FFh,FCh,1h
.DB 83h,E0h,Fh,1h
.DB 87h,80h,7h,81h
.DB 8Eh,0h,1h,C1h
.DB 8Ch,0h,0h,C1h
.DB 98h,Ch,0h,61h
.DB B8h,33h,0h,71h
.DB B0h,40h,80h,31h
.DB 60h,40h,80h,19h
.DB 60h,80h,40h,19h
.DB 60h,80h,42h,19h
.DB 60h,40h,8Dh,99h
.DB 60h,40h,88h,99h
.DB 60h,33h,8h,99h
.DB 60h,Ch,Dh,99h
.DB 60h,0h,2h,19h
.DB 60h,0h,0h,19h
.DB 60h,3h,C0h,19h
.DB B0h,7Ch,38h,31h
.DB B9h,80h,0h,71h
.DB 98h,0h,0h,61h
.DB 8Ch,0h,0h,C1h
.DB 8Eh,0h,1h,C1h
.DB 87h,80h,7h,81h
.DB 83h,E0h,Fh,1h
.DB 80h,FFh,FCh,1h
.DB 80h,3Fh,E0h,1h
.DB 80h,0h,0h,1h
.DB FFh,FFh,FFh,FFh
;
; END bitmap file: bw_32x32_face.bmp
;
Путем замены символов в notepad-е и преобразования из шестнадцатеричных чисел в двоичные получаем такой битмап:
11111111111111111111111111111111
1 1
1 111111111 1
1 11111111111111 1
1 11111 1111 1
1 1111 1111 1
1 111 111 1
1 11 11 1
1 11 11 11 1
1 111 11 11 111 1
1 11 1 1 11 1
11 1 1 11 1
11 1 1 11 1
11 1 1 1 11 1
11 1 1 11 11 11 1
11 1 1 1 1 11 1
11 11 11 1 1 11 1
11 11 11 11 11 1
11 1 11 1
11 11 1
11 1111 11 1
1 11 11111 111 11 1
1 111 11 111 1
1 11 11 1
1 11 11 1
1 111 111 1
1 1111 1111 1
1 11111 1111 1
1 11111111111111 1
1 111111111 1
1 1
11111111111111111111111111111111
blog comments powered by Disqus