5 Stimmen

Bearbeiten von 8bpp indizierten Bitmaps

Ich versuche, die Pixel eines 8bpp zu bearbeiten. Da dies PixelFormat es indexed Ich weiß, dass es eine Farbtabelle verwendet, um die Pixelwerte zuzuordnen.

Auch wenn ich die Bitmap bearbeiten kann, indem ich sie in 24bpp konvertiere, ist die Bearbeitung mit 8bpp viel schneller (13ms gegenüber 3ms). Aber, jeden Wert zu ändern, wenn der Zugriff auf die 8bpp Bitmap Ergebnisse in einigen zufälligen RGB-Farben, obwohl das PixelFormat 8bpp bleibt.

Ich entwickle derzeit in C# und der Algorithmus ist wie folgt:

  1. Original-Bitmap mit 8bpp laden
  2. Empty temp Bitmap mit 8bpp mit der gleichen Größe wie das Original erstellen
  3. LockBits beider Bitmaps und, unter Verwendung von P/Invoke, Aufruf einer C++-Methode, bei der ich die Scan0 eines jeden BitmapData Objekt. (Ich habe eine C++-Methode verwendet, da sie beim Iterieren durch die Pixel der Bitmap eine bessere Leistung bietet)
  4. Erstellen einer int[256] Palette entsprechend einiger Parameter und bearbeiten Sie die temporären Bitmap-Bytes, indem Sie die Pixelwerte des Originals durch die Palette leiten.
  5. UnlockBits.

Meine Frage ist, wie kann ich die Pixelwerte bearbeiten, ohne die seltsamen RGB-Farben zu haben. Oder, noch besser, wie kann ich die 8bpp Bitmap Farbtabelle bearbeiten?

12voto

Dai Punkte 125973

Es gibt keine Notwendigkeit, in C++ Land zu bewegen oder P/Invoke überhaupt zu verwenden; C# unterstützt Zeiger und unsicheren Code völlig in Ordnung; Ich kann sogar eine Vermutung wagen, dass dies Ihre Probleme verursacht.

Die Farben stammen wahrscheinlich aus der Standardpalette. Sie werden feststellen, dass das Ändern der Palette überhaupt nicht langsam sein sollte. Dies ist, was ich tun, um eine Graustufenpalette zu erstellen:

image = new Bitmap( _size.Width, _size.Height, PixelFormat.Format8bppIndexed);
ColorPalette pal = image.Palette;
for(int i=0;i<=255;i++) {
    // create greyscale color table
    pal.Entries[i] = Color.FromArgb(i, i, i);
}
image.Palette = pal; // you need to re-set this property to force the new ColorPalette

4voto

Stellen Sie sich vor, dass Ihre indizierten 8ppp-Graysacle in einem linearen Array dataB gespeichert sind (aus Geschwindigkeitsgründen)

Probieren Sie diesen Code aus:

//Create 8bpp bitmap and look bitmap data
bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
bmp.SetResolution(horizontalResolution, verticalResolution);
bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);

//Create grayscale color table
ColorPalette palette = bmp.Palette;
for (int i = 0; i < 256; i++)
    palette.Entries[i] = Color.FromArgb(i, i, i);
bmp.Palette = palette;

//write data to bitmap
int dataCount = 0;
int stride = bmpData.Stride < 0 ? -bmpData.Stride : bmpData.Stride;
unsafe
{
    byte* row = (byte*)bmpData.Scan0;
    for (int f = 0; f < height; f++)
    {
        for (int w = 0; w < width; w++)
        {
            row[w] = (byte)Math.Min(255, Math.Max(0, dataB[dataCount]));
            dataCount++;
        }
        row += stride;
    }
}

//Unlock bitmap data
bmp.UnlockBits(bmpData);

0voto

Paul Ruane Punkte 35712

Haben Sie versucht, eine System.Drawing.Image stattdessen? Mit dieser Klasse haben Sie Zugriff auf die Farbpalette. Sie können dann die System.Drawing.Image auf als System.Drawing.Bitmap sobald die Palette eingestellt ist.

Ich bin nicht sicher, wie System.Drawing.BitMap.SetPixel() arbeitet mit indizierten Farbbildern. Es könnte sein, dass es versucht, die nächstgelegene Farbe in der Palette zuzuordnen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X