Bitmap files und deren Aufbau
Nachdem ich bei meinem derzeitigen Projekt hier in Mexiko mit Bitmap-Files arbeiten muss, habe ich im Internet nach ein paar Informationen zum Aufbau des unkomprimierten BMP-Formats gesucht. Und anderem bin ich auch ziemlich oft auf folgende Methode gestoßen, um den Speicherplatzverbrauch eines Bitmaps zu errechnen:
BITMAPINFO bi;
// ...
bi.bmiHeader.biSizeImage = bi.bmiHeader.biWidth * (bi.bmiHeader.biBitCount >> 3) * bi.bmiHeader.biHeight
Erscheint eigentlich irgendwie logisch, oder?
biBitCount
ist die Auflösung des Bitmaps (meistens 24bit, also 3 Bytes, manchmal aber auf 32bit wobei dann das letzte Byte Reserved und somit immer 0 ist).
Dementsprechend habe ich meinen Zielpuffer auch gemalloc()
t und brav das Bild entsprechend hineingeschrieben, also einfach Zeile für Zeile die 24bit-Werte in den Buffer reingestopft.
Zu meiner großen Überraschung enthielt das geschriebene Bitmap immer einen scheußlichen Querstreifen mitten durchs Bild. Ich habe lange herumgegrübelt und getestet, um rauszufinden, woher der Streifen kommt…
Bis ich schließlich auf folgenden Microsoft-Artikel gestoßen bin, der mir endlich Klarheit verschafft hat: http://support.microsoft.com/kb/81498/en-us
Der springende Punkt ist, dass Bitmap-Scanlines DWORD-Aligned sind
Das bedeutet, man kann die Größe incht mit oben gezeigter Formel berechnen, so wie das viele Programmierer im Internet fälschlicherweise gemacht haben.
Stattdessen muss man die auf der M$-Seite angegebene Formel verwenden:
bi.bmiHeader.biSizeImage = ((((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount) + 31) & ~31) >> 3) * bi.bmiHeader.biHeight;
Außerdem sollte man darauf achten, dass man nicht vergisst, DeleteObject()
zu machen, nachdem man mit CreateCompatibleBitmap()
ein Bitmap angelegt hat.
Soweit zum Thema Bitmaps…