C#

[C#] Bitmap.LockBits 메서드

우준세 2023. 9. 25. 17:36
728x90
반응형

 

이번 포스팅은 제가 C#에서 영상처리 구현을 공부하면서 알게 된 Bitmap 클래스의 LockBits 메서드에 대해 작성하려 합니다. 이때까지 픽셀 단위 작업을 하며 GetPixel, SetPixel 메서드를 사용하며 작업했는데 속도면에서 LockBits 메서드가 더 빠르다는 것을 알았고 더욱 사용하게 되었습니다.

GetPixel, SetPixel에 대해 간단히 설명하고 LockBits 메서드에 대해 예제와 함께 정리하겠습니다.


| GetPixel 및 SetPixel 메서드 

- GetPixel과 SetPixel을 사용하면 이미지 데이터에 대한 직접적인 포인터 액세스를 하지 않아도 작업할 수 있으므로 코드가 더 안정적일 수 있습니다. 

- 하지만 GetPixel과 SetPixel 메서드는 비트맵 이미지의 픽셀 값을 조작할 때마다 메서드 호출이 발생하므로 이미지의 전체 픽셀을 다루게 되면 느리게 동작합니다. 


| LockBits 메서드란?

- LockBits 메서드는 비트맵 이미지의 픽셀 데이터에 접근하는 데 사용합니다. 비트맵의 픽셀 데이터에 대한 포인터를 얻어와서 해당 데이터를 직접 조작할 수 있습니다.

- 픽셀 데이터에 대한 포인터 작업을 하므로 대량의 이미지 데이터 처리 작업에 대한 속도가 빨라지며 효율적으로 처리할 수 있게 됩니다. 간단한 예시를 통해 LockBits 메서드 사용 방법에 대해 알아보겠습니다.

 

예시) 이미지를 반전시키는 작업 수행 코드 

// 비트맵 이미지 로드
using (Bitmap bmp = new Bitmap("input.jpg"))
{
    // 이미지를 잠금
    BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                                      ImageLockMode.ReadWrite,
                                      bmp.PixelFormat);

    // 픽셀 데이터에 접근
    unsafe
    {
        byte* ptr = (byte*)bmpData.Scan0;
        int bytesPerPixel = Image.GetPixelFormatSize(bmp.PixelFormat) / 8;

        for (int y = 0; y < bmp.Height; y++)
        {
            for (int x = 0; x < bmp.Width; x++)
            {
                // 각 픽셀을 조작
                for (int i = 0; i < bytesPerPixel; i++)
                {
                    ptr[i] = 255 - ptr[i]; // 픽셀 반전
                }
                ptr += bytesPerPixel; // 다음 픽셀로 이동
            }
             ptr += bmpData.Stride - (bmp.Width * bytesPerPixel); // Stride 처리
        }
    }

    // 이미지 잠금 해제
    bmp.UnlockBits(bmpData);

    // 변경된 이미지 저장
    bmp.Save("output.jpg");
}

- BitmapData 구조로 선언하여 bitmap.LoctBits로 이미지를 잠그고 포인터를 반환합니다.

- LockBits 메서드의 기본 형식은 다음과 같습니다.

public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)

- rect : 이미지에서 잠길 영역을 정의하는 사각형

- flags : 잠금 모드, ImageLockMode.ReadWrite 또는 ImageLockMode.ReadOnly 선택 

- format : 픽셀 형식을 나타내며, 주로 PixelFormat.Format24bppRgb 또는 PixelFormat.Format32bppArgb 사용

- 그리고 ptr 포인터를 얻고 픽셀 데이터에 접근하여 각 픽셀을 반전시킵니다. 반전시킨 후 ptr 포인터를 다음 픽셀로 이동하고 bmpData.Stride를 사용하여 각 행의 바이트 수를 처리합니다.

- Stride는 이미지 행 간 간격을 나타내며 각 행은 메모리에서 연속적으로 저장되지 않을 수 있으며 각 행의 데이터 길이를 나타냅니다.

- 마지막으로 Unlockbits를 통해 이미지 잠금을 해제하고 이미지를 저장합니다.


| 마치며

- Lockbits 메서드는 C#에서 이미지 처리를 위한 도구라는 것을 알게 되었고 고속처리를 위해서 꼭 필요한 기능이라는 것을 알게 되었습니다. 하지만 메모리 누수나 예외 처리에 조금 더 신경을 써야 할 것 같습니다. 

 

다음 포스팅으로 찾아오겠습니다.

 

감사합니다 :)

 

 

 

728x90
반응형