Accueil > > > PARSEUR/LECTEUR DE FICHIER BITMAP
PARSEUR/LECTEUR DE FICHIER BITMAP
Information sur la source
Description
Ce code lit directement depuis le fichier bitmap sans utiliser de librairie. Il permet ensuite de lafficher via wx. Il renvoi aussi un tableau au dimension de limage ou chaque cellule est un pixel avec ses valeurs RGB. C'est interessant pour une introduction au module struct et aux manipulations binaires (notamment, pour la bitmap monochrome et 4 bits per pixels (16 colors)). Le module prend pour linstant en charge que les fichiers non compressé (RLE viendra) et que les bitmap monochrome, 4bpp, 8bpp et 24 bpp. Les formats 16 et 32 ayant l'air d'etre assez rare et peu utiliser je ne l'ai pas implementer (surtout que paint ne permet pas denregistrer ds ce format). Dans le zip se trouve un fichier bitmap 256 couleurs (8 bpp).
Source
- #code du module parseur :
- # -*- coding: cp1252 -*-
- import os.path
- import struct as s
- import wx, Afficheur, time, sys
-
- class BitmapError(Exception):
- pass
-
- class NotOpened(BitmapError):
- pass
- class NotExists(BitmapError):
- pass
-
- class bitmap:
- """class permettant de charger et de parser un fichier Bitmap
- """
- def __init__(self):
- self.opened=0
- self.identifier={'BM' : 'Windows 3.1x, 95, NT',
- 'BA' : 'OS/2 Bitmap Array',
- 'CI' : 'OS/2 Color Icon',
- 'CP' : 'OS/2 Color Pointer',
- 'IC' : 'OS/2 Icon',
- 'PT' : 'OS/2 Pointer',
- }
- def load(self, bitmap):
- if(os.path.exists(bitmap)==False) : RaiseNotExists, bitmap+' n\'existe pas'
- f=open(bitmap, 'rb')
- self.ident=self.identifier[f.read(2)]
- self.filesize=s.unpack('L', f.read(4))[0]
- self.reserved=s.unpack('L', f.read(4))[0]
- self.offset=s.unpack('L', f.read(4))[0]
- self.headersize=s.unpack('L', f.read(4))[0]
- self.size=(s.unpack('L', f.read(4))[0], s.unpack('L', f.read(4))[0])
- self.planes=s.unpack('h', f.read(2))[0]
- self.bpp=s.unpack('h', f.read(2))[0]
- self.compression=s.unpack('L', f.read(4))[0]
- self.datasize=s.unpack('L', f.read(4))[0]
- self.hres=s.unpack('L', f.read(4))[0]
- self.vres=s.unpack('L', f.read(4))[0]
- self.colors=s.unpack('L', f.read(4))[0]
- self.impcolors=s.unpack('L', f.read(4))[0]
-
- #creation du tableau de pixels
- self.Pixels=[]
- for i in range(self.size[0]):
- self.Pixels.append([])
- for j in range(self.size[1]):
- self.Pixels[i].append((0,0,0))
-
- if(self.bpp==24 and self.compression==0):
- #1 pixel = 3 octect
- f.seek(self.offset)
- for y in range(self.size[1], 0, -1):
- i=0
- for x in range(self.size[0]):
- pix=f.read(3)
- i+=3
- RGB=(s.unpack('B', pix[2])[0], s.unpack('B', pix[1])[0], s.unpack('B', pix[0])[0])
- self.Pixels[x][y-1]=RGB
- if(i%4!=0): f.read(4-(i%4))
- elif(self.bpp==1 and self.compression==0):
- #1pixel=1bits
- colors=[]
- for i in range(2):
- pix=f.read(4)
- colors.append((s.unpack('B', pix[2])[0], s.unpack('B', pix[1])[0], s.unpack('B', pix[0])[0]))
- print colors
-
- x=0
- y=self.size[1]-1
- i=0
- f.seek(self.offset)
- while 1:
- a=s.unpack('B', f.read(1))[0]
- i+=1
- for j in range(8):
- bit=a & (0x80>>j)
- if(int(bit)!=0): self.Pixels[x][y]=colors[1]
- else: self.Pixels[x][y]=colors[0]
- x+=1
- if(x==self.size[0]):
- x=0
- y-=1
- if(i%4!=0):
- f.read(4-(i%4))
- i=0
- break
- if(y<0) : break
- if(y<0) : break
- elif(self.bpp==4 and self.compression==0):
- #1 pixel = 1/2 octet
- colors=[]
- for i in range(16):
- pix=f.read(4)
- colors.append((s.unpack('B', pix[2])[0], s.unpack('B', pix[1])[0], s.unpack('B', pix[0])[0]))
- print colors
- palindice=['0000', '0100', '0010', '0110', '0001',
- '0101', '0011', '0111', '1000', '1100',
- '1010', '1110', '1001', '1101', '1011', '1111'] ##rangement ds lordre des bits qui corresponde a lordre
- #des couleurs ds la palettes : 0000 --> indice 0 de la palette
- x=0
- y=self.size[1]-1
- i=0
- f.seek(self.offset)
- while 1:
- a=s.unpack('B', f.read(1))[0]
- i+=1
- for j in range(2):
- res=''
- for l in range(j*4, 4*j+4):
- set=a&(0x80>>l)
- if(set!=0) : res+='1'
- else : res+='0'
- self.Pixels[x][y]=colors[palindice.index(res)]
- res=''
- x+=1
- if(x==self.size[0]):
- x=0
- y-=1
- if(i%4!=0):
- f.read(4-(i%4))
- i=0
- break
- if(y<0) : break
- if(y<0) : break
- elif(self.bpp==8 and self.compression==0):
- #1 pixel=1 octet
- colors=[]
- for i in range(256):
- pix=f.read(4)
- colors.append((s.unpack('B', pix[2])[0], s.unpack('B', pix[1])[0], s.unpack('B', pix[0])[0]))
- #print colors
- f.seek(self.offset)
- for y in range(self.size[1], 0, -1):
- i=0
- for x in range(self.size[0]):
- pix=f.read(1)
- i+=1
- self.Pixels[x][y-1]=colors[s.unpack('B', pix)[0]]
- if(i%4!=0): f.read(4-(i%4))
- self.opened=1
- def get_type(self):
- if(self.opened==0):
- raise NotOpened, 'aucun fichier chargé'
- else :
- return self.ident
- def get_filesize(self):
- if(self.opened==0):
- raise NotOpened, 'aucun fichier chargé'
- else :
- return self.filesize
- def get_offset(self):
- if(self.opened==0):
- raise NotOpened, 'aucun fichier chargé'
- else :
- return self.offset
- def get_headersize(self):
- if(self.opened==0):
- raise NotOpened, 'aucun fichier chargé'
- else :
- return self.headersize
- def get_size(self):
- if(self.opened==0):
- raise NotOpened, 'aucun fichier chargé'
- else :
- return self.size
- def get_Pixels(self):
- if(self.opened==0):
- raise NotOpened, 'aucun fichier chargé'
- else :
- return self.Pixels
- def Output(self, pixels):
- img=wx.EmptyImage()
- img.Create(self.size[0], self.size[1])
- for x in range(self.size[0]):
- for y in range(self.size[1]):
- img.SetRGB(x,y, pixels[x][y][0], pixels[x][y][1], pixels[x][y][2])
- return img
-
-
- def affiche(img):
- app = wx.PySimpleApp(0)
- wx.InitAllImageHandlers()
- frame_1 = Afficheur.MyFrame(None, -1, "")
- app.SetTopWindow(frame_1)
- frame_1.set_bitmap(wx.BitmapFromImage(img))
- frame_1.Show()
- app.MainLoop()
-
- if __name__=='__main__':
- b=bitmap()
- b.load('test.bmp')
- print b.get_type()
- print b.get_filesize()
- print b.get_offset()
- print b.get_headersize()
- size=b.get_size()
- print size
-
- affiche(b.Output(b.get_Pixels()))
-
#code du module parseur :
# -*- coding: cp1252 -*-
import os.path
import struct as s
import wx, Afficheur, time, sys
class BitmapError(Exception):
pass
class NotOpened(BitmapError):
pass
class NotExists(BitmapError):
pass
class bitmap:
"""class permettant de charger et de parser un fichier Bitmap
"""
def __init__(self):
self.opened=0
self.identifier={'BM' : 'Windows 3.1x, 95, NT',
'BA' : 'OS/2 Bitmap Array',
'CI' : 'OS/2 Color Icon',
'CP' : 'OS/2 Color Pointer',
'IC' : 'OS/2 Icon',
'PT' : 'OS/2 Pointer',
}
def load(self, bitmap):
if(os.path.exists(bitmap)==False) : RaiseNotExists, bitmap+' n\'existe pas'
f=open(bitmap, 'rb')
self.ident=self.identifier[f.read(2)]
self.filesize=s.unpack('L', f.read(4))[0]
self.reserved=s.unpack('L', f.read(4))[0]
self.offset=s.unpack('L', f.read(4))[0]
self.headersize=s.unpack('L', f.read(4))[0]
self.size=(s.unpack('L', f.read(4))[0], s.unpack('L', f.read(4))[0])
self.planes=s.unpack('h', f.read(2))[0]
self.bpp=s.unpack('h', f.read(2))[0]
self.compression=s.unpack('L', f.read(4))[0]
self.datasize=s.unpack('L', f.read(4))[0]
self.hres=s.unpack('L', f.read(4))[0]
self.vres=s.unpack('L', f.read(4))[0]
self.colors=s.unpack('L', f.read(4))[0]
self.impcolors=s.unpack('L', f.read(4))[0]
#creation du tableau de pixels
self.Pixels=[]
for i in range(self.size[0]):
self.Pixels.append([])
for j in range(self.size[1]):
self.Pixels[i].append((0,0,0))
if(self.bpp==24 and self.compression==0):
#1 pixel = 3 octect
f.seek(self.offset)
for y in range(self.size[1], 0, -1):
i=0
for x in range(self.size[0]):
pix=f.read(3)
i+=3
RGB=(s.unpack('B', pix[2])[0], s.unpack('B', pix[1])[0], s.unpack('B', pix[0])[0])
self.Pixels[x][y-1]=RGB
if(i%4!=0): f.read(4-(i%4))
elif(self.bpp==1 and self.compression==0):
#1pixel=1bits
colors=[]
for i in range(2):
pix=f.read(4)
colors.append((s.unpack('B', pix[2])[0], s.unpack('B', pix[1])[0], s.unpack('B', pix[0])[0]))
print colors
x=0
y=self.size[1]-1
i=0
f.seek(self.offset)
while 1:
a=s.unpack('B', f.read(1))[0]
i+=1
for j in range(8):
bit=a & (0x80>>j)
if(int(bit)!=0): self.Pixels[x][y]=colors[1]
else: self.Pixels[x][y]=colors[0]
x+=1
if(x==self.size[0]):
x=0
y-=1
if(i%4!=0):
f.read(4-(i%4))
i=0
break
if(y<0) : break
if(y<0) : break
elif(self.bpp==4 and self.compression==0):
#1 pixel = 1/2 octet
colors=[]
for i in range(16):
pix=f.read(4)
colors.append((s.unpack('B', pix[2])[0], s.unpack('B', pix[1])[0], s.unpack('B', pix[0])[0]))
print colors
palindice=['0000', '0100', '0010', '0110', '0001',
'0101', '0011', '0111', '1000', '1100',
'1010', '1110', '1001', '1101', '1011', '1111'] ##rangement ds lordre des bits qui corresponde a lordre
#des couleurs ds la palettes : 0000 --> indice 0 de la palette
x=0
y=self.size[1]-1
i=0
f.seek(self.offset)
while 1:
a=s.unpack('B', f.read(1))[0]
i+=1
for j in range(2):
res=''
for l in range(j*4, 4*j+4):
set=a&(0x80>>l)
if(set!=0) : res+='1'
else : res+='0'
self.Pixels[x][y]=colors[palindice.index(res)]
res=''
x+=1
if(x==self.size[0]):
x=0
y-=1
if(i%4!=0):
f.read(4-(i%4))
i=0
break
if(y<0) : break
if(y<0) : break
elif(self.bpp==8 and self.compression==0):
#1 pixel=1 octet
colors=[]
for i in range(256):
pix=f.read(4)
colors.append((s.unpack('B', pix[2])[0], s.unpack('B', pix[1])[0], s.unpack('B', pix[0])[0]))
#print colors
f.seek(self.offset)
for y in range(self.size[1], 0, -1):
i=0
for x in range(self.size[0]):
pix=f.read(1)
i+=1
self.Pixels[x][y-1]=colors[s.unpack('B', pix)[0]]
if(i%4!=0): f.read(4-(i%4))
self.opened=1
def get_type(self):
if(self.opened==0):
raise NotOpened, 'aucun fichier chargé'
else :
return self.ident
def get_filesize(self):
if(self.opened==0):
raise NotOpened, 'aucun fichier chargé'
else :
return self.filesize
def get_offset(self):
if(self.opened==0):
raise NotOpened, 'aucun fichier chargé'
else :
return self.offset
def get_headersize(self):
if(self.opened==0):
raise NotOpened, 'aucun fichier chargé'
else :
return self.headersize
def get_size(self):
if(self.opened==0):
raise NotOpened, 'aucun fichier chargé'
else :
return self.size
def get_Pixels(self):
if(self.opened==0):
raise NotOpened, 'aucun fichier chargé'
else :
return self.Pixels
def Output(self, pixels):
img=wx.EmptyImage()
img.Create(self.size[0], self.size[1])
for x in range(self.size[0]):
for y in range(self.size[1]):
img.SetRGB(x,y, pixels[x][y][0], pixels[x][y][1], pixels[x][y][2])
return img
def affiche(img):
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
frame_1 = Afficheur.MyFrame(None, -1, "")
app.SetTopWindow(frame_1)
frame_1.set_bitmap(wx.BitmapFromImage(img))
frame_1.Show()
app.MainLoop()
if __name__=='__main__':
b=bitmap()
b.load('test.bmp')
print b.get_type()
print b.get_filesize()
print b.get_offset()
print b.get_headersize()
size=b.get_size()
print size
affiche(b.Output(b.get_Pixels()))
Conclusion
Voila donc normalement Aucun bug fonctionne meme avec les bitmap dont la taille de la largeur n'est pas un multiple de 4 octets.
Historique
- 30 septembre 2005 23:58:48 :
- ...
Sources du même auteur
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
[MIX 2010] - TELECHARGEZ INTERNET EXPLORER 9 EN PREVIEW ![MIX 2010] - TELECHARGEZ INTERNET EXPLORER 9 EN PREVIEW ! par redo
La Preview de Windows Explorer 9 est maintenant disponible à l'adresse suivante : http://ie.microsoft.com/testdrive/ Cette version ne nécessite pas un redémarrage de votre machine pour être exploitée . Cette version est fonctionnelle mais reste cependant ...
Cliquez pour lire la suite de l'article par redo [MIX 2010] - KEYNOTE DAY 2 ONLINE : WINDOWS INTERNET EXPLORER 9, JQUERY, ODATA ET DALLAS CTP2 ![MIX 2010] - KEYNOTE DAY 2 ONLINE : WINDOWS INTERNET EXPLORER 9, JQUERY, ODATA ET DALLAS CTP2 ! par redo
Dans la lignée du premier keynote, retrouvez la vidéo du second keynote en ligne : Visionnez la vidéo à l'url suivante : http://www.microsoft.com/presspass/events/mix/VideoGallery.aspx Vous y retrouverez ainsi les speakers Scott Guthrie, Dean Hachamovitch...
Cliquez pour lire la suite de l'article par redo [MIX 2010] - RETOUR D'EXPéRIENCE DéVELOPPEMENT SEESMIC SUR WINDOWS PHONE 7[MIX 2010] - RETOUR D'EXPéRIENCE DéVELOPPEMENT SEESMIC SUR WINDOWS PHONE 7 par redo
En avant première, Loic le retour d'expérience de Loïc Le Meur du portage de l'application http://seesmic.com/ sur plateforme Windows Phone 7 . c'était d'ailleurs une des rares opportunités de tester, voir toucher le nouveau device . voyez par vous-même :...
Cliquez pour lire la suite de l'article par redo [MIX 2010] - LE KEYNOTE DAY 1 DISPONIBLE ONLINE ![MIX 2010] - LE KEYNOTE DAY 1 DISPONIBLE ONLINE ! par redo
Si tout comme moi, vous avez manqué de peu le premier keynote du Microsoft Mix 2010, je vous invite à prendre deux heure et le consulter ci-dessous . Visionnez le Keynote à l'url suivante : http://www.microsoft.com/Presspass/events/mix/videoGallery.aspx?c...
Cliquez pour lire la suite de l'article par redo VISUAL STUDIO TALK SHOW: EF4VISUAL STUDIO TALK SHOW: EF4 par Matthieu MEZIL
La semaine dernière, j'étais à Montréal pour y animer des conférences sur Entity Framework. J'en ai profité pour enregister un podcast Visual Studio Talk Show que vous pouvez retrouver ici ....(read more) ...
Cliquez pour lire la suite de l'article par Matthieu MEZIL
Logiciels
Xilisoft Convertisseur Vidéo Ultimate (5.1.39.0305)XILISOFT CONVERTISSEUR VIDéO ULTIMATE (5.1.39.0305)Xilisoft Convertisseur Vidéo Ultimate est un outil puissant de conversion vidéo, facile à utilise... Cliquez pour télécharger Xilisoft Convertisseur Vidéo Ultimate Xilisoft DVD Ripper Ultimate (5.0.64.0304)XILISOFT DVD RIPPER ULTIMATE (5.0.64.0304)Xilisoft DVD Ripper Ultimate est un logiciel excellent pour copier et convertir DVD vers presque ... Cliquez pour télécharger Xilisoft DVD Ripper Ultimate Rigs of Rods (63.3)RIGS OF RODS (63.3)c'est un jeu de multi-simulation camions,autobus voitures, avions, bateaux, hélicoptère avec défo... Cliquez pour télécharger Rigs of Rods Konvertor (4.00)KONVERTOR (4.00)Le logiciel est un gestionnaire multimedia affichant, jouant et convertissant plus de 2000 format... Cliquez pour télécharger Konvertor
|