起初是在网上看见了字符动画,所以开始查资料,发现BMP文件开头是
具体数据举例:
如某BMP文件开头:
424D 4690 0000 0000 0000 4600 0000 2800 0000 8000 0000 9000 0000 0100*1000 0300 0000 0090 0000 A00F 0000 A00F 0000 0000 0000 0000 0000*00F8 0000 E007 0000 1F00 0000 0000 0000*02F1 84F1 04F1 84F1 84F1 06F2 84F1 06F2 04F2 86F2 06F2 86F2 86F2 .... ....
BMP文件可分为四个部分:位图文件头、位图信息头、彩色板、图像数据阵列,在上图中已用*分隔。
一、图像文件头
1)1:(这里的数字代表的是"字",即两个字节,下同)图像文件头。424Dh=’BM’,表示是Windows支持的BMP格式。
2)2-3:整个文件大小。4690 0000,为00009046h=36934。
3)4-5:保留,必须设置为0。
4)6-7:从文件开始到位图数据之间的偏移量。4600 0000,为00000046h=70,上面的文件头就是35字=70字节。
5)8-9:位图图信息头长度。
6)10-11:位图宽度,以像素为单位。8000 0000,为00000080h=128。
7)12-13:位图高度,以像素为单位。9000 0000,为00000090h=144。
8)14:位图的位面数,该值总是1。0100,为0001h=1。
二、位图信息头
9)15:每个像素的位数。有1(单色),4(16色),8(256色),16(64K色,高彩色),24(16M色,真彩色),32(4096M色,增强型真彩色)。1000为0010h=16。
10)16-17:压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)。RLE简单地说是采用像素数+像素值的方式进行压缩。T408采用的是位域存放方式,用两个字节表示一个像素,位域分配为r5b6g5。图中0300 0000为00000003h=3。
11)18-19:用字节数表示的位图数据的大小,该数必须是4的倍数,数值上等于位图宽度×位图高度×每个像素位数。0090 0000为00009000h=80×90×2h=36864。
12)20-21:用象素/米表示的水平分辨率。A00F 0000为0000 0FA0h=4000。
13)22-23:用象素/米表示的垂直分辨率。A00F 0000为0000 0FA0h=4000。
14)24-25:位图使用的颜色索引数。设为0的话,则说明使用所有调色板项。
15)26-27:对图象显示有重要影响的颜色索引的数目。如果是0,表示都重要。
引自:http://blog.youkuaiyun.com/zhaozidong86/article/details/6628469
然后就一步步来解析图像了,用的是最简单的32位BMP
把每个像素的灰度算出来,改成汉字,写入TXT,完事
但是因为不懂灰度怎么划分所以图只能看出个大概=-= 有点蛋疼
另外像素的记录是从右下角开始的,所以图反过来了...改一下就能正过来吧...
有一点值得注意的是BMP头文件记录的数据不是按顺序来的,(具体的变化在代码中给出了)以前想刷黑苹果有注意过这个现象,但是一直不知道为什么,查不到...
另外加了点多线程 ,但是十分坑爹 感觉变慢了...
还有 ,在print到文件的时候每个汉字都隔着一个空格!...所以手动TXT里面替换所有空格...本来是想改下的...但是懒...
代码(写了好久 ):
#-*- coding:utf8 -*-
#Nonikka
#2014.9.16
import os,threading,time
#数据转换 8
def transfrom(predata_str):
datastr = predata_str[6:7] + predata_str[7:8] + predata_str[4:5] + predata_str[5:6] + predata_str[2:3] + predata_str[3:4] + predata_str[0:1] + predata_str[1:2]
return datastr
#数据转换 4
def transfrom4(predata_str):
datastr = predata_str[2:3] + predata_str[3:4] + predata_str[0:1] + predata_str[1:2]
return datastr
#数据转换 2
def transfrom2(predata_str):
datastr = predata_str[1:2] + predata_str[0:1]
return datastr
base=[str(x) for x in range(10)] + [chr(x) for x in range(ord('a'),ord('a')+6)]
#16进制 to 10进制
def hex2dec(string_num):
return str(int(string_num.upper(),16))
#16进制 to 2进制
def hex2bin(string_num):
num = int (string_num)
mid = []
while True:
if num ==0:break
num,rem = divmod(num,2)
mid.append(base[rem])
return ''.join([str(x) for x in mid[::-1]])
path = 'C://Python27/Project file/extract'
filesname = os.listdir(path)
# BMP文件头
filesflag=0
if __name__ == '__main__':
f=open(path +"/"+ filesname[filesflag],'rb')
f.seek(0,0)
flag=0
head=''
while(flag<100):
byte = f.read(1)
hexstr = "%s" % byte.encode('hex') # decnum = int(hexstr,16)
head = head + hexstr # 16进制转换
flag=flag+1
f.close()
#print head[4:12]
prefilesize=head[4:12]
prefilesize = str(prefilesize)
#文件大小
filesize = prefilesize[6:7] + prefilesize[7:8] + prefilesize[4:5] + prefilesize[5:6] + prefilesize[2:3] + prefilesize[3:4] + prefilesize[0:1] + prefilesize[1:2]
#位图像素宽度
biwidth = head[36:44]
biwidth = hex2dec(transfrom(biwidth))
#位图像素高度
biheight = head[44:52]
biheight = hex2dec(transfrom(biheight))
#颜色深度
biBitcount = head[56:60]
biBitcount = hex2dec(transfrom4(biBitcount))
#偏移量 图像数据的地址 即文件头+信息头+调色板的长度
OffBits = head[20:24]
OffBits = hex2dec(transfrom4(OffBits))
OffBits = int(OffBits)
Databig = head[68:76]
Databig = hex2dec(transfrom(Databig))
Databig = int(Databig)
filesize=hex2dec(filesize)
#*******************************************读取文件数据开始**********************************************
lock = threading.Lock()
#while(filesflag<len(filesname)):
def func():
global filesflag
while(filesflag<len(filesname)):
print '%s acquire lock...' % threading.currentThread().getName()
if lock.acquire():
print '%s get the lock' %threading.currentThread().getName()
inside = filesflag
filesflag = filesflag + 1
print '%s release lock...' % threading.currentThread().getName()
lock.release()
file=open(path +"/"+ filesname[inside],'rb')
file.seek(0,0)
byte = file.read()
hexstr = "%s" % byte.encode('hex')
#接下来是32位的BMP解析 红+绿+蓝+Alpha
red=[]
green=[]
blue=[]
Alpha=[]
bmpdata = hexstr[len(hexstr)-2457600:]
k=0
x=0
#存入4个数组
while(True):
if(x<(len(bmpdata))):
blue.append(bmpdata[x:x+2])
green.append(bmpdata[x+2:x+4])
red.append(bmpdata[x+4:x+6])
x = x+8
else :
break
#数组中数转为10进制
z = 0
lenofarray = len(red)
for z in range(len(red)):
blue[z] = transfrom2(blue[z])
green[z] = transfrom2(green[z])
red[z] = transfrom2(red[z])
for i in range(len(red)):
red[i] = int(red[i],16)
green[i] = int(green[i],16)
blue[i] = int(blue[i],16)
gray = []
i = 0
while(True):
if(i<lenofarray):
gray.append(299*red[i] + 587*green[i] + 114*blue[i])
i = i+1
else:
break
#转换字符
characode = ['撒','十','大','夫','打','府','一']
i = 0
while(True):
if(i<lenofarray):
if(gray[i]>=820*256):
gray[i] = characode[0]
elif(gray[i]>=700*256):
gray[i] = characode[1]
elif(gray[i]>=580*256):
gray[i] = characode[2]
elif(gray[i]>=460*256):
gray[i] = characode[3]
elif(gray[i]>=310*256):
gray[i] = characode[4]
elif(gray[i]>=160*256):
gray[i] = characode[5]
else :
gray[i] = characode[6]
i = i+1
else:
break
#输出
out = open("C://Python27/Project file/transfromed/%s.txt" % filesflag,"at")
i = lenofarray - 1
x = 0
while(True):
if(x<480):
for l in range(640):
print >>out,gray[i-640*(x+1)],
i=i-1
print >>out,'\n',
x = x+1
else:
break
out.close()
print "The %s finished" % inside
del red
del green
del blue
del Alpha
del gray
del i,x,z
t1 = threading.Thread(target = func)
t2 = threading.Thread(target = func)
t3 = threading.Thread(target = func)
t4 = threading.Thread(target = func)
t5 = threading.Thread(target = func)
t6 = threading.Thread(target = func)
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
t6.start()
另外正在学习Django,不过慢的不行就是了...