VisualBrush를 통해 브러쉬 요소로 사용할 수 가 있습니다.
이를 사용하여 윈도우 창에 있는 객체를 선택하거나 선택영역을 지정하여
해당 포맷에 맞는 이미지로 저장하는 간단한 예제를 만들어 보았습니다.
예제를 위해 눈사람 이라고 만들었는데 영 이상하네요. ㅎㅎ
객체 선택 : 마우스를 커서가 위치한 객체에 다음과 같이 빨간 테두리가 생깁니다.
Background 해제 시 객체만을 이미지로 저장합니다.
Background 체크 시 객체 영역을 이미지로 저장합니다.
저장 : 마우스 왼쪽 버튼
선택 영역 지정 : Cut 체크박스를 체크 한 후 마우스 왼쪽 버튼을 누른 채 이동하여 사각형을 만듭니다.
사각형을 드래그하여 이미지로 저장할 영역을 설정합니다.
저장 : 마우스 오른쪽 버튼
저장된 결과입니다.
예제는 부모 요소가 Canvas임을 고려하여 만들었습니다.
객체를 이미지로 변경하는 소스부분입니다.
DrawingVisual 객체로 객체 브러쉬로 사각형 그림을 그린 뒤 RenderTargetBitmap을 사용하여 Bitmap으로 변환합니다.
DrawRectangle의 Rect 첫번째 인자는 브러쉬로 칠할 시작 위치입니다.
30 public static RenderTargetBitmap ConverterBitmapImage(FrameworkElement element) 31 { 32 DrawingVisual drawingVisual = new DrawingVisual(); 33 DrawinContext drawingContext = drawingVisual.RenderOpen(); 34 35 // 해당 객체의 그래픽요소로 사각형의 그림을 그립니다. 36 drawingContext.DrawRectangle(new VisualBrush(element), null, 37 new Rect(new Point(0, 0), new Point(element.ActualWidth, element.ActualHeight))); 38 drawingContext.Close(); 39 40 // 비트맵으로 변환합니다. 41 RenderTargetBitmap target = 42 new RenderTargetBitmap((int)element.ActualWidth, (int)element.ActualHeight, 43 96, 96, System.Windows.Media.PixelFormats.Pbgra32); 44 45 target.Render(drawingVisual); 46 return target; 47 } |
선택영역을 이미지로 변환하는 부분입니다.
CopyPixels 함수에서 부모 Canvas 이미지에서 해당 영역 만큼 픽셀을 복사해 와 비트맵 소스로 변환합니다.
104 public static BitmapSource CutAreaToImage(int x, int y, int width, int height)
105 { . . // 예외 처리 부분 . 126 127 byte[] pixels = CopyPixels(x, y, width, height); 128 129 int stride = (width * backround.Format.BitsPerPixel + 7) / 8; 130 131 return BitmapSource.Create(width, height, 96, 96, PixelFormats.Pbgra32, null, pixels, stride); 132 } |
CopyPixels은 단지 CopyPixels 함수로 픽셀을 복사합니다.
82 public static byte[] CopyPixels(int x, int y, int width, int height)
83 { 84 byte[] pixels = new byte[width * height * 4]; 85 int stride = (width * backround.Format.BitsPerPixel + 7) / 8; 86 87 // Canvas 이미지에서 객체 역역만큼 픽셀로 복사 88 canvasImage.CopyPixels(new Int32Rect(x, y, width, height), pixels, stride, 0); 89 90 return pixels; 91 } |
다음은 객체 영역을 계산하는 부분입니다.
객체 이미지 픽셀과 Canvas영역에서 객체 영역만큼 잘라온 픽셀을 통해 계산해 보았는데
수정이 필요한 부분이네요. -_-;; 아니면 다른 방식으로 객체 영역만을 가져와야 하겠습니다.
하나의 픽셀은 4가지의 값을 (B,G,R,A) 가지고 있기 때문에 객체 브러쉬를 통해 비트맵으로 변환하게 되면 객체가 아닌
부분은 알파값이 제로이기 때문에 이를 사용해 봤지만 에러가 좀 있네요. ㅎㅎ
142 private static void PixelTransform(byte[] pixels, byte[] element_pixels, int length) 143 { 144 for(int i=3; i<length; i+=4) 145 { 146 if (element_pixels[i] == 0) 147 { 148 pixels[i] = 0; 149 } 150 else 151 { 152 if (pixels[i] > element_pixels[i]) 153 { 154 pixels[i] = element_pixels[i]; 155 pixels[i - 1] = element_pixels[i - 1]; 156 pixels[i - 2] = element_pixels[i - 2]; 157 pixels[i - 3] = element_pixels[i - 3]; 158 } 159 } 160 } 161 } |
Save함수는 포맷에 맞게 인코딩 후 저장합니다.
169 public static void Save(BitmapSource source, bool png)
170 { 171 SaveFileDialog dlg = new SaveFileDialog(); 172 173 dlg.Filter = "PNG|*.png|JPG|*.jpg|GIF|*.gif|BMP|*.bmp"; 174 dlg.AddExtension = true; 175 176 if (dlg.ShowDialog() == true) 177 { 178 FileStream stream = new FileStream(dlg.FileName, FileMode.Create, FileAccess.Write); 179 BitmapEncoder encoder = new PngBitmapEncoder(); 180 181 dlg.FileName.ToCharArray(dlg.FileName.Length - 3, 3); 182 183 string upper = dlg.FileName.ToUpper(); 184 char[] format = upper.ToCharArray(dlg.FileName.Length - 3, 3); 185 upper = new string(format); 186 187 if (!png) 188 { 189 switch (upper.ToString()) 190 { 191 case "JPG": 192 encoder = new JpegBitmapEncoder(); 193 break; 194 195 case "GIF": 196 encoder = new GifBitmapEncoder(); 197 break; 198 199 case "BMP": 200 encoder = new BmpBitmapEncoder(); 201 break; 202 } 203 } 204 205 encoder.Frames.Add(BitmapFrame.Create(source)); 206 207 encoder.Save(stream); 208 stream.Close(); 209 } 210 } |
'Window > WPF' 카테고리의 다른 글
[ WPF ] TextBox Select All Text (0) | 2010.02.11 |
---|---|
[ WPF ] Window 사이즈 변경 시 컨트롤 크기 변경하기 (3) | 2010.02.08 |
[WPF] 시계 만들기 (0) | 2010.01.26 |
[WPF] Image Pixel (0) | 2010.01.24 |
[WPF] Drag, Scale, Rotate (1) | 2010.01.24 |