Bitmap Speicherverteilung bei nicht – alignter Breite in C#

Bitmap Speicherverteilung bei nicht – alignter Breite in C#

„Stride” ist ein Konzept aus alten Tagen, als es noch Geschwindigkeitsvorteile gab, wenn Daten 4-byte-aligned sind. Das verfolgt Programmierer noch bis heute.

Wenn man direkt das einer Bitmap zugrundeliegende Array beschreiben will, und Bilder mit einer Breite hat, die nicht ein Vielfaches von 4 ist, sieht man seltsame Effekte: Treppenbildung und allerlei seltsamer Artefakte.

Dies liegt daran, daß die Zeilenweite im Speicher nicht genau der Bytezahl entspricht, die man durch Multiplikation von Weite und Byte-pro-Pixel erhält.

Die tatsächliche Weite ist jedoch

int widthInBytes = (int)Math.Ceiling(width * 3 / 4.) * 4;

So läßt sich dann z. B. ein zusammenhängendes Array von Daten folgendermaßen in ein Array kopieren, das dann direkt mit Marshal.Copy in eine Bitmap kopiert werden kann:

1
2
for (int i = 0; i < height; ++i)
  Array.Copy(indata, i * width * 3, resdata, i * widthInBytes, widthInBytes);

und schließlich in eine Bitmap einbetten

1
2
3
4
5
6
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
Rectangle rectangle = new Rectangle(0, 0, widht, height);
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
IntPtr scan = bitmapData.Scan0;
Marshal.Copy(data, 0, scan, data.Length);
bitmap.UnlockBits(bitmapData);

Wichtig vielleicht noch, daß ich sage, daß all dies nur für 3-byte Daten gilt, also jeweils 8 Bit pro Farbe pro Pixel, ohne Alpha-Kanal, typisch als BGR im Speicher abgelegt (obwohl das Format Format24bppRgb heißt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.