2016-08-05 51 views
2

Ich benutze eine benutzerdefinierte Klasse, um ein Bild auf ein anderes Bild von größerer Größe zu schreiben. Hier ist die vollständige source code in DotNetFiddle.Das Zeichnen einer Bitmap auf eine andere erzeugt ein verzerrtes Bild

Meine benutzerdefinierte GetPixel() funktioniert gut. Aber die folgende SetPixel() ist nicht in der Lage, die richtige Ausgabe zu produzieren. Wahrscheinlich gab es einige Probleme mit der Berechnung von Adressen. Aber ich kann es nicht erkennen.

public void SetPixel(int x, int y, Color color) 
    { 
     // Get color components count 
     int cCount = ColorDepth/8; 
     // Get start index of the specified pixel 
     int i = ((y * Width) + x) * cCount; 
     //int i = ((x * Width) + y) * cCount; 
     if (ColorDepth == 32) // For 32 bpp set Red, Green, Blue and Alpha 
     { 
      _imageData[i] = color.B; 
      _imageData[i + 1] = color.G; 
      _imageData[i + 2] = color.R; 
      _imageData[i + 3] = color.A; 
     } 

     if (ColorDepth == 24) // For 24 bpp set Red, Green and Blue 
     { 
      _imageData[i] = color.B; 
      _imageData[i + 1] = color.G; 
      _imageData[i + 2] = color.R; 
     } 
     if (ColorDepth == 8) 
     { 
      // For 8 bpp set color value (Red, Green and Blue values are the same) 
      _imageData[i] = color.B; 

      string str = string.Empty; 
     } 
    } 

Dies ist ein verzerrtes Bild zu erzeugen:

enter image description here

.

P.S. Hier ist das Eingangsbild:

enter image description here

.

.

+0

"Index außerhalb des Bereichs" ist der Schlüssel, den Sie erhalten. Es verweist auf _imageData [i] 'und hat nichts mit Get/Set-Pixeln zu tun, außer es gibt einen Fehler im Code. Da der Debugger bereits aktiv ist, nehmen Sie sich Zeit, um den Wert von "i" und die Größe von "_imageData" zu überprüfen. – user2864740

+0

Beachten Sie auch, dass '(x * Q) + y' nicht blind 'invertiert' werden kann als' (y * Q) + x' (sie ergeben einen anderen Bereich), wenn 'y! = X'. – user2864740

+0

Versuchen Sie Größe Bild mit beibehalten Seitenverhältnis: Überprüfung http://stackoverflow.com/questions/1940581/c-sharp-image-resizing-to-different-size-while-preserving-aspect-ratio –

Antwort

2
// Get start index of the specified pixel 
    int i = ((y * Width) + x) * cCount; 

Das ist nicht richtig, weder in GetPixel noch in SetPixel. Sie erhalten den Schräglauf, weil Sie Stride ignorieren. Welches sind die Anzahl der Bytes in einer einzelnen Scanzeile des Bildes? Es ist ein Vielfaches von 4 bis align die Pixeldaten im Speicher, hilft dem Prozessor, die Daten schneller zu lesen. Fix:

Es gibt einen weiteren Fehler, der in Ihrem Code versteckt ist, Scanlinien werden auf dem Kopf stehend gespeichert. Mit anderen Worten, die Daten für die letzte Abtastlinie werden zuerst gespeichert. Aber nur wenn BitmapData.Height nicht negativ ist. Da dieser Fehler sowohl in Ihrer GetPixel- als auch in Ihrer SetPixel-Methode auftritt, heben sie sich gegenseitig auf. Korrekter Code wäre (Höhe - y - 1) * Schritt + x * cCount.

Dieser Code ist nicht schneller als Graphics.DrawImage(), die Methode, die Sie immer bevorzugen sollten.

+0

Bitte verwenden Sie die bereitgestellten Informationen zu folge, dass du das Array nicht korrekt erstellt hast. Der gleiche Fehler, du verwendest jetzt wieder Breite anstelle von Stride. –

+0

Lieber Hans, siehe Link. Ich habe '(Höhe - y - 1) * Stride + x * cCount' benutzt. http://i.imgur.com/MBfMvVh.png – anonymous

+1

Nein, das Problem ist Ihr '_imageData' ** Array **, es muss natürlich Stride * Height Bytes enthalten, um die gesamte Bitmap zu speichern. Du machst es nicht groß genug. –