ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Silverlight3 - WriteableBitmap
    Silverlight 2009. 6. 25. 23:26

    안녕하세요. 승미입니다. 오랜만에 글을 쓰네요.

     

    오늘은 Silverlight 3의 WritableBitmap에 대해서 알아보도록 하겠습니다.

     

    들어가기에 앞서..

    Silverlight 2에서 반사(Reflection) 효과를 표현하고 싶을 때는 XAML에 중복된 디자인을 넣어야 했습니다. 왜냐하면 2에서는 Control의 모양을 복사할 수 있는 API가 전혀 제공되지 않았기 때문이죠. Silverlight 3에서는 이러한 부분을 보완하기 위해 Control의 모양을 그대로 복사할 수 있는 WriteableBitmap API가 추가되었습니다. 쉽게 말해서 현재 Control의 모양을 Capture하는 기능을 합니다. 또한 WritableBitmap은 영상 처리를 위해 이미지를 Pixel 단위로 처리할 수 있는 기능을 제공합니다. 이제 이미지의 각 Pixel을 가져와 이미지 확대, 축소, Blur, Gaussian effect 등을 직접 구현해서 적용할 수 있게 된 것입니다.

    다시 정리하자면 WritableBitmap은 다음과 같이 2가지 기능을 제공합니다.

     

       - Control의 현재 모습을 Capture
       - 이미지를 Pixel 단위로 처리할 수 있도록 지원

     

    이번 글에서 위 2가지 특징을 살펴보겠습니다.

     

     

    예제 프로젝트 다운로드

     다운로드

     

     

    WriteableBitmap 클래스 구조

    먼저 WriteableBitmap에서 지원하는 기능을 알아보기 전에 WriteableBitmap이 어떤 구조를 가지고 있는지 살펴보겠습니다.

     

    image

     

    상단의 그림은 WriteableBitmap의 클래스 구조를 보여줍니다. 먼저 BitmapSource를 부모로 상속하고 있으며 BitmapSource는 ImageSource를 부모로 상속하고 있습니다. 여기서 ImageSource는 Image Control의 Source(이미지 주소) 프로퍼티에 할당되는 값임을 알 수 있습니다. 다시 말해, WriteableBitmap 인스턴스를 생성해 Capture나 픽셀을 조작한 후 Image Control의 Source에 넣어주기만 하면 화면에 출력되는 것입니다.

     

    image

     

     

    Render 메서드 사용하기

    다음으로 Control의 Capture 기능을 제공하는 Render 메서드를 알아보도록 하겠습니다.

     

    image

     

    위 그림은 Render 메서드의 원형을 보여줍니다. 첫 번째 인자는 Capture할 대상 Control 입니다. 그리고 두 번째 인자는 Capture한 내용을 Transform 시키고자 할 경우 사용합니다. 즉, Capture한 화면이 너무 크면 ScaleTransform을 이용해 화면 크기를 축소할 때 사용하는 것이 한 예가 될 수 있겠습니다.

     

    그럼 현재 재생되는 동영상을 Capture하는 간단한 프로그램을 제작해보겠습니다.

    먼저 동영상을 재생할 수 있는 XAML을 만듭니다.

     

     image

     image

     

    위 2개의 화면은 간단히 제작한 동영상 재생 프로그램의 디자인과 XAML을 보여줍니다. 크게 3가지 영역으로 나뉘어 있습니다. Capture 버튼을 클릭하게 되면 현재 재생되는 동영상을 Capture해 Capture 저장 구역에 추가되는 방식으로 작동합니다.

    이제 Render 메서드를 이용해 실제로 Capture하는 코드를 살펴보도록 하겠습니다.

     image

     

    위 화면은 Capture를 수행하는 코드를 보여줍니다. 각 코드 영역의 설명은 다음과 같습니다.

     

    1. 먼저 CaptureButton이 클릭됐을 때 CaptureButton_Click 메서드가 호출되도록 이벤트를 설정합니다.

     

    2. WriteableBitmap을 생성합니다. WriteableBitmap은 생성자의 인자로 총 3개가 필요하며 각각 넓이, 높이, 픽셀 포맷을 인자로 받습니다. 여기서는 MediaElement(MyMediaElement)를 Capture하기 위해 MediaElement의 크기를 인자로 주었습니다.

     

    3. 현재 화면에 보이는 MediaElement를 Capture 하기 위해 Render 메서드를 호출합니다. Render 메서드는 앞서 살펴본 것처럼 첫 번째 인자로 Capture할 Control을 받습니다. 여기서는 MediaElement(MyMediaElement)를 인자로 주었습니다. 2번째 인자는 적용할 Transform을 입력하는 부분으로 여기서는 일반 ScaleTransform()을 인자로 주었습니다. 즉, Transform을 수행하지 않겠다는 의미입니다.

     

    4. 이제 Capture한 내용을 화면에 출력하기 위해 Image control을 생성합니다. 그리고 Source 프로퍼티에 앞서 생성한 WriteableBitmap을 할당합니다.

     

    5. 마지막으로, 생성된 Image control을 “Capture 저장 구역”인 StackPanel에 추가합니다.

     

    위 예제 프로그램은 다음과 같습니다.

     

    이상으로 간단하게 Control을 Capture하는 방법에 대해서 알아봤습니다. 여기서는 MediaElement를 Capture했지만 Grid나 Button등 다양한 Control들도 Capture를 할 수 있습니다. 가능하시면 첨부파일의 프로젝트를 실행시켜 직접 실행시켜보시기 바랍니다.

     

     

    Pixel Data 사용하기

    WriteableBitmap을 이용하면 Pixel 하나 하나를 직접 조작할 수 있으며 이를 이용해 다양한 영상 처리 효과를 적용할 수 있습니다.

     

    image

     

    위 화면은 WriteableBitmap을 Pixel 단위로 조작하는 것을 보여줍니다. 먼저 100x100 크기의 빈 WriteableBitmap을 생성합니다. 그리고 Bitmap의 Pixel을 조절하기 위해 Lock 메서드를 호출해 외부에서의 변경을 방지합니다. 이렇게 설정한 후 배열 Index를 이용해 각 Pixel에 접근할 수 있습니다. 즉, 100x100 크기의 Pixel을 배열 Index를 통해 하나 하나 접근할 수 있는 것입니다. 이 부분의 자세한 예제는 링크를 참고하시기 바랍니다.

     

     

    Pixel Data의 문제점

    WriteableBitmap을 이용해 각 Pixel을 제어하는 방법을 알아봤습니다. 하지만 빈 화면부터 시작하는 법만 알아봤을 뿐 실제 이미지를 기반으로 제어하는 방법은 알아보지 않았습니다.

     

    image

     

    위 화면은 기존의 이미지를 기반으로 WriteableBitmap을 생성해 각 Pixel을 제어하는 코드를 보여줍니다. WriteableBitmap은 앞서 살펴본 것처럼 빈 화면에서 시작할 수도 있고 위 화면처럼 기존 이미지(BitmapSource)를 생성자의 인자로 줌으로써 기존 이미지를 기반으로 시작할 수 있습니다.

     

    하지만..

    image

     

    현재 Beta 버전에서는 기존 이미지로 생성된 WriteableBitmap을 배열에 접근하는 순간 위와 같이 NullPointerException을 발생합니다. 정식 버전에서는 수정될 것으로 예상됩니다.

     

     

    마치며..

    이상으로 WriteableBitmap에 대해서 간단히 알아봤습니다. Silverlight 2에서는 처리할 수 없었던 Capture가 가능하게 됨으로써  흥미롭게 응용될 수 있는 부분이라고 생각합니다. 또한 Pixel 하나 하나를 제어할 수 있게 됨으로써 영상처리 분야와도 결합되어 사용될 수 있을 것으로 예상됩니다.

Designed by Tistory.