2017-05-11 13 views
2

Bitmap.LockBits에서 ImageLockMode의 목적은 무엇입니까? 화상의 일부를 판독하기위한 고정되도록 지정 읽기 전용 documentation 들어 만Bitmap.LockBits에서 ImageLockMode의 목적 (코드 포함)

는 읽기 전용 상태.

그러나 다음 코드는 이것이 사실이 아니라고 증명합니다. 질문은 이전에 물어 보았습니다. 이번에는 다른 곳에서는 답변을 찾을 수 없으므로 실제 코드로 시도합니다.

다음 코드를 실행하면 대답과 동일하게 동작합니다.

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

namespace LockBits_Trials 
{ 
    class Program 
    { 
     static readonly Random rnd = new Random(42); 
     static void Main(string[] args) 
     { 
     Bitmap bmp_fromFile = new Bitmap("example.png"); 
     Bitmap bmp_fromCtor = new Bitmap(100, 100, PixelFormat.Format24bppRgb); 
     marshalCopy(bmp_fromFile, "result_marshalCopy_fromFile.png"); 
     marshalCopy(bmp_fromCtor, "result_marshalCopy_fromCtor.png"); 
     usePointer(bmp_fromFile, "result_usePointer_fromFile.png"); 
     usePointer(bmp_fromCtor, "result_usePointer_fromCtor.png"); 
     } 

     private static unsafe void usePointer(Bitmap bmp, string filename) 
     { 
     ImageLockMode mode = ImageLockMode.ReadOnly; 
     //code from turgay at http://csharpexamples.com/fast-image-processing-c/ 
     if (bmp.PixelFormat != PixelFormat.Format24bppRgb) 
      throw new Exception(); 
     BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), mode, bmp.PixelFormat); 
     int bytesPerPixel = 3; int heightInPixels = bitmapData.Height; int widthInBytes = bitmapData.Width * bytesPerPixel; 
     byte* ptrFirstPixel = (byte*)bitmapData.Scan0; 
     for (int y = 0; y < heightInPixels; y++) { 
      byte* currentLine = ptrFirstPixel + (y * bitmapData.Stride); 
      for (int x = 0; x < widthInBytes; x = x + bytesPerPixel) { 
       currentLine[x] = (byte)rnd.Next(0, 255); 
       currentLine[x + 1] = (byte)rnd.Next(0, 255); 
       currentLine[x + 2] = (byte)rnd.Next(0, 255); 
      } 
     } 
     bmp.UnlockBits(bitmapData); 
     bmp.Save(filename, ImageFormat.Png); 
     } 

     private static unsafe void marshalCopy(Bitmap bmp, string filename) 
     { 
     ImageLockMode mode = ImageLockMode.ReadOnly; 
     if (bmp.PixelFormat != PixelFormat.Format24bppRgb) 
      throw new Exception(); 
     BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), mode, bmp.PixelFormat); 
     IntPtr ptrFirstPixel = bitmapData.Scan0; 
     int totalBytes = bitmapData.Stride * bitmapData.Height; 
     byte[] newData = new byte[totalBytes]; 
     for (int i = 0; i < totalBytes; i++) 
      newData[i] = (byte)rnd.Next(0, 255); 
     Marshal.Copy(newData, 0, ptrFirstPixel, newData.Length); 
     bmp.UnlockBits(bitmapData); 
     bmp.Save(filename, ImageFormat.Png); 
     } 
    } 
} 

사진result_marshalCopy_fromFile.png 및 result_usePointer_fromFile.png은 모두 원래의 이미지를 포함, 그래서 아무것도 덮어되지 않았다 (어떠한 예외가 발생하지 않습니다!). 다른 두 개의 그림에는 잠긴 상태에서 기록 된 임의의 잡음이 포함되어 있습니다.

필자는 어쨌든 병렬 쓰기 액세스의 동작을 확인하기 위해 테스트를 더 이상 수행하지 않았습니다.

은 중복 아니지만, 강력하게 관련 : 당신이 원시 데이터 포인터에 대한 액세스 권한을 얻은 후 Does Bitmap.LockBits “pin” a bitmap into memory?

+0

당신은 충분히 행복하지 못하며, 코덱을 사용하지 않아도됩니다. 비트 맵의 ​​픽셀 형식과 일치하지 않는 픽셀 형식을 의도적으로 요구함으로써 인생을 더 힘들게해야합니다. –

+0

@ 한자 Passant 나는 이해가 안되니? –

답변

1

것은 당신이 관찰 한 때, 그 메모리에 쓰기에서 당신을 막을 아무것도에 관계없이 없다 잠금 유형을 선택하십시오. 잠금 유형은 다음 두 상황에서 매우 유용합니다.

1) 코드 잠금 요청이 동시에 여러 번 발생하는 경우 읽기 잠금을 공유 할 수 있지만 한 번에 하나의 쓰기 잠금 만 허용됩니다. 이것은 물론 코드를 적절히 사용하여 잠금을 획득하는 코드에 달려 있습니다.

2) 모든 잠금이 비트 맵 메모리에 직접적으로 지원되는 것은 아닙니다. 예를 들어, 메모리 비트 맵을 작성한 다음 동일한 픽셀 형식으로 잠금을 요청했기 때문입니다. 그러나 비트 맵은 장치 컨텍스트가 소유 한 픽셀과 같은 다른 GDI + 개체를 나타낼 수 있습니다. 또한 원본 이외의 픽셀 형식을 요청하면 변환해야 할 수도 있습니다. 두 경우 모두에서 읽기 잠금이 요청되면 GDI +는 실제 원본에서 비트 맵 복사본을 가져 와서 요청한 픽셀 형식으로 제공해야 할 수 있습니다. 해당 복사본을 수정하려면 소스 컨텍스트에 다시 기록되지 않습니다. 쓰기 잠금을 요청한 경우 잠금을 해제하면 GDI +는 픽셀을 원본으로 다시 복사하는 것을 알고 있습니다.

+0

자세한 답변 해 주셔서 감사합니다. 나는 당신이 말한 것을 확인하고 이에 따라 나의 질문을 편집하는 몇 가지 테스트를 수행했습니다. 코드에 오류가 있는지 살펴볼 수 있습니까? 그것은 굉장 할 것입니다. –