czwartek, 5 stycznia 2012

[WPF] Wycinanie z WriteableBitmap

Temat:
Jak wycinać dowolny prostokąt z obrazka reprezentowanego przez WriteableBitmap.

Przygotowałem własną ExtensionMethod dla klasy WriteableBitmap, która korzystając z kodu niezarządzanego wybiera interesujący nas zbiór pikseli i zwraca nową bitmapę. ExtensionMethod działa jako dodatkowa metoda dla istniejącej już klasy. Można jej używać w zasięgu jednego namespace i musi być ona statyczną metoda statycznej klasy przyjmującą za pierwszy argument typ na rzecz którego ma być wywoływana poprzedzony this.


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public static class Extensions
    {
        public static WriteableBitmap Split(this WriteableBitmap wb, int left, int top, int width, int height)
        {
            if(left + width > wb.PixelWidth || top + height > wb.PixelHeight)
                throw new ArgumentException("Out of picture bounds !");

            WriteableBitmap split = new WriteableBitmap(width, height, wb.DpiX, wb.DpiY, wb.Format, wb.Palette);

            var pixelLength = wb.Format.BitsPerPixel / 8;
            var stride = pixelLength * wb.PixelWidth;
            var data = new byte[pixelLength * width * height];         
            int k = 0;
                        
            unsafe
            {
                var tab = (byte*)wb.BackBuffer;

                int index = 0;
                for (int j = 0; j < wb.Height; j++)
                {
                    for (int i = 0; i < wb.Width; i++)
                    {

                        if (i > left && i <= left + width && j > top && j <= top + height)
                        {
                            index = j * (pixelLength * (int)wb.PixelWidth) + i * pixelLength;
                            data[k++] = (byte)tab[index];
                            data[k++] = (byte)tab[index + 1];
                            data[k++] = (byte)tab[index + 2];
                            data[k++] = (byte)tab[index + 3];
                        }
                    }
                }
            }


            var rect = new Int32Rect(0, 0, width, height);
            split.WritePixels(rect, data, width * pixelLength , 0);

            return split;
        }
    }

Przykład użycia metody dla obrazka, który jest itemem dodanym do projektu:

1
2
3
4
5
6
7
8
9
private void LoadImage()
        {
            var uri = new Uri("pack://siteoforigin:,,,/vlepa.jpg");
            BitmapSource bs = new BitmapImage(uri);
            image = new WriteableBitmap(bs);

          
            WriteableBitmap small = image.Split(50,50,200,200);
        }

Aby móc kompilować kod niezarządzany (blok unsafe), należy w VS wejść w Properties projektu i w zakładce Build wybrać Allow unsafe code.

Kompilator : VS 2010

Brak komentarzy:

Prześlij komentarz