Window/WPF2010. 1. 24. 10:14

이미지의 픽셀 값을 얻어 오기 위해서는 Bitmap으로 불러 들어와 GetPixel 함수를 호출하는 방법도 있지만

BitmapSource를 이용해 얻어오는 방법에 대해 InkCanvas를 사용해 다음과 같은 간단한 예제를 만들어 보았습니다.

 

        

 

소스는 매우 간략하기 때문에 이해가 쉬울 겁니다.

중요한 부분은 픽셀 포맷에 따라 Stride의 값을 달리하여 읽어 들어와야 하는 부분입니다.

 

비트맵의 Stride는 픽셀 데이타의 한 행의 폭으로 바이트 수를 나타냅니다.

이미지 포맷에 따라 오프셋을 구하는 효율을 위해 4의 배수로 부수적으로 의미없는 바이트가 추가 되는 경우가 있습니다.

 

예로 24Bit에서 Width가 17Pixel인 경우 51바이트(3 * 17)가 필요하지만 Stride값은 4배의 배수인 52바이트로 의미없는 1바이트가 추가됩니다.

자세한 자료는 다음 사이트를 참고 하시기 바랍니다.

http://www.bobpowell.net/lockingbits.htm

 

     9 class ImagePixelColor : Image

   10 {

   11     private static readonly DependencyProperty CurrentColorProperty =

   12         DependencyProperty.Register("CurrentColor", typeof(Color), typeof(ImagePixelColor),

   13         new FrameworkPropertyMetadata(Colors.Black,

   14             FrameworkPropertyMetadataOptions.AffectsRender));

   15 

   16     public Color CurrentColor

   17     {

   18         get

   19         {

   20             return (Color)GetValue(CurrentColorProperty);

   21         }

   22     }

   23 

   24     byte[] Pixels = new byte[4];

   25 

   26     protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)

   27     {

   28         SetValue(CurrentColorProperty, GetPixelColor(e.GetPosition(this)));

   29     }

   30 

   31     protected override void OnMouseMove(MouseEventArgs e)

   32     {

   33         if (e.LeftButton == MouseButtonState.Pressed || e.RightButton == MouseButtonState.Pressed)

   34         {

   35             SetValue(CurrentColorProperty, GetPixelColor(e.GetPosition(this)));

   36         }

   37     }

   38 

   39     private Color GetPixelColor(Point CurrentPoint)

   40     {

   41         BitmapSource CurrentSource = this.Source as BitmapSource;

   42 

   43         // 비트맵 내의 좌표 값 계산

   44         CurrentPoint.X *= CurrentSource.PixelWidth / this.ActualWidth;

   45         CurrentPoint.Y *= CurrentSource.PixelHeight / this.ActualHeight;

   46 

   47         if (CurrentSource.Format == PixelFormats.Bgra32 || CurrentSource.Format == PixelFormats.Bgr32)

   48         {

   49             // 32bit stride = (width * bpp + 7) /8

   50             int Stride = (CurrentSource.PixelWidth * CurrentSource.Format.BitsPerPixel + 7) / 8;

   51             // 한 픽셀 복사

   52             CurrentSource.CopyPixels(

   53                 new Int32Rect((int)CurrentPoint.X, (int)CurrentPoint.Y, 1, 1), Pixels, Stride, 0);

   54 

   55             // 컬러로 변환 후 리턴

   56             return Color.FromArgb(Pixels[3], Pixels[2], Pixels[1], Pixels[0]);

   57         }

   58         else

   59         {

   60             MessageBox.Show("지원되지 않는 포맷형식");

   61         }

   62         // TODO: 다른 포맷 형식 추가

   63 

   64         return Color.FromArgb(Pixels[3], Pixels[2], Pixels[1], Pixels[0]);

   65     }

   66 }

 

Ink의 색상과 선택한 픽셀값을 보여주는 Rectangle의 색상을 변경하기 위해 다음과 같은 컨버트와 바인딩 시켰습니다.

IvalueConverter 인터페이스는 바인딩 엔진을 통과할 때 데이터 수정을 가능하게 하는 메소드를 가지고 있습니다.

다음의 두 함수를 통해 전달되는 데이터를 값을 변경할 수 있습니다.

 

Convert : 소스 데이터를 UI에 표시하기 위해 대상에 전달하기 전에 수정합니다.

ConvertBack : 대상 데이터를 소스 개체에 전달하기 전에 수정합니다. TwoWay 바인딩에서만 호출됩니다.

 value  대상으로 전달되는 소스 데이터
 targetType  대상 종속성 속성에 필요한 데이터 타입
 parameter  변환기 논리에 사용 될 선택적 매개 변수
 culture  변환의 문화권

 

 

    50 [ValueConversion(typeof(Color), typeof(Brush))]

   51 public class ColorBrushConverter : IValueConverter

   52 {

   53     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

   54     {

   55         return new SolidColorBrush((Color)value);

   56     }

   57 

   58     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

   59     {

   60         return null;

   61     }

   62 }

   63 

   64 [ValueConversion(typeof(Color), typeof(DrawingAttributes))]

   65 public class InkColorConverter : IValueConverter

   66 {

   67     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

   68     {

   69         DrawingAttributes attribute = new DrawingAttributes();

   70         attribute.Color = (Color)value;

   71         return attribute;

   72     }

   73 

   74     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

   75     {

   76         return null;

   77     }

   78 }

 

[ Rectangle ]

 Fill="{Binding ElementName=Palette, Path=CurrentColor, Converter={StaticResource ColorConverter}}"

 

[ InkCanvas ]

 DefaultDrawingAttributes="{Binding ElementName=Palette, Path=CurrentColor, Converter={StaticResource InkColorConverter}}"

 

 

'Window > WPF' 카테고리의 다른 글

[ WPF ] Window 사이즈 변경 시 컨트롤 크기 변경하기  (3) 2010.02.08
[WPF] Object Capture  (0) 2010.01.29
[WPF] 시계 만들기  (0) 2010.01.26
[WPF] Drag, Scale, Rotate  (1) 2010.01.24
[ WPF ] Drag  (0) 2009.09.27
Posted by 열ㅇl