2014-09-08 8 views
3

C#에서 랩핑 된 C 라이브러리를 사용 중이므로 해당 라이브러리의 이미지를 비트 맵으로 변환 한 후 다시 변환해야하지만, 픽셀 버퍼를 복사하지 않고 이 아닙니다. 비트 맵으로 변환IntPtr이 관리되는 메모리 또는 관리되지 않는 메모리를 가리키는 지 확인합니다.

는 간단했다

Bitmap WrapAsBitmap(CImage image) 
{ 
    return new Bitmap(image.Width, image.Height, image.BytesPerLine, PixelFormat.Format24bppRgb, image.Data); 
} 

단지 Bitmap 생성자 원래 픽셀 버퍼 (image.Data)에 전달하여이 카피가 필요하지 않다. 반대를하고, 나는 원래 픽셀 버퍼의 IntPtr에 액세스하려면 LockBitsUnlockBits를 호출해야 : 당신이 볼 수있는 data.Scan0 관리 메모리에있는 경우,

CImage WrapAsCImage(Bitmap bitmap) 
{ 
    BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat); 
    var image = new CImage(bitmap.Width, bitmap.Height, data.Stride * 3, data.Scan0); 
    bitmap.UnlockBits(data); 
    return image; 
} 

이제,이 실제로 위험하다 새롭게 구성된 image이 사용되기 전에 비트가 '잠금 해제 됨'으로 접근합니다. WrapAsBitmap 메서드에서 bitmap을 만든 경우 data.Scan0은 관리되지 않는 메모리를 가리키며 .NET에서 이동하지 않으므로 아무런 문제가 없습니다. 따라서 data.Scan0 포인터의 위치 (관리/비 관리)를 확인하는 안전성 검사를 구축하고 싶습니다.

내가 생각 된 다른 솔루션은 Bitmap 클래스에서 상속과 Bitmap와 함께 원래의 포인터 image.Data를 추적 할 수 있었다, 그러나 Bitmap 클래스는 밀봉, 그래서 나는 운입니다.

요약 :IntPtr의 위치 (관리되는/관리되지 않는)를 감지하는 방법은 무엇입니까?

+0

여기에 'CImage'란 무엇입니까? –

+0

C 라이브러리에서 오는 이미지를 래핑하는 래퍼 클래스입니다. 이 클래스의 유일한 관련 멤버는'WrapAsBitmap' 메서드에 표시됩니다. –

+0

그것은 가능할 것입니다 (잘 모르겠습니다). 여기에 또 다른 문제가 있습니다. CImage -> WrapAsBitmap -> WrapAsCImage -> CImage, 이제 두 개 있습니다. 동일한 메모리를 가리키는 CImage 인스턴스. 어쩌면 당신은 WrapAsCImage에서 메모리를 복사해야합니까? –

답변

5

IntPtr이 관리되는 메모리를 가리키는 시나리오는 없습니다. 물론 이미지 데이터가 C 코드로 생성 된 경우는 아닙니다. Bitmap에서 생성 된 경우도 GDI +는 비 관리 코드입니다. 당신은 스스로 이것을 통해 추론 할 수 있습니다, 당신은 단지 그것을 관리하여 관리되는 메모리를위한 IntPtr을 얻을 수 있습니다. GCHandle.AddrOfPinnedObject(). 가비지 수집기가 힙을 압축 할 때 포인터를 무효화하지 못하도록하는 어려운 요구 사항. 문서화 된 핀이 필요없는 곳은 어디에도 없습니다.

테스트 구현에 아무런 의미가 없습니다.

은 비트 맵 래퍼의 유효 기간 동안 해당 IntPtr을 유효하게 유지해야합니다. Dispose() 메소드를 호출하는 지점까지. IDisposable 자체를 구현하는 클래스에서 Bitmap 객체를 캡슐화하는 것 이외에는이 자동 연산을 만들 수 없습니다. 그렇게하지 않으면 잘못 행동하는 경우가 발생합니다. 운이 좋으면 AccessViolationException 만 발생합니다. 무작위 픽셀 내용이 포함 된 손상된 비트 맵은 일반적인 오류 모드입니다.

보증을 구현할 수없는 경우 이 아니고이 아니라 비트 맵 데이터를 복사해야합니다.구현하기가 어렵지 않습니다.

0

Bitmap 클래스는 실제로 GDI + Bitmap 개체에 대한 관리되는 래퍼입니다. 객체는 사용자 코드에 노출 된 고정 버퍼에서 작동하지 않으며 해당 버퍼가 특정 형식으로 보장되지 않기 때문에 설명 된 작업을 수행 할 수 없습니다.

즉, 문제 공간을 요청한 것과 관계없이 버퍼 복사가 필요한 경우가 분명합니다.

+0

흠, 나는 생각하지 않는다. [constructor] (http://msdn.microsoft.com/en-us/library/zy1a2d14 (v = .110) .aspx) 및 remark : 호출자는 scan0 매개 변수로 지정된 메모리 블록 할당 및 해제를 담당합니다. 그러나 관련 Bitmap이 릴리스 될 때까지 메모리를 해제해서는 안됩니다. –

+0

@WouterHuysentruit 사용하는 기본 GDI + 메서드에 대한 설명서를 버퍼를 복사 할 제안합니다. http://msdn.microsoft.com/en-us/library/ms536315.aspx –