Python小玩具:BMP转字符画(多线程?)

起初是在网上看见了字符动画,所以开始查资料,发现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,表示都重要。

引自:

然后就一步步来解析图像了,用的是最简单的32位BMP

把每个像素的灰度算出来,改成汉字,写入TXT,完事

但是因为不懂灰度怎么划分所以图只能看出个大概=-= 有点蛋疼

另外像素的记录是从右下角开始的,所以图反过来了…改一下就能正过来吧…

有一点值得注意的是BMP头文件记录的数据不是按顺序来的,(具体的变化在代码中给出了)以前想刷黑苹果有注意过这个现象,但是一直不知道为什么,查不到…

另外加了点多线程 ,但是十分坑爹 感觉变慢了…

还有 ,在print到文件的时候每个汉字都隔着一个空格!…所以手动TXT里面替换所有空格…本来是想改下的…但是懒…

代码(写了好久 ):

#-*- coding:utf8 -*-#Nonikka#2014.9.16import os,threading,time #数据转换 8def 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 #数据转换 4def transfrom4(predata_str):datastr = predata_str[2:3] + predata_str[3:4] + predata_str[0:1] + predata_str[1:2]return datastr#数据转换 2def transfrom2(predata_str):datastr = predata_str[1:2] + predata_str[0:1]return datastrbase=[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:breaknum,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=0if __name__ == '__main__':f=open(path +"/"+ filesname[filesflag],'rb')f.seek(0,0)flag=0head=''while(flag<100):byte = f.read(1)hexstr = "%s" % byte.encode('hex') # decnum = int(hexstr,16)head = head + hexstr# 16进制转换flag=flag+1f.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 filesflagwhile(filesflag<len(filesname)):print '%s acquire lock…' % threading.currentThread().getName()if lock.acquire():print '%s get the lock' %threading.currentThread().getName()inside = filesflagfilesflag = filesflag + 1print '%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解析 红+绿+蓝+Alphared=[]green=[]blue=[]Alpha=[]bmpdata = hexstr[len(hexstr)-2457600:]k=0x=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+8else :break#数组中数转为10进制z = 0lenofarray = 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 = 0while(True):if(i<lenofarray):gray.append(299*red[i] + 587*green[i] + 114*blue[i])i = i+1else:break#转换字符characode = ['撒','十','大','夫','打','府','一']i = 0while(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+1else:break#输出out = open("C://Python27/Project file/transfromed/%s.txt" % filesflag,"at")i = lenofarray – 1x = 0while(True):if(x<480):for l in range(640):print >>out,gray[i-640*(x+1)],i=i-1print >>out,'\n',x = x+1else:breakout.close()print "The %s finished" % insidedel reddel greendel bluedel Alphadel graydel i,x,zt1 = 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()

为什么进度这么慢呢?因为在学日语,现在准备今年12月的N2考试啦

另外正在学习Django,不过慢的不行就是了…

只是需要垮上后座的勇气和一颗想走即走的心,

Python小玩具:BMP转字符画(多线程?)

相关文章:

你感兴趣的文章:

标签云: