'BitmapSource'에 해당되는 글 2건

  1. 2013.01.03 Access BitmapSource Pixel Data (WIC Image Hack)
  2. 2010.02.28 Visual To BitmapSource Using RenderTargetBitmap (1)

Introduction 

WPF에서 파일로부터 불러온 이미지의 픽셀데이터에 접근하고자 할 경우 아래와 같이 CopyPixels를 통해 이미지에 포함된 픽셀 값들을 복사하는 방법을 사용합니다. CopyPixels는 이름에서도 알 수 있듯이 이미지에 있는 픽셀데이터를 복사하는데요, 이 때문에 데이터의 용도가 단순한 읽기 전용이거나 업데이트를 위한 용도일 경우에는 불필요한 메모리와 퍼포먼스를 요구하게 되므로 효율적이지 못합니다.

MSDN에서는 픽셀데이터에 접근하기 위한 또다른 방법으로 WriteableBitmap을 이야기하는데 WriteableBitmap 또한 내부적으로는 CopyPixels를 사용하기 때문에 큰 효율은 얻을 수 없습니다.)

이번시간에는 WPF내부적으로 사용되고 있는 Image Framework인 WIC(Windows Image Component)에 직접 Access하여 보다 효과적으로 픽셀데이터에 접근하는 방법에 대해 소개합니다. 아래 동영상은 WIC를 이용했을 때와 CopyPixels를 이용했을 때의 비교영상입니다.

위 테스트에서 사용된 코드는 첨부파일을 다운로드 하시면 확인 하실 수 있습니다.

Windows Image Component

앞서 말씀드린 것과 같이 WPF에서는 내부적으로 WIC를 이용해 이미지를 관리합니다. 즉 Native Code로 작성된 WIC API를 Managed Code로 Wrapping하여 제공하는건데요. 이때 Native Code에서 생성된 이미지 데이터를 Managed Code에서 무분별하게 Access할 경우 발생할 수 있는 메모리 관련 이슈들을 사전에 방지하고자 직접적인 Access를 허용하지 않고 Copy 관련 메서드만 제공하는것으로 보입니다.

※ .Net Reflector등의 툴로 BitmapSource객체를 열어보시면 아래와같이 내부적으로 WIC 이미지를 가지고 있는것을 확인 하실 수 있습니다.

_wicSource라는 이름으로 WIC객체가 저장되어 있는것을 확인하실 수 있습니다. wicSource는 Internal로 정의되어있기 때문에 Reflection을 통해 WIC객체 포인터에 Access하고 WIC API를 이용해 Native Code상에서 생성된 이미지 데이터에 접근하시면됩니다.

WIC에 대한 자세한 내용은 여기(http://msdn.microsoft.com/ko-kr/library/windows/desktop/ee719654.aspx)서 확인 할 수 있습니다.

Create WICBitmapBuffer

WIC를 이용해 픽셀 데이터를 접근하기 위해 필요한 API들과 Native객체 생성과 파괴를 관리 할 수 있도록 임의의 WICBitmapBuffer를 아래와 같이 사용하면 더 쉽게 사용할 수 있습니다.

위 코드를 사용할 때에는 아래와 같이 사용합니다. WICBitmapBuffer.Create 메서드에 BitmapSource객체를 넣고 Buffer에 접근하시면 됩니다.

이상으로 이번 포스팅을 마치며 영상에서 사용된 전체 소스코드는 아래에서 다운로드 받으시면됩니다. 기타 질문이나 문의사항은 댓글이나 이메일 주시면 답변드리도록 하겠습니다. 감사합니다.

WIT.WPF.BitmapExtensionExample.zip

 

신고

Introduction

WPF Application을 개발하다보면 현재 화면에 출력되고 있는 Visual객체나 임의로 생성한 Visual 객체를 Image로 변환 해야하는 경우가 있습니다. 이번 강좌에서는 RenderTargetBitmap을 이용해 Visual 객체를 Image로 변환하는 방법에 대해 소개합니다.

What is RenderTargetBitmap?

RenderTargetBitmap은 WPF상의 Visual객체를 Bimap으로 변환 해주는 클래스로, 제공되는 Render메서드를 통해 Visual 객체를 Bitmap으로 변환 할 수 있습니다. Render메서드를 호출하게 되면 입력한 Visual의 Measure와 Arrange를 수행한 결과를 바탕으로 생성된 Bitmap영역에 Visual을 렌더링 하게됩니다. RenderTargetBitmap은 생성자로 생성할 Bitmap의 Width, Height, DpiX, DpiY, PixelFormat을 파라미터로 전달받으며, 기본적인 사용법은 아래와 같습니다. 아래 코드는 파라미터로 전달받은 Visual객체를 BitmapSource로 변환 하는 함수입니다.

Some Problems in RenderTargetBitmap

Flexible Size

RenderTargetBitmap은 입력받은 Visual객체를 Bitmap형식으로 변환되기 때문에 Bitmap으로 저장될때의 크기가 정확하게 지정되어야 합니다. 위 코드에서는 크기를 지정하기 위해 객체의 Width와 Height속성을 이용했는데, WPF의 Layout 구조상 렌더링 타임에 크기가 측정되는경우 Width, Height속성이 실제 렌더링 결과와 차이가 있을 수 있습니다.  이를 보안하기 위해 객체의 렌더링시 크기를 가져오는 ActualWidth, ActualHeight속성을 이용 할 수 있습니다.

Non-Parent / Pre-Measure

위에서 언급한 ActualWidth, ActualHeight는 VisualTree에서 수행하는 크기 측정과정을 통해 측정된 결과를 반환 하기 때문에, 부모가 없는 Visual이거나 한번도 측정을 수행하지 않은 경우에는 항상 0을 반환하게 됩니다. 크기가 0일경우 렌더링시 아무것도 내용도 출력되지 않기 때문에 원하는 결과를 얻을 수 없습니다. 이경우 직접 측정을 수행하도록 Arrange 메서드를 호출하는 방법으로 해결 할 수 있습니다.

Transform Size

ActualWidth나 ActualHeight는 Transform을 고려하지 않은 실제 Visual의 크기를 반환 합니다. 때문에 Transform이 적용된 객체의 경우 원하는 결과와 다르게 동작하게 됩니다. 이 경우 Transform객체의 TransformBounds메서드를 통해 Transform이 적용된 영역을 계산 할 수 있습니다. 아래 코드는 위에서 언급한 몇가지 문제점을 개선한 코드입니다.

위 코드를 사용할 때는 다음과 같이 이용할 수 있습니다.

신고