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,不過慢的不行就是了...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章