起初是在網上看見了字符動畫,所以開始查資料,發現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()
另外正在學習Django,不過慢的不行就是了...