잠금 해제 된 Bitmap 관리되지 않는 메모리에서 직접 쓰고 읽을 수 있습니까?Unlocked Bitmap 관리되지 않는 메모리 (Scan0)에 직접 읽고 씁니다.
비트 맵의 UnlockBits 이후에 BitmapData를 계속 사용할 수 있습니까? 나는 다른 스레드가 동일한 비트 맵에 픽셀을 쓰는 동안 마우스 위치에서 PictureBox의 비트 맵 픽셀을 읽을 수있는 테스트 응용 프로그램을 만들었습니다.
EDIT 1 Boing
로서 그의 대답 지적 "Scan0 비트 맵 객체의 실제 픽셀 데이터를 가리 키지 않으며, 오히려 화소 데이터의 부분을 대표하는 임시 버퍼를 가리키는 비트 맵 개체. " MSDN.
그러나 일단 Scan0을 얻으면 Lockbit 또는 UnlockBits가 필요없이 비트 맵을 읽고 쓸 수 있습니다! 나는 스레드에서 많은 시간을 보내고 있습니다. Scan0이 Bitmap 데이터의 COPY를 가리 키기 때문에 MSDN에 따라, 이런 일이 일어나서는 안됩니다! 글쎄, C#에서 모든 테스트는 복사본이 아니라는 것을 보여줍니다. C++에서는 그것이 제대로 작동하는지 모르겠습니다.
EDIT 2 : 회전 방법을 사용하면 OS가 비트 맵 픽셀 데이터 복사본을 해제하게됩니다. 결론, it is not safe to read/write an unlocked Bitmap Scan0
. 귀하의 답변과 의견을 주셔서 감사합니다!
다음은 BitmapData를 가져 와서 픽셀 값을 읽고 쓰는 방법입니다.
/// <summary>
/// Locks and unlocks the Bitmap to get the BitmapData.
/// </summary>
/// <param name="bmp">Bitmap</param>
/// <returns>BitmapData</returns>
public static BitmapData GetBitmapData(Bitmap bmp)
{
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
bmp.UnlockBits(bmpData);
return bmpData;
}
/// <summary>
/// Get pixel directly from unamanged pixel data based on the Scan0 pointer.
/// </summary>
/// <param name="bmpData">BitmapData of the Bitmap to get the pixel</param>
/// <param name="p">Pixel position</param>
/// <param name="channel">Channel</param>
/// <returns>Pixel value</returns>
public static byte GetPixel(BitmapData bmpData, Point p, int channel)
{
if ((p.X > bmpData.Width - 1) || (p.Y > bmpData.Height - 1))
throw new ArgumentException("GetPixel Point p is outside image bounds!");
int bitsPerPixel = ((int)bmpData.PixelFormat >> 8) & 0xFF;
int bpp = bitsPerPixel/8;
byte data;
int id = p.Y * bmpData.Stride + p.X * bpp;
unsafe
{
byte* pData = (byte*)bmpData.Scan0;
data = pData[id + channel];
}
return data;
}
//Non UI Thread
private void DrawtoBitmapLoop()
{
while (_drawBitmap)
{
_drawPoint = new Point(_drawPoint.X + 10, _drawPoint.Y + 10);
if (_drawPoint.X > _backImageData.Width - 20)
_drawPoint.X = 0;
if (_drawPoint.Y > _backImageData.Height - 20)
_drawPoint.Y = 0;
DrawToScan0(_backImageData, _drawPoint, 1);
Thread.Sleep(10);
}
}
private static void DrawToScan0(BitmapData bmpData, Point start, int channel = 0)
{
int x = start.X;
int y = start.Y;
int bitsPerPixel = ((int)bmpData.PixelFormat >> 8) & 0xFF;
int bpp = bitsPerPixel/8;
for (int i = 0; i < 10; i++)
{
unsafe
{
byte* p = (byte*)bmpData.Scan0;
int id = bmpData.Stride * y + channel + (x + i) * bpp;
p[id] = 255;
}
}
}
는, 그래,이 픽셀을 얻고 설정하는 매우 빠른 방법입니다,하지만 당신은'GetPixel'를 사용하여 작은 이미지 (* 500 <500), 작업하는 경우 'SetPixel'은 훨씬 쉬울 것입니다. – Mehran
@Mehran, 제 편집과 Boings 대답을보세요. 내가 잠겨 있지 않은 비트 맵을 읽고 쓰고 있다는 것을 알고 있니? 따라서 MSDN에 따라 이것이 작동해서는 안됩니다. – Pedro77
나는 당신이 말한 것을 시도했지만, 비트 잠금을 풀지 않고서는 제 'picturebox'와 흰색 바탕에 흰색 바탕에 적십자가 있습니다! , 당신은 이미 언급했듯이 이것이 효과가 없어야하지만, 나는 그것이 당신의 경우에 왜하는지 잘 모른다! – Mehran