2011-01-05 5 views
0

Ich extrahiere Reihen von Pixeln aus einem Bild in ein Array von int mit Marshal.Copy. Alles funktioniert gut, bis ich die letzte Zeile des Bildes erreiche. Wenn ich versuche, es zu extrahieren, erhalte ich eine nette Ausnahme:System.AccessViolationException beim Versuch, die letzte Zeile eines Bitmap-Bilds zu kopieren

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 

Hier ist ein kleiner Testfall, der den Fehler reproduziert. Was mache ich falsch ?

[Test] 
public void testMarshalCopy() { 
    Bitmap image = new Bitmap("../../TestResources/barcode.jpg"); 

    int left = 0; 
    int top = image.Height - 1; 
    int width = image.Width; 
    int height = 1; 

    Rectangle zone = new Rectangle(left, top, width, height); 
    BitmapData data = image.LockBits(zone, System.Drawing.Imaging.ImageLockMode.ReadOnly, image.PixelFormat); 

    IntPtr pointer = data.Scan0; 
    int[] pixels = new int[width * height]; 

    Marshal.Copy(pointer, pixels, 0, pixels.Length); // throws System.AccessViolationException 

    image.UnlockBits(data); 
} 
+0

Was ist Ihr Bildpixelformat? Ist jedes Pixel == 'sizeof (int)'? – heavyd

+1

Fwiw, das ist die erste Zeile. Bitmaps werden auf dem Kopf stehend gespeichert. –

+0

@Hans: Danke für die Information! – Wookai

Antwort

1

Das Bild I war Lade Format24bppRgb als Pixelformat wurde mit. Wie Hans sagte, ermöglicht die Arbeit mit Format32bppRgb, direkt mit int[] statt byte[] zu arbeiten.

Ich habe das Pixelformat auf Format32bppRgb geändert und jetzt funktioniert es!

+0

Normalerweise markieren Sie eine Antwort und lassen Sie einen Kommentar lieber dann eine andere Antwort verlassen. – asawyer

+2

Ich denke, ich weiß, wie SO funktioniert ... Es gab keine Antwort, die das sagte, nur ein Kommentar, also um es sichtbar zu machen, habe ich es als Antwort gepostet. – Wookai

2

Sie berücksichtigen beim Kopieren nicht Ihr Pixelformat.

Blick auf dieses Beispiel:

http://msdn.microsoft.com/en-us/library/ms229672(v=vs.80).aspx

bemerken sie einen Puffer von Breite fertig werden * height * 3.

das Bild in diesem Beispiel ist das RGB-Format, ein Byte pro Farbkanal.

Sehen Sie diese Linie hier in der Nähe von oben:

PixelFormat pxf = PixelFormat.Format24bppRgb; 

One mehr bearbeiten -

Sie ihre Aufmerksamkeit auch auf die Stride Wert zahlen sollte Bitmap.

http://msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.stride.aspx

+1

Ja. Verwenden Sie jedoch Format32bppRgb so int [] ist noch verwendbar. 24bpp ist schwer zu bewältigen. Schritt ist hier nicht wichtig. –

+0

Ich stimme zu, es genau so im msdn Beispiel und das Verständnis des Konzepts von Bitmap Schritt kann nützlich sein, um das Plakat, so dass ich es warf. – asawyer

1

Die Anzahl des Bytes in der gesperrten Bitmap-Zone hängt von dem Bildformat, versucht, mehr Bytes zu extrahieren wird eine Ausnahme werfen. Um die Sache zu vereinfachen, können Sie ein Byte-Array verwenden, das mit jedem Bildformat funktioniert, aber Sie müssen den Multiplikator anpassen - das folgende Beispiel geht von einem 3-Byte- (24-Bit-) Bildformat aus.

 int bytesNeeded = zone.Width * zone.Height * 3; 
     byte[] pixels = new byte[bytesNeeded]; 

     Marshal.Copy(pointer, pixels, 0, pixels.Length); 
     image.UnlockBits(data); 
Verwandte Themen