Frage

Ich habe einen Speicherpuffer zu meiner Bildschirmauflösung (1280x800 bei 24 Bit pro Pixel) entspricht, die meinen Bildschirminhalt auf 24 bpp enthält. Ich möchte das 8-bpp konvertieren (dh. Halbton-Farbpalette in Windows). Ich tue dies derzeit: 1. Verwendung CreateDIBSection neuen 1280x800 24-bpp-Puffer und darauf zuzugreifen als DC, sowie ein einfacher Speicherpuffer zuzuzuweisen 2. Verwenden Sie Memcpy von meinen ursprünglichen Puffern zu diesem neuen Puffer aus Schritt 1 kopieren 3. Verwenden Sie BitBlt lassen GDI die Farbumwandlung durchführen

Ich mag 2. die zusätzliche Memcpy von Schritt zu vermeiden, dies zu tun, kann ich zwei Ansätze denken:

a. Wickeln Sie meinen ursprünglichen mem buf in einem DC BitBlt auszuführen direkt von ihm

b. Schreiben meiner eigenen 24-bpp bis 8-bpp Farbkonvertierung. Ich kann keine Informationen finden, wie Windows-implementiert diese Halbton-Farbkonvertierung. Außerdem, selbst wenn ich herausfinden, werde ich nicht die beschleunigten Funktionen von GDI verwenden, dass BitBlt Zugriff hat.

Wie kann ich tun, entweder (a) oder (b)?

Danke!

War es hilfreich?

Lösung

OK, um die beiden Teile des Problems zu lösen.

  1. Der folgende Code zeigt, wie innerhalb einer Bitmap an den Pixeln erhalten, so dass sie und sie ändern in die Bitmap zurückstellen. Man kann immer einen Dummy-Bitmap, die richtigen Größe und das Format erzeugen, öffnen Sie es, kopieren Sie Ihre Daten und Sie dann ein Bitmap-Objekt mit Ihren Daten haben:

    private void LockUnlockBitsExample(PaintEventArgs e)
    {
    
       // Create a new bitmap.
       Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");
    
       // Lock the bitmap's bits.  
       Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
       System.Drawing.Imaging.BitmapData bmpData =
             bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
             bmp.PixelFormat);
    
       // Get the address of the first line.
       IntPtr ptr = bmpData.Scan0;
    
       // Declare an array to hold the bytes of the bitmap.
       int bytes  = bmpData.Stride * bmp.Height;
       byte[] rgbValues = new byte[bytes];
    
       // Copy the RGB values into the array.
       System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
    
       // Set every third value to 255. A 24bpp bitmap will look red.  
       for (int counter = 2; counter < rgbValues.Length; counter += 3)
           rgbValues[counter] = 255;
    
       // Copy the RGB values back to the bitmap
       System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
    
       // Unlock the bits.
       bmp.UnlockBits(bmpData);
    
       // Draw the modified image.
       e.Graphics.DrawImage(bmp, 0, 150);
    }
    

Um den Inhalt zu konvertieren 8bpp Sie die System.Drawing.Imaging.ColorMatrix-Klasse verwendet werden sollen. Ich habe nicht die richtigen Matrixwerte für Raste bei der Hand, aber dieses Beispiel Graustufen und die Einstellung der Werte sollen Ihnen eine Vorstellung von der Wirkung geben:

Graphics g = e.Graphics;
Bitmap bmp = new Bitmap("sample.jpg");
g.FillRectangle(Brushes.White, this.ClientRectangle);

// Create a color matrix
// The value 0.6 in row 4, column 4 specifies the alpha value
float[][] matrixItems = {
                            new float[] {1, 0, 0, 0, 0},
                            new float[] {0, 1, 0, 0, 0},
                            new float[] {0, 0, 1, 0, 0},
                            new float[] {0, 0, 0, 0.6f, 0}, 
                            new float[] {0, 0, 0, 0, 1}};
ColorMatrix colorMatrix = new ColorMatrix(matrixItems);

// Create an ImageAttributes object and set its color matrix
ImageAttributes imageAtt = new ImageAttributes();
imageAtt.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

// Now draw the semitransparent bitmap image.
g.DrawImage(bmp, this.ClientRectangle, 0.0f, 0.0f, bmp.Width, bmp.Height, 
            GraphicsUnit.Pixel, imageAtt);

imageAtt.Dispose();

Ich werde versuchen, und später mit dem Matrixwert für Rasten aktualisiere, ist es wahrscheinlich eine Menge von 0,5 oder 0,333 Werten dort sein!

Andere Tipps

Verwenden CreateDIBitmap statt CreateDIBSection.

Wenn Sie die Kopie (Schritt 2) beseitigen wollen, nur CreateDIBSection verwenden Original-Speicherpuffer in dem ersten Platz zu schaffen. Dann können Sie einfach eine kompatible DC für die Bitmap erstellen und als Quelle für die BitBlt Betrieb verwenden.

d. es gibt keine Notwendigkeit, den Speicher von einem „plain Speicher“ Puffer zu einem CreateDIBSection Bitmap vor Blitten wenn Sie einen CreateDIBSection Bitmap anstelle einem „plain Speicher“ Puffer in dem ersten Platz.

zu kopieren

Immerhin zugewiesen ein Puffer CreateDIBSection ist im Wesentlichen nur ein „einfacher Speicher“ Puffer das ist kompatibel mit CreateCompatibleDC, das ist das, was Sie suchen.

Wie hast du den Bildschirminhalt in diesen 24bpp Speicherpuffer in erster Linie?

Der offensichtliche Weg eine Unnötig Memcpy zu vermeiden, ist durch die Schaffung der 24 bpp DIBSection zuerst das ursprüngliche screen zu unterlaufen, und an die Funktion als screenZielPuffer übergeben.

Wenn das ist nicht möglich, können Sie immer noch GDI versuchen und zwingen in die harte Hebe tun, indem ein BITMAP Erstellen Sie das Format des Speicherpuffers beschreiben, und nur StretchDIBits nennen es blitten auf Ihren 8bpp DIBSection.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top