使用LockBits时AccessViolation [英] AccessViolation when using LockBits

查看:135
本文介绍了使用LockBits时AccessViolation的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想更多更快的比较类似的图像使用LockBits方法

I would like to compare the similar images more faster using LockBits method as follows

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

public class CompareImages {

 public static void Main ( String[] args ) {

 Bitmap bm1 = new Bitmap ( "PB270029.JPG" );  
 Console.WriteLine ( bm1.PixelFormat.ToString() );

 int width = bm1.Width;
 int height = bm1.Height;
 Console.WriteLine ( "width = " + width + "  height = " + height );

 Rectangle rect1 = new Rectangle ( 0, 0, width, height );
 BitmapData bm1Data = bm1.LockBits ( rect1, ImageLockMode.ReadOnly, bm1.PixelFormat );

 Console.WriteLine ( "stride = " + bm1Data.Stride );

 IntPtr bm1Ptr = bm1Data.Scan0;

 int bytes = Math.Abs(bm1Data.Stride) * height;
 Console.WriteLine ( "bytes = " + bytes );

 byte[] rgbValues1 = new byte [ bytes ];
 Marshal.Copy ( bm1Ptr, rgbValues1, 0, bytes );

 Console.WriteLine ( "After 1st Marshal.Copy ..." );

 Bitmap bm2 = new Bitmap ( "PA050164.JPG" ); 
 Rectangle rect2 = new Rectangle ( 0, 0, bm2.Width, bm2.Height );
 BitmapData bm2Data = bm2.LockBits ( rect2, ImageLockMode.ReadOnly, bm2.PixelFormat );

 IntPtr bm2Ptr = bm2Data.Scan0;
 byte[] rgbValues2 = new byte [ Math.Abs(bm2Data.Stride) * bm2.Height ];
 Marshal.Copy ( bm2Ptr, rgbValues2, 0, rgbValues2.Length );

 }

}



但在在发生第二Marshal.Copy的AccessViolationException:

but during the second Marshal.Copy the AccessViolationException is occurred:

C:\CompareImages>csc CompareImages.cs
Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1
Copyright (C) Microsoft Corporation. All rights reserved.


C:\CompareImages>CompareImages.exe
Format24bppRgb
width = 3648   height = 2736
stride = 10944
bytes = 29942784
After 1st Marshal.Copy ...

Unhandled Exception: System.AccessViolationException: Attempted to read or write
 protected memory. This is often an indication that other memory is corrupt.
   at System.Runtime.InteropServices.Marshal.CopyToManaged(IntPtr source, Object
 destination, Int32 startIndex, Int32 length)
   at CompareImages.Main(String[] args)

什么是错在我的计划?

感谢。

推荐答案

我一直在寻找到了几个小时了类似的问题,现在,我想我已经找到了可能是你的问题。我猜你的位图可能存储在稍有不同的格式。位图可以向前或向后存储。向后储存时步幅将是负面的。然而,SCAN0总是指向扫描的第一行,即第一像素不会第一个字节数组中

I've been looking into a similar issue for a few hours now, and I think I've found what might be your problem. I'm guessing your bitmaps might be stored in slightly different formats. Bitmaps can be stored either forwards or backwards. Stride will be negative when stored backwards. However, Scan0 will always point to the first line of the scan, ie, the first pixel NOT the first byte in the array.

因此,在一个向后扫描的位图,SCAN0 + ABS(步幅) - 1是阵列中的最后一个字节。 SCAN0 +步速将永远是第二行的开始,所以如果步幅是否定它的工作原理向后和积极向前会的工作。

Therefore, in a backwards scan bitmap, Scan0 + Abs(Stride) - 1 is the last byte in the array. Scan0 + Stride will always be the start of the second line, so if stride is negative it works backwards and positive will work forwards.

如果你这样做Marshal.Copy(bm2Ptr ,rgbValues2,0,rgbValues2.Length)为负的步伐,这将最后的扫描线进入访问冲突领土之前复制。下面的代码将任何位图转换成一个向后扫描的byte [](只是因为这是我与工作)。我猜你已经固定/现在工作圆你的问题,但希望这可以帮助别人。

If you do Marshal.Copy(bm2Ptr, rgbValues2, 0, rgbValues2.Length) with a negative stride, this will copy the last scanline before entering access violation territory. The following code will convert any bitmap into a backwards scan byte[] (just because that's what I was working with). I'm guessing you've fixed / worked round your problems by now, but hopefully this helps others.

    private byte[] BitmapToByteArray2(Bitmap bmp)
    {
        // Lock the bitmap's bits.  
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        System.Drawing.Imaging.BitmapData bmpData =
            bmp.LockBits(rect, ImageLockMode.ReadOnly,
            bmp.PixelFormat);

        int absStride = Math.Abs(bmpData.Stride);
        int bytes = absStride * bmp.Height;

        // Declare an array to hold the bytes of the bitmap.
        byte[] rgbValues = new byte[bytes];

        for (int i = 0; i < bmp.Height; i++)
        {
            IntPtr pointer = new IntPtr(bmpData.Scan0.ToInt32() + (bmpData.Stride * i));
            System.Runtime.InteropServices.Marshal.Copy(pointer, rgbValues, absStride * (bmp.Height - i - 1), absStride);
        }

        // Unlock the bits.
        bmp.UnlockBits(bmpData);

        return rgbValues;
    }

这篇关于使用LockBits时AccessViolation的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆