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,表示都重要。


引自:http://blog.csdn.net/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()


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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值