BMP Grafikentschlüssel

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

 

morszeck

Betreff: BMP Grafikentschlüssel

BeitragFr, Jul 30, 2004 0:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Hier ein Beispielprogramm wie man ein BMP-Bild dekodieren kann. Zur Zeit werden 1-bit (monochrom) 8-bit (256 Graustufen) und 24-bit (Truecolor) unterstützt.

Quelltext sowie die Variabeln sind selbsterklärend. Das ganze soll zu Lehrzwecken dienen.


BlitzBasic: [AUSKLAPPEN]
; BMP Grafikentschlüssel V1.2 
;
; Bei Auflösung des mehrstelliger Bytes Schlüssel
; ist das 1. Byte ist immer das niedrigste Byte
;
; alle Werte sind Dezimal angegeben
;
;
; Byte Bedeutung
;
; 0-13 Dateikopf
;
; 0-1 Zeichen BM
; 2-5 Dateigrösse in Byte
; 6-9 Reserviert (unbedeutend)
; 10-13 BMP-Dateikopfgrösse/Bildpositionsanfang
; Dateigrösse - Dateikopfgrösse = Bildgösse
;
; 14-53 Informationsblock/Datenstruktur 40byte (Ausmass, Farbformat)
;
; 14-17 Grösse der Datenstruktur (normalerweise 40)
; 18-21 Breite in Pixel
; 22-25 Höhe in Pixel
; 26-27 Anzahl Farbebenen für das Ausgabegerät (normalerweise 1)
; 28-29 Anzahl Bits die zur Speicherung eines Pixel noetig sind
; 1 = 2 Farben (schwarzweiss Grafik)
; 4 = 16 Farben
; 8 = 256 Farben (Graustufen)
; 24 = 16 Mio. Farben
; 0 = es existiert keine Farbtabelle
; 30-33 Typ der Datenkomprimierung
; 0 = unkomprimiert
; 1 = lauflängencodierte max. 16 Farben 4Bit pro Pixel
; 2 = lauflängencodierte max. 256 Farben 8Bit pro Pixel
; 34-37 Grösse der Bitmap in Byte
; 38-41 Breite der Bitmap in Pixel pro Meter (unbedeutend)
; 42-45 Höhe der Bitmap in Pixel pro Meter (unbedeutend)
; 46-49 Anzahl der verwendeten Farben
; die weniger Farben als tatsächlich enthält, bei Bildern < 24bit
; 50-53 Anzahl der wichtigen Farben, bei Bitmapkomprimierung
;
; 54-... Beginn der Bitmap oder Farbtabelle, wen Bitmap < 24bit (siehe byte 28-29)
; Die Daten sind von unten/recht nach oben/links gespeichert!
;
;
; Bei Bitmaps mit 24 bit Auflösung gilt:
;
; 0 Intensität der Grundfarbe blau
; 1 Intensität der Grundfarbe grün
; 2 Intensität der Grundfarbe rot
;
;
; Bei Bitmaps mit 1 bit Auflösung gilt:
;
; In jeweils ein Byte werden 8 Bildpunkte gespeichert.
;
;
;----------------------------------------------------------------
;

Graphics 800,600,32,2

Global datei ; workdata
Global daten ; bank
Global info_datei ; bank
Global info_farbtabelle ; bank
Global info_dateigroesse ; variabel
Global info_infogroesse ;variabel
Global info_datengroesse ; variabel
Global info_pixelbreite ; variabel
Global info_pixelhoehe ; variabel
Global info_farbebenen ; variabel
Global info_colorformat ; variabel
Global info_komprimierung ; variabel
Global info_bitmapgroesse ; variabel
Global info_breitepixelmeter ; variabel
Global info_hoehepixelmeter ; variabel
Global info_anzahlfarben ; variabel
Global info_wichtigefarben ; variabel


; Öffnen der BMP-Datei und ermitteln der Dateilänge
datei = ReadFile("03441437.bmp")


;----------------------------------------------------------------


; Datenbank für Dateikopf erstellen [byte 0-53]
info_datei = CreateBank(54)

; Dateikopf einlesen, die Ersten 54 Bytes [byte 0-53]
For t = 0 To 53
PokeByte info_datei, t, ReadByte(datei)
Next


;----------------------------------------------------------------


; Auslesen und berechnen der Dateigrösse [byte 2-5]
For t = 5 To 2 Step -1
info_dateigroesse = info_dateigroesse * 256 + PeekByte(info_datei,t)
Next
Print "info_dateigoesse : " + info_dateigroesse


; Auslesen und berechnen der kompletten Infogösse (mit Farbtabelle) [byte 10-13]
For t = 13 To 10 Step -1
info_infogroesse = info_infogroesse * 256 + PeekByte(info_datei, t)
Next
Print "info_infogroesse : " + info_infogroesse


; Auslesen und berechnen der Bilddatengrösse [byte 14-17]
For t = 17 To 14 Step -1
info_infoblock = info_infoblock * 256 + PeekByte(info_datei, t)
Next
Print "info_infoblock : " + info_infoblock


; Auslesen und berechnen der Breite in Pixel [byte 18-21]
For t = 21 To 18 Step -1
info_pixelbreite = info_pixelbreite * 256 + PeekByte(info_datei, t)
Next
Print "info_pixelbreite : " + info_pixelbreite


; Auslesen und berechnen der Höhe in Pixel [byte 22-25]
For t = 25 To 22 Step -1
info_pixelhoehe = info_pixelhoehe * 256 + PeekByte(info_datei, t)
Next
Print "info_pixelhoehe : " + info_pixelhoehe


; Auslesen und berechnen der Farbebenen [byte 26-27]
For t = 27 To 26 Step -1
info_farbebenen = info_farbebenen * 256 + PeekByte(info_datei, t)
Next
Print "info_farbebenen : " + info_farbebenen


; Auslesen und berechnen der Höhe in Pixel [byte 28-29]
For t = 29 To 28 Step -1
info_colorformat = info_colorformat * 256 + PeekByte(info_datei, t)
Next
Print "info_colorformat : " + info_colorformat


; Auslesen und berechnen der Datenkomprimierung [byte 30-33]
For t = 33 To 30 Step -1
info_komprimierung = info_komprimierung * 256 + PeekByte(info_datei, t)
Next
Print "info_komprimierung : " + info_komprimierung


; Auslesen und berechnen der Bitmapgrösse [byte 34-37]
For t = 37 To 34 Step -1
info_bitmapgroesse = info_bitmapgroesse * 256 + PeekByte(info_datei, t)
Next
Print "info_bitmapgroesse : " + info_bitmapgroesse


; Auslesen und berechnen der Pixelbreite pro Meter [byte 38-41]
For t = 38 To 41 Step -1
info_breitepixelmeter = info_breitepixelmeter * 256 + PeekByte(info_datei, t)
Next
Print "info_breitepixelmeter : " + info_breitepixelmeter


; Auslesen und berechnen der Pixelhöhe pro Meter [byte 42-45]
For t = 45 To 42 Step -1
info_hoehepixelmeter = info_hoehepixelmeter * 256 + PeekByte(info_datei, t)
Next
Print "info_hoehepixelmeter : " + info_hoehepixelmeter


; Auslesen und berechnen der Anzahl verwendeten Farben [byte 46-49]
For t = 49 To 46 Step -1
info_anzahlfarben = info_anzahlfarben * 256 + PeekByte(info_datei, t)
Next
Print "info_anzahlfarben : " + info_anzahlfarben


; Auslesen und berechnen der Anzahl wichtiger Farben [byte 50-53]
For t = 50 To 53 Step -1
info_wichtigefarben = info_wichtigefarben * 256 + PeekByte(info_datei, t)
Next
Print "info_wichtigefarben : " + info_wichtigefarben


;----------------------------------------------------------------

; Datenbank für die Farbtabelle bei Bitmaps < 24 bit
If info_infogroesse > 54 Then

info_farbtabelle = CreateBank(info_infogroesse - 54)

For t = 0 To (BankSize(info_farbtabelle) - 1)
PokeByte info_farbtabelle, t, ReadByte(datei)
Next

Print "info_farbtabelle : " + BankSize(info_farbtabelle)

Else

Print "info_farbtabelle : " + 0

EndIf


;----------------------------------------------------------------


; Datenbank für die Bilddaten
daten = CreateBank(info_bitmapgroesse)


; Bilddaten einlesen
For t = 0 To (BankSize(daten) - 1)

PokeByte daten, t, ReadByte(datei)

Next


;----------------------------------------------------------------


; Auslesen und berechnen eines 24 bit Bildes (truecolor)
If info_colorformat = 24 Then

; y-Achse auf Bitmap-Pixelhöhe setzen (zum decodieren notwendig)
y = info_pixelhoehe

For t = 0 To (info_bitmapgroesse - 1) Step 3

If x = info_pixelbreite Then x = 0 : y = y - 1

blau = PeekByte(daten, t)
gruen = PeekByte(daten, t + 1)
rot = PeekByte(daten, t + 2)

Color rot, gruen, blau

Plot x + 300 , y

x = x + 1

Next

End If


;----------------------------------------------------------------


; Auslesen und berechnen eines 1 bit Bildes (monochrom)
If info_colorformat = 1 Then

; y-Achse auf Bitmap-Pixelhöhe setzen (zum decodieren notwendig)
y = info_pixelhoehe

For t = 0 To (info_bitmapgroesse - 1)

For byte = 7 To 0 Step - 1

If x = info_pixelbreite Then x = 0 : y = y - 1

bit = 2^byte And PeekByte(daten, t)

If bit > 0 Then Color 255, 255, 255 Else Color 0, 0, 0

Plot x + 300, y

x = x + 1

Next

Next

End If


;----------------------------------------------------------------


; Auslesen und berechnen eines 8 bit Bildes (256 Graustufen)
If info_colorformat = 8 Then

; y-Achse auf Bitmap-Pixelhöhe setzen (zum decodieren notwendig)
y = info_pixelhoehe

For t = 0 To (info_bitmapgroesse - 1)

If x = info_pixelbreite Then x = 0 : y = y - 1

bit = PeekByte(daten, t)

Color bit, bit, bit

Plot x + 300, y

x = x + 1

Next

End If

;----------------------------------------------------------------


Color 255, 255, 255
Text 0, 580, " fertig, Programm beenden mit beliebiger Taste... "

WaitKey()
End

WinXpProf&SP2, B3D V1.88, B+ V1.40, BMax101Beta, AMD TB1.4GHz, DDR266/768MB, GeForce3@64MB

Vertex

BeitragSa, Jul 31, 2004 11:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist das nicht von morszeck geklaut?
vertex.dreamfall.at | GitHub
 

hot-bit

Gast

BeitragSa, Jul 31, 2004 11:26
Antworten mit Zitat
Hoi,

nein, glaube nicht ! Wink

Toni

MVB

BeitragSa, Jul 31, 2004 12:34
Antworten mit Zitat
Benutzer-Profile anzeigen
morszeck=ping=husky
aquamonit.de|BlitzMax|MaxGUI
 

morszeck

BeitragSa, Jul 31, 2004 17:47
Antworten mit Zitat
Benutzer-Profile anzeigen
genau Smile Es ist in der neuen Version nur die 8-bit Entschlüsselung hinzu gekommen, da meine Freundin an ein MRT arbeitet und ich ihr eine Software schreiben muss um mehrere Bilder in 3D darzustellen, die eben nur 8-bit Graustufen-Grafik sind...
WinXpProf&SP2, B3D V1.88, B+ V1.40, BMax101Beta, AMD TB1.4GHz, DDR266/768MB, GeForce3@64MB
 

David

BeitragSa, Jul 31, 2004 22:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi!

Gut, aber muss noch bisschen erweitert werden, z.B. werden noch keine Komprimierten Bilder unterstützt oder?? Smile

grüße
http://bl4ckd0g.funpic.de

D2006

Administrator

BeitragSo, Aug 01, 2004 10:57
Antworten mit Zitat
Benutzer-Profile anzeigen
jetzt hör ich das schon das zweite mal dieses Wochenende:

seit wann gibt es komprimierte BMP's ???
In Bitmaps ist doch jeder Pixel eingespeichert, weswegen die auch so
verdammt groß sind, oder irre ich mich da ?

MfG

Vertex

BeitragSo, Aug 01, 2004 13:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Axo, gut dann hatte ich ja insofern mit morszeck recht Smile
D2006: Also ich kenn mich mit BMP auch nicht so genau aus, aber es hat glaube ich eine extra Option für Run length encoding.
mfg olli
vertex.dreamfall.at | GitHub
 

morszeck

BeitragSo, Aug 01, 2004 13:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Es gibt sowas wie eine komprimierung von BMP, also wen man dies so sagen darf. Wen jemanden dies schon aufgefallen ist, so kann man in einer bmp eine Farbtabelle abspeichern. So ist jedes Byte keine Farbinformation sondern ein Wert in der Farbtabelle... So ähnlich wie es in GIF's gehandhabt wird...
WinXpProf&SP2, B3D V1.88, B+ V1.40, BMax101Beta, AMD TB1.4GHz, DDR266/768MB, GeForce3@64MB

Vertex

BeitragSo, Aug 01, 2004 14:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe mal von Wotsit das ganze herausgefischt:
Zitat:
Bitmap Compression

Windows versions 3.0 and later support run-length encoded (RLE) formats for
compressing bitmaps that use 4 bits per pixel and 8 bits per pixel.
Compression reduces the disk and memory storage required for a bitmap.

Compression of 8-Bits-per-Pixel Bitmaps

When the biCompression member of the BITMAPINFOHEADER structure is set to
BI_RLE8, the DIB is compressed using a run-length encoded format for a
256-color bitmap. This format uses two modes: encoded mode and absolute mode.
Both modes can occur anywhere throughout a single bitmap.

Encoded Mode

A unit of information in encoded mode consists of two bytes. The first byte
specifies the number of consecutive pixels to be drawn using the color index
contained in the second byte. The first byte of the pair can be set to zero
to indicate an escape that denotes the end of a line, the end of the bitmap,
or a delta. The interpretation of the escape depends on the value of the
second byte of the pair, which must be in the range 0x00 through 0x02.
Following are the meanings of the escape values that can be used in the
second byte:

Second byte Meaning

0 End of line.
1 End of bitmap.
2 Delta. The two bytes following the escape contain unsigned values
indicating the horizontal and vertical offsets of the next pixel from the
current position.


husky: Sind die GIF Dateien NUR auf diese Tabelle beschränkt als Kompression, oder wird noch eine weitere durchgeführt?
vertex.dreamfall.at | GitHub
 

morszeck

BeitragSo, Aug 01, 2004 14:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Bei gif bin ich mir nicht sicher. Soweit ich aber weiss, kann man mit gif's nur max 256 Farben darstellen, die aber in einer Farbtabelle mitteln Truecolor definiert werden können. Aber gif finde ich ausser wegen der Animationskontrolle uninteressant. Da ist png interessanter...

Von GalieleoPress gibts ein Buch über verschiedenste Datenformate wie auch BitMap sowie andere zbsp Word etc... Das kann ich nur empfehlen...
WinXpProf&SP2, B3D V1.88, B+ V1.40, BMax101Beta, AMD TB1.4GHz, DDR266/768MB, GeForce3@64MB

Xenon

BeitragMo, Aug 09, 2004 20:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,

ich hab mir für meine OpenGL Engine auch einen BMP Loader gebaut, der nicht auf deinen Code hier aufbaut, aber ziemlich Ähnlich abläuft.

Dein Code husky hat allerdings ein paar Macken:

du ließt zuerst in eine Bank und speicherst das ganze dann umständlich in Variablen mit so nem for-Schleifen-Kack um anscheinend Little Endian zu lesen. Allerdings wird immer Little Endian gelesen, dh. du kannst ruhig ReadInt, ReadShort und ReadByte nehmen, wie ich!
Ebenso sind der 1 Bit und 8 Bit Code falsch, da es nicht wirklich Monochrom oder Graustufen ist. In Wirklichkeit sind die Werte die Indizes für die Palette die du ja auch ließt!

Zusätzlich kann mein Code auch 4 Bit Bitmaps lesen. Das einzige was noch fehlt ist die Komprimierung.

Darum habe ich meinen Code nach BB übersetzt und stelle ihn euch hier zu Verfügung:

BlitzBasic: [AUSKLAPPEN]
; Bitmap laden
Function LoadBmp(szFileName$)
Local File
Local uiFileSize
Local uiReserved1
Local uiBMPBegin
Local uiSize
Local uiWidth
Local uiHeight
Local usLayerCount
Local usBitsPerPixel
Local uiCompression
Local uiBitMapSize
Local uiWidthPixelPerMeter
Local uiHeightPixelPerMeter
Local uiColorCounr
Local uiImportantCompressionColors
Local pData
Local pFileData
Local pColorData

Local t, x, y, i
Local bits
Local R, G, B, Byte, M

; Prüfen ob die Datei existiert
If szFileName = "" Then Return 0

File = ReadFile(szFileName)

If Not File Then Return 0

; Prüfen ob der Header passt
B = ReadByte(File)
M = ReadByte(File)

If (B <> Asc("B")) Or (M <> Asc("M")) Then
CloseFile(File)
Return 0
End If

; Header und Dataheader lesen
uiFileSize = ReadInt(File)
uiReserved1 = ReadInt(File)
uiBMPBegin = ReadInt(File)
uiSize = ReadInt(File)
uiWidth = ReadInt(File)
uiHeight = ReadInt(File)
usLayerCount = ReadShort(File)
usBitsPerPixel = ReadShort(File)
uiCompression = ReadInt(File)
uiBitMapSize = ReadInt(File)
uiWidthPixelPerMeter = ReadInt(File)
uiHeightPixelPerMeter = ReadInt(File)
uiColorCounr = ReadInt(File)
uiImportantCompressionColors = ReadInt(File)

; Falls Palette vorhanden, die Palette lesen
If uiBMPBegin > 54 Then
pColorData = CreateBank(uiBMPBegin - 54)
For i = 0 To uiBMPBegin-55
PokeByte pColorData, i, ReadByte(file)
Next
End If

; Bitmap daten lesen
pFileData = CreateBank(uiBitMapSize)
For i=0 To uiBitMapSize-1
PokeByte pFileData, i, ReadByte(file)
Next

; Datei schließen
CloseFile(File)

; Speicher für die RGB Daten reservieren
pData = CreateImage(uiWidth, uiHeight)
LockBuffer ImageBuffer(pData)

; Anzahl der Bits pro Pixel vergleichen
Select usBitsPerPixel
; 1 Bit pro Pixel
Case 1
If uiBMPBegin < 62 Then
FreeBank(pFileData)
If pColorData Then FreeBank(pColorData)
UnlockBuffer ImageBuffer(pData)
FreeImage(pData)
Return 0
End If

; Bitmapdaten in RGB Daten umwandeln
x = 0
y = uiHeight-1
For t = 0 To uiBitMapSize-1
For bits = 7 To 0 Step -1
Byte = PeekByte(pFileData, t)
Byte = (Byte Shr bits) And $01

B = PeekByte(pColorData, Byte*4)
G = PeekByte(pColorData, Byte*4+1)
R = PeekByte(pColorData, Byte*4+2)

WritePixelFast x, y, (R Shl 16) Or (G Shl 8) Or B, ImageBuffer(pData)
x = x + 1
If x = uiWidth Then
y = y - 1
x = 0
End If
Next
Next

; 4 Bit pro Pixel
Case 4
If uiBMPBegin < 118 Then
FreeBank(pFileData)
If pColorData Then FreeBank(pColorData)
UnlockBuffer ImageBuffer(pData)
FreeImage(pData)
Return 0
End If

; Bitmapdaten in RGB Daten umwandeln
x = 0
y = uiHeight-1
For t = 0 To uiBitMapSize-1
For bits = 1 To 0 Step -1
Byte = PeekByte(pFileData, t)
Byte = (Byte Shr bits*4) And $0F

B = PeekByte(pColorData, Byte*4)
G = PeekByte(pColorData, Byte*4+1)
R = PeekByte(pColorData, Byte*4+2)

WritePixelFast x, y, (R Shl 16) Or (G Shl 8) Or B, ImageBuffer(pData)
x = x + 1
If x = uiWidth Then
y = y - 1
x = 0
End If
Next
Next

; 8 Bit pro Pixel
Case 8
If uiBMPBegin < 1078 Then
FreeBank(pFileData)
If pColorData Then FreeBank(pColorData)
UnlockBuffer ImageBuffer(pData)
FreeImage(pData)
Return 0
End If

; Bitmapdaten in RGB Daten umwandeln
x = 0
y = uiHeight-1
For t = 0 To uiBitMapSize-1
Byte = PeekByte(pFileData, t)

B = PeekByte(pColorData, Byte*4)
G = PeekByte(pColorData, Byte*4+1)
R = PeekByte(pColorData, Byte*4+2)

WritePixelFast x, y, (R Shl 16) Or (G Shl 8) Or B, ImageBuffer(pData)
x = x + 1
If x = uiWidth Then
y = y - 1
x = 0
End If
Next

; 24 Bit pro Pixel
Case 24
; Bitmapdaten in RGB Daten umwandeln
x = 0
y = uiHeight-1
For i = 0 To uiBitMapSize-1 Step 3
B = PeekByte(pFileData, i)
G = PeekByte(pFileData, i+1)
R = PeekByte(pFileData, i+2)

WritePixelFast x, y, (R Shl 16) Or (G Shl 8) Or B, ImageBuffer(pData)
x = x + 1
If x = uiWidth Then
y = y - 1
x = 0
End If
Next
Default
FreeBank(pFileData)
If pColorData Then FreeBank(pColorData)
UnlockBuffer ImageBuffer(pData)
FreeImage(pData)
Return 0
End Select

; Datenspeicher freigeben
FreeBank(pFileData)
If pColorData Then FreeBank(pColorData)
UnlockBuffer ImageBuffer(pData)

Return pData
End Function
 

David

BeitragDi, Aug 10, 2004 0:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi!

Genau, das Bmp Format unterstützt das RLE Kompressionsverfahren, was tatsächlich eine Kompression ist, weshalb man es auch so nennen darf.
Das ganze ist recht simpel, die Farbwerte werden in Blöcken gespeichert, wobei alle gleichen Werte zu einem Block zusammen gefasst werden.

Hier mal ein Codeschnippsel aus meinem aktuellen Projekt.

BlitzBasic: [AUSKLAPPEN]

bool CBmpFile::ReadRLE_RGB( uint _uPixelCount, uint _uBytesPerPixel, ubyte **_pData )
{
uint l_uDataSize = _uPixelCount * _uBytesPerPixel;
*_pData = New ubyte[ l_uDataSize ];
ubyte *l_pTmp = *_pData;
ubyte b[ 4 ];
ubyte h = NULL;

While ( _uPixelCount > 0 )
{
fread( &h, sizeof( ubyte ), 1, m_pFile );

If ( h & 0x80 )
{
h &= 0x7f;
h++;
_uPixelCount -= h;

fread( b, _uBytesPerPixel, 1, m_pFile );

For ( ; h != 0; --h )
{
For ( Int i = 0; i < _uBytesPerPixel; ++i )
{
*l_pTmp++ = b[ i ];
}
}
}
Else
{
h++;
_uPixelCount -= h;

fread( l_pTmp, h * _uBytesPerPixel, 1, m_pFile );
l_pTmp += h * _uBytesPerPixel;
}
}

Return true;
}


Am Rande: mit einer Farbpalette hat das allerdings nichts zu tuen, aber es ist natürlich möglich BMP Dateien mit Palette zu speichern.

grüße
http://bl4ckd0g.funpic.de

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group