/// <summary>
        /// Fills the whole WriteableBitmap with a color.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="color">The color used for filling.</param>
        public static void Clear(this WriteableBitmap bmp, Color color)
        {
            // Add one to use mul and cheap bit shift for multiplicaltion
            int a = color.A + 1;
            int col = (color.A << 24)
                      | ((byte) ((color.R*a) >> 8) << 16)
                      | ((byte) ((color.G*a) >> 8) << 8)
                      | ((byte) ((color.B*a) >> 8));

            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
            #if SILVERLIGHT
             var pixels = bmp.Pixels;
             var len = w*SizeOfArgb;
            #else
            bmp.Lock();
            unsafe
            {
                var pixels = (int*) bmp.BackBuffer;
                int len = bmp.BackBufferStride;
            #endif

                // Fill first line
                for (int x = 0; x < w; x++)
                {
                    pixels[x] = col;
                }

                // Copy first line
                int blockHeight = 1;
                int y = 1;
                while (y < h)
                {
            #if SILVERLIGHT
                 Buffer.BlockCopy(pixels, 0, pixels, y*len, blockHeight*len);
            #else
                    NativeMethods.CopyUnmanagedMemory((IntPtr) pixels, 0, (IntPtr) pixels, y*len, blockHeight*len);
            #endif
                    y += blockHeight;
                    blockHeight = Math.Min(2*blockHeight, h - y);
                }

            #if !SILVERLIGHT
            }
            bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
            bmp.Unlock();
            #endif
        }
Exemplo n.º 2
0
        /// <summary>
        /// Clear all pixel with given color.
        /// </summary>
        /// <param name="wBitmap">Must not be null, or pixel width, pixel height equal to zero</param>
        /// <exception>Exception should be expect with null writeablebitmap or pixel width, height equal to zero.</exception>
        internal static void Clear(this WriteableBitmap wBitmap, Color color)
        {
            if (!(wBitmap.Format == PixelFormats.Pbgra32 || wBitmap.Format == PixelFormats.Gray8))
                return;
            byte[] col = ConvertColor(wBitmap.Format, color);

            //Currently only support two PixelFormat.
            int sizeOfColor = wBitmap.Format == PixelFormats.Pbgra32 ? 4 : 1;

            int pixelW = wBitmap.Format == PixelFormats.Gray8 ? wBitmap.BackBufferStride : wBitmap.PixelWidth;
            int pixelH = wBitmap.PixelHeight;
            int totalPixels = pixelW * pixelH;

            wBitmap.Lock();
            unsafe
            {
                byte* pixels = (byte*)wBitmap.BackBuffer;
                int length = col.Length;
                //Draw first dot color. 
                for (int index = 0; index < length; index++)
                {
                    *(pixels + index) = col[index];
                }

                int pixelIndex = 1;
                int blockPixels = 1;
                //Expand to all other pixels with Log(n) process. 
                while (pixelIndex < totalPixels)
                {
                    CopyUnmanagedMemory(pixels, 0, pixels, pixelIndex * sizeOfColor, blockPixels * sizeOfColor);

                    pixelIndex += blockPixels;
                    blockPixels = Math.Min(2 * blockPixels, totalPixels - pixelIndex);
                }
            }
            wBitmap.AddDirtyRect(new Int32Rect(0, 0, wBitmap.PixelWidth, wBitmap.PixelHeight));
            wBitmap.Unlock();

        }
        /// <summary>
        /// Draws a cubic Beziér spline defined by start, end and two control points.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="x1">The x-coordinate of the start point.</param>
        /// <param name="y1">The y-coordinate of the start point.</param>
        /// <param name="cx1">The x-coordinate of the 1st control point.</param>
        /// <param name="cy1">The y-coordinate of the 1st control point.</param>
        /// <param name="cx2">The x-coordinate of the 2nd control point.</param>
        /// <param name="cy2">The y-coordinate of the 2nd control point.</param>
        /// <param name="x2">The x-coordinate of the end point.</param>
        /// <param name="y2">The y-coordinate of the end point.</param>
        /// <param name="color">The color.</param>
        public static void DrawBezier(this WriteableBitmap bmp, int x1, int y1, int cx1, int cy1, int cx2, int cy2,
                                      int x2, int y2, int color)
        {
            // Determine distances between controls points (bounding rect) to find the optimal stepsize
            int minX = Math.Min(x1, Math.Min(cx1, Math.Min(cx2, x2)));
            int minY = Math.Min(y1, Math.Min(cy1, Math.Min(cy2, y2)));
            int maxX = Math.Max(x1, Math.Max(cx1, Math.Max(cx2, x2)));
            int maxY = Math.Max(y1, Math.Max(cy1, Math.Max(cy2, y2)));

            // Get slope
            int lenx = maxX - minX;
            int len = maxY - minY;
            if (lenx > len)
            {
                len = lenx;
            }

            // Prevent divison by zero
            if (len != 0)
            {
                // Use refs for faster access (really important!) speeds up a lot!
                int w = bmp.PixelWidth;
                int h = bmp.PixelHeight;
#if SILVERLIGHT
            int[] pixels = bmp.Pixels;
#else
                bmp.Lock();
                IntPtr pixels = bmp.BackBuffer;
#endif

                // Init vars
                float step = StepFactor/len;
                int tx1 = x1;
                int ty1 = y1;
                int tx2, ty2;

                // Interpolate
                for (float t = step; t <= 1; t += step)
                {
                    float tSq = t*t;
                    float t1 = 1 - t;
                    float t1Sq = t1*t1;

                    tx2 = (int) (t1*t1Sq*x1 + 3*t*t1Sq*cx1 + 3*t1*tSq*cx2 + t*tSq*x2);
                    ty2 = (int) (t1*t1Sq*y1 + 3*t*t1Sq*cy1 + 3*t1*tSq*cy2 + t*tSq*y2);

                    // Draw line
                    DrawLine(pixels, w, h, tx1, ty1, tx2, ty2, color);
                    tx1 = tx2;
                    ty1 = ty2;
                }

                // Prevent rounding gap
                DrawLine(pixels, w, h, tx1, ty1, x2, y2, color);
#if !SILVERLIGHT
                bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
                bmp.Unlock();
#endif
            }
        }
        /// <summary>
        /// Draws a closed Cardinal spline (cubic) defined by a point collection. 
        /// The cardinal spline passes through each point in the collection.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="points">The points for the curve in x and y pairs, therefore the array is interpreted as (x1, y1, x2, y2, x3, y3, x4, y4, x1, x2 ..., xn, yn).</param>
        /// <param name="tension">The tension of the curve defines the shape. Usually between 0 and 1. 0 would be a straight line.</param>
        /// <param name="color">The color for the spline.</param>
        public static void DrawCurveClosed(this WriteableBitmap bmp, int[] points, float tension, int color)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
#if SILVERLIGHT
         int[] pixels = bmp.Pixels;
#else
            bmp.Lock();
            IntPtr pixels = bmp.BackBuffer;
#endif
            int pn = points.Length;

            // First segment
            DrawCurveSegment(points[pn - 2], points[pn - 1], points[0], points[1], points[2], points[3], points[4],
                             points[5], tension, color, pixels, w, h);

            // Middle segments
            int i;
            for (i = 2; i < pn - 4; i += 2)
            {
                DrawCurveSegment(points[i - 2], points[i - 1], points[i], points[i + 1], points[i + 2], points[i + 3],
                                 points[i + 4], points[i + 5], tension, color, pixels, w, h);
            }

            // Last segment
            DrawCurveSegment(points[i - 2], points[i - 1], points[i], points[i + 1], points[i + 2], points[i + 3],
                             points[0], points[1], tension, color, pixels, w, h);

            // Last-to-First segment
            DrawCurveSegment(points[i], points[i + 1], points[i + 2], points[i + 3], points[0], points[1], points[2],
                             points[3], tension, color, pixels, w, h);
#if !SILVERLIGHT
            bmp.AddDirtyRect(new Int32Rect(0, 0, w, h));
            bmp.Unlock();
#endif
        }
 /// <summary>
 /// Fills the whole WriteableBitmap with an empty color (0).
 /// </summary>
 /// <param name="bmp">The WriteableBitmap.</param>
 public static void Clear(this WriteableBitmap bmp)
 {
     #if SILVERLIGHT
       Array.Clear(bmp.Pixels, 0, bmp.Pixels.Length);
     #else
     bmp.Lock();
     NativeMethods.SetUnmanagedMemory(bmp.BackBuffer, 0, bmp.BackBufferStride*bmp.PixelHeight);
     bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
     bmp.Unlock();
     #endif
 }
        /// <summary>
        /// Draws a rectangle.
        /// x2 has to be greater than x1 and y2 has to be greater than y1.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="x1">The x-coordinate of the bounding rectangle's left side.</param>
        /// <param name="y1">The y-coordinate of the bounding rectangle's top side.</param>
        /// <param name="x2">The x-coordinate of the bounding rectangle's right side.</param>
        /// <param name="y2">The y-coordinate of the bounding rectangle's bottom side.</param>
        /// <param name="color">The color.</param>
        public static void DrawRectangle(this WriteableBitmap bmp, int x1, int y1, int x2, int y2, int color)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
#if SILVERLIGHT
         int[] pixels = bmp.Pixels;
#else
            bmp.Lock();
            unsafe
            {
                var pixels = (int*) bmp.BackBuffer;
#endif
                // Check boundaries
                if (x1 < 0)
                {
                    x1 = 0;
                }
                if (y1 < 0)
                {
                    y1 = 0;
                }
                if (x2 < 0)
                {
                    x2 = 0;
                }
                if (y2 < 0)
                {
                    y2 = 0;
                }
                if (x1 >= w)
                {
                    x1 = w - 1;
                }
                if (y1 >= h)
                {
                    y1 = h - 1;
                }
                if (x2 >= w)
                {
                    x2 = w - 1;
                }
                if (y2 >= h)
                {
                    y2 = h - 1;
                }

                int startY = y1*w;
                int endY = y2*w;

                int offset2 = endY + x1;
                int endOffset = startY + x2;
                int startYPlusX1 = startY + x1;

                // top and bottom horizontal scanlines
                for (int x = startYPlusX1; x <= endOffset; x++)
                {
                    pixels[x] = color; // top horizontal line
                    pixels[offset2] = color; // bottom horizontal line
                    offset2++;
                }

                // offset2 == endY + x2

                // vertical scanlines
                endOffset = startYPlusX1 + w;
                offset2 -= w;

                for (int y = startY + x2 + w; y < offset2; y += w)
                {
                    pixels[y] = color; // right vertical line
                    pixels[endOffset] = color; // left vertical line
                    endOffset += w;
                }
#if !SILVERLIGHT
            }
            bmp.AddDirtyRect(new Int32Rect(x1, y1, x2 - x1, y2 - y1));
            bmp.Unlock();
#endif
        }
        /// <summary>
        /// Draws a polyline. Add the first point also at the end of the array if the line should be closed.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="points">The points of the polyline in x and y pairs, therefore the array is interpreted as (x1, y1, x2, y2, ..., xn, yn).</param>
        /// <param name="color">The color for the line.</param>
        public static void DrawPolyline(this WriteableBitmap bmp, int[] points, int color)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
#if SILVERLIGHT         
          int[] pixels = bmp.Pixels;
#else
            bmp.Lock();
            IntPtr pixels = bmp.BackBuffer;
#endif
            int x1 = points[0];
            int y1 = points[1];
            int x2, y2;
            for (int i = 2; i < points.Length; i += 2)
            {
                x2 = points[i];
                y2 = points[i + 1];
                DrawLine(pixels, w, h, x1, y1, x2, y2, color);
                x1 = x2;
                y1 = y2;
            }
#if !SILVERLIGHT
            bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
            bmp.Unlock();
#endif
        }
        /// <summary>
        /// Draws a colored line by connecting two points using an optimized DDA.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="x1">The x-coordinate of the start point.</param>
        /// <param name="y1">The y-coordinate of the start point.</param>
        /// <param name="x2">The x-coordinate of the end point.</param>
        /// <param name="y2">The y-coordinate of the end point.</param>
        /// <param name="color">The color for the line.</param>
        public static void DrawLine(this WriteableBitmap bmp, int x1, int y1, int x2, int y2, int color)
        {
#if SILVERLIGHT
         DrawLine(bmp.Pixels, bmp.PixelWidth, bmp.PixelHeight, x1, y1, x2, y2, color);
#else
            bmp.Lock();
            DrawLine(bmp.BackBuffer, bmp.BackBufferStride/SizeOfArgb, bmp.PixelHeight, x1, y1, x2, y2, color);
            bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
            bmp.Unlock();
#endif
        }
 /// <summary>
 /// Sets the color of the pixel using an extra alpha value.
 /// </summary>
 /// <param name="bmp">The WriteableBitmap.</param>
 /// <param name="x">The x coordinate (row).</param>
 /// <param name="y">The y coordinate (column).</param>
 /// <param name="a">The alpha value of the color.</param>
 /// <param name="color">The color.</param>
 public static void SetPixel(this WriteableBitmap bmp, int x, int y, byte a, Color color)
 {
     // Add one to use mul and cheap bit shift for multiplicaltion
     int ai = a + 1;
     int argb = (a << 24)
                | ((byte) ((color.R*ai) >> 8) << 16)
                | ((byte) ((color.G*ai) >> 8) << 8)
                | ((byte) ((color.B*ai) >> 8));
     #if SILVERLIGHT
       bmp.Pixels[y * bmp.PixelWidth + x] = argb;
     #else
     bmp.Lock();
     unsafe
     {
         var pixels = (int*) bmp.BackBuffer;
         pixels[y*bmp.BackBufferStride/SizeOfArgb + x] = argb;
     }
     bmp.AddDirtyRect(new Int32Rect(x, y, 1, 1));
     bmp.Unlock();
     #endif
 }
        /// <summary>
        /// Applies the given function to all the pixels of the bitmap in 
        /// order to set their color.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="func">The function to apply. With parameters x, y, source color and a color as a result</param>
        public static void ForEach(this WriteableBitmap bmp, Func<int, int, Color, Color> func)
        {
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
            #if SILVERLIGHT
             int[] pixels = bmp.Pixels;
            #else
            bmp.Lock();
            unsafe
            {
                var pixels = (int*) bmp.BackBuffer;
            #endif
                int index = 0;

                for (int y = 0; y < h; y++)
                {
                    for (int x = 0; x < w; x++)
                    {
                        int c = pixels[index];
                        Color color = func(x, y,
                                           Color.FromArgb((byte) (c >> 24), (byte) (c >> 16), (byte) (c >> 8),
                                                          (byte) (c)));
                        // Add one to use mul and cheap bit shift for multiplicaltion
                        int a = color.A + 1;
                        pixels[index++] = (color.A << 24)
                                          | ((byte) ((color.R*a) >> 8) << 16)
                                          | ((byte) ((color.G*a) >> 8) << 8)
                                          | ((byte) ((color.B*a) >> 8));
                    }
                }
            #if !SILVERLIGHT
            }
            bmp.AddDirtyRect(new Int32Rect(0, 0, w, h));
            bmp.Unlock();
            #endif
        }
 /// <summary>
 /// Sets the color of the pixel including the alpha value.
 /// </summary>
 /// <param name="bmp">The WriteableBitmap.</param>
 /// <param name="x">The x coordinate (row).</param>
 /// <param name="y">The y coordinate (column).</param>
 /// <param name="a">The alpha value of the color.</param>
 /// <param name="r">The red value of the color.</param>
 /// <param name="g">The green value of the color.</param>
 /// <param name="b">The blue value of the color.</param>
 public static void SetPixel(this WriteableBitmap bmp, int x, int y, byte a, byte r, byte g, byte b)
 {
     int argb = (a << 24) | (r << 16) | (g << 8) | b;
     #if SILVERLIGHT
       bmp.Pixels[y * bmp.PixelWidth + x] = argb;
     #else
     bmp.Lock();
     unsafe
     {
         var pixels = (int*) bmp.BackBuffer;
         pixels[y*bmp.BackBufferStride/SizeOfArgb + x] = argb;
     }
     bmp.AddDirtyRect(new Int32Rect(x, y, 1, 1));
     bmp.Unlock();
     #endif
 }
        /// <summary>
        /// Draws a filled rectangle.
        /// x2 has to be greater than x1 and y2 has to be greater than y1.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="x1">The x-coordinate of the bounding rectangle's left side.</param>
        /// <param name="y1">The y-coordinate of the bounding rectangle's top side.</param>
        /// <param name="x2">The x-coordinate of the bounding rectangle's right side.</param>
        /// <param name="y2">The y-coordinate of the bounding rectangle's bottom side.</param>
        /// <param name="color">The color.</param>
        public static void FillRectangle(this WriteableBitmap bmp, int x1, int y1, int x2, int y2, int color)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
            #if SILVERLIGHT
             int[] pixels = bmp.Pixels;
            #else
            bmp.Lock();
            unsafe
            {
                var pixels = (int*) bmp.BackBuffer;
            #endif

                // Check boundaries
                if (x1 < 0)
                {
                    x1 = 0;
                }
                if (y1 < 0)
                {
                    y1 = 0;
                }
                if (x2 < 0)
                {
                    x2 = 0;
                }
                if (y2 < 0)
                {
                    y2 = 0;
                }
                if (x1 >= w)
                {
                    x1 = w - 1;
                }
                if (y1 >= h)
                {
                    y1 = h - 1;
                }
                if (x2 >= w)
                {
                    x2 = w - 1;
                }
                if (y2 >= h)
                {
                    y2 = h - 1;
                }

                // Fill first line
                int startY = y1*w;
                int startYPlusX1 = startY + x1;
                int endOffset = startY + x2;
                for (int x = startYPlusX1; x < endOffset; x++)
                {
                    pixels[x] = color;
                }

                // Copy first line
                int len = (x2 - x1)*SizeOfArgb;
                int srcOffsetBytes = startYPlusX1*SizeOfArgb;
                int offset2 = y2*w + x1;
                for (int y = startYPlusX1 + w; y < offset2; y += w)
                {
            #if SILVERLIGHT
                  Buffer.BlockCopy(pixels, srcOffsetBytes, pixels, y*SizeOfArgb, len);
            #else
                    NativeMethods.CopyUnmanagedMemory((IntPtr) pixels, srcOffsetBytes, (IntPtr) pixels, y*SizeOfArgb,
                                                      len);
            #endif
                }
            #if !SILVERLIGHT
            }
            bmp.AddDirtyRect(new Int32Rect(x1, y1, x2 - x1, y2 - y1));
            bmp.Unlock();
            #endif
        }
        /// <summary>
        /// Draws a filled polygon. Add the first point also at the end of the array if the line should be closed.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="points">The points of the polygon in x and y pairs, therefore the array is interpreted as (x1, y1, x2, y2, ..., xn, yn).</param>
        /// <param name="color">The color for the line.</param>
        public static void FillPolygon(this WriteableBitmap bmp, int[] points, int color)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
            #if SILVERLIGHT
             int[] pixels = bmp.Pixels;
            #else
            bmp.Lock();
            unsafe
            {
                var pixels = (int*) bmp.BackBuffer;
            #endif
                int pn = points.Length;
                int pnh = points.Length >> 1;
                var intersectionsX = new int[pnh];

                // Find y min and max (slightly faster than scanning from 0 to height)
                int yMin = h;
                int yMax = 0;
                for (int i = 1; i < pn; i += 2)
                {
                    int py = points[i];
                    if (py < yMin) yMin = py;
                    if (py > yMax) yMax = py;
                }
                if (yMin < 0) yMin = 0;
                if (yMax >= h) yMax = h - 1;

                // Scan line from min to max
                for (int y = yMin; y <= yMax; y++)
                {
                    // Initial point x, y
                    int vxi = points[0];
                    int vyi = points[1];

                    // Find all intersections
                    // Based on http://alienryderflex.com/polygon_fill/
                    int intersectionCount = 0;
                    for (int i = 2; i < pn; i += 2)
                    {
                        // Next point x, y
                        int vxj = points[i];
                        int vyj = points[i + 1];

                        // Is the scanline between the two points
                        if (vyi < y && vyj >= y
                            || vyj < y && vyi >= y)
                        {
                            // Compute the intersection of the scanline with the edge (line between two points)
                            // NOTE: only division has to be floating point
                            intersectionsX[intersectionCount++] =
                                (int) (vxi + (y - vyi)/(float) (vyj - vyi)*(vxj - vxi));
                        }
                        vxi = vxj;
                        vyi = vyj;
                    }

                    // Sort the intersections from left to right using Insertion sort
                    // It's faster than Array.Sort for this small data set
                    int t, j;
                    for (int i = 1; i < intersectionCount; i++)
                    {
                        t = intersectionsX[i];
                        j = i;
                        while (j > 0 && intersectionsX[j - 1] > t)
                        {
                            intersectionsX[j] = intersectionsX[j - 1];
                            j = j - 1;
                        }
                        intersectionsX[j] = t;
                    }

                    // Fill the pixels between the intersections
                    for (int i = 0; i < intersectionCount - 1; i += 2)
                    {
                        int x0 = intersectionsX[i];
                        int x1 = intersectionsX[i + 1];

                        // Check boundary
                        if (x1 > 0 && x0 < w)
                        {
                            if (x0 < 0) x0 = 0;
                            if (x1 >= w) x1 = w - 1;

                            // Fill the pixels
                            for (int x = x0; x <= x1; x++)
                            {
                                pixels[y*w + x] = color;
                            }
                        }
                    }
                }
            #if !SILVERLIGHT
            }
            bmp.AddDirtyRect(new Int32Rect(0, 0, w, h));
            bmp.Unlock();
            #endif
        }
        /// <summary>
        /// Draw rectangle with given color.
        /// </summary>
        /// <param name="wBitmap">Must not be null, or pixel width, pixel height equal to zero</param>
        /// <exception>Exception should be expect with null writeablebitmap or pixel width, height equal to zero.</exception>
        internal static void FillRectangle(this WriteableBitmap wBitmap, Int32Rect rectangle, Color color)
        {
            if (!(wBitmap.Format == PixelFormats.Pbgra32 || wBitmap.Format == PixelFormats.Gray8))
                return;
            byte[] col = ConvertColor(wBitmap.Format, color);

            //Currently only support two PixelFormat.
            int sizeOfColor = wBitmap.Format == PixelFormats.Pbgra32 ? 4 : 1;

            int pixelW = wBitmap.Format == PixelFormats.Gray8 ? wBitmap.BackBufferStride : wBitmap.PixelWidth;
            int pixelH = wBitmap.PixelHeight;

            if (rectangle.X >= pixelW
                || rectangle.Y >= pixelH
                || rectangle.X + rectangle.Width - 1 < 0
                || rectangle.Y + rectangle.Height - 1 < 0)
                return;

            if (rectangle.X < 0) rectangle.X = 0;
            if (rectangle.Y < 0) rectangle.Y = 0;
            if (rectangle.X + rectangle.Width >= pixelW) rectangle.Width = pixelW - rectangle.X;
            if (rectangle.Y + rectangle.Height >= pixelH) rectangle.Height = pixelH - rectangle.Y;

            wBitmap.Lock();
            unsafe
            {
                byte* pixels = (byte*)wBitmap.BackBuffer;

                int startPoint = rectangle.Y * pixelW + rectangle.X;
                int endBoundry = startPoint + rectangle.Width;
                int srcOffsetBytes = startPoint * sizeOfColor;

                int length = col.Length;
                //Draw first dot color.
                for (int index = 0; index < length; index++)
                {
                    *(pixels + srcOffsetBytes + index) = col[index];
                }

                int pixelIndex = startPoint + 1;
                int blockPixels = 1;

                //Use first pixel color at (x, y) offset to draw first line.
                while (pixelIndex < endBoundry)
                {
                    CopyUnmanagedMemory(pixels, srcOffsetBytes, pixels, pixelIndex * sizeOfColor, blockPixels * sizeOfColor);

                    pixelIndex += blockPixels;
                    blockPixels = Math.Min(2 * blockPixels, endBoundry - pixelIndex);
                }

                int bottomLeft = (rectangle.Y + rectangle.Height - 1) * pixelW + rectangle.X;
                //Use first line of pixel to fill up rest of rectangle.
                for (pixelIndex = startPoint + pixelW; pixelIndex <= bottomLeft; pixelIndex += pixelW)
                {
                    CopyUnmanagedMemory(pixels, srcOffsetBytes, pixels, pixelIndex * sizeOfColor, rectangle.Width * sizeOfColor);
                }

            }
            wBitmap.AddDirtyRect(rectangle);
            wBitmap.Unlock();
        }
        /// <summary>
        /// Draws a colored line by connecting two points using the Bresenham algorithm.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="x1">The x-coordinate of the start point.</param>
        /// <param name="y1">The y-coordinate of the start point.</param>
        /// <param name="x2">The x-coordinate of the end point.</param>
        /// <param name="y2">The y-coordinate of the end point.</param>
        /// <param name="color">The color for the line.</param>
        public static void DrawLineBresenham(this WriteableBitmap bmp, int x1, int y1, int x2, int y2, int color)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
#if SILVERLIGHT
         int[] pixels = bmp.Pixels;
#else
            bmp.Lock();
            unsafe
            {
                var pixels = (int*) bmp.BackBuffer;
#endif
                // Distance start and end point
                int dx = x2 - x1;
                int dy = y2 - y1;

                // Determine sign for direction x
                int incx = 0;
                if (dx < 0)
                {
                    dx = -dx;
                    incx = -1;
                }
                else if (dx > 0)
                {
                    incx = 1;
                }

                // Determine sign for direction y
                int incy = 0;
                if (dy < 0)
                {
                    dy = -dy;
                    incy = -1;
                }
                else if (dy > 0)
                {
                    incy = 1;
                }

                // Which gradient is larger
                int pdx, pdy, odx, ody, es, el;
                if (dx > dy)
                {
                    pdx = incx;
                    pdy = 0;
                    odx = incx;
                    ody = incy;
                    es = dy;
                    el = dx;
                }
                else
                {
                    pdx = 0;
                    pdy = incy;
                    odx = incx;
                    ody = incy;
                    es = dx;
                    el = dy;
                }

                // Init start
                int x = x1;
                int y = y1;
                int error = el >> 1;
                if (y < h && y >= 0 && x < w && x >= 0)
                {
                    pixels[y*w + x] = color;
                }

                // Walk the line!
                for (int i = 0; i < el; i++)
                {
                    // Update error term
                    error -= es;

                    // Decide which coord to use
                    if (error < 0)
                    {
                        error += el;
                        x += odx;
                        y += ody;
                    }
                    else
                    {
                        x += pdx;
                        y += pdy;
                    }

                    // Set pixel
                    if (y < h && y >= 0 && x < w && x >= 0)
                    {
                        pixels[y*w + x] = color;
                    }
                }
#if !SILVERLIGHT
            }
            bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
            bmp.Unlock();
#endif
        }
 /// <summary>
 /// Sets the color of the pixel.
 /// </summary>
 /// <param name="bmp">The WriteableBitmap.</param>
 /// <param name="x">The x coordinate (row).</param>
 /// <param name="y">The y coordinate (column).</param>
 /// <param name="color">The color.</param>
 public static void SetPixel(this WriteableBitmap bmp, int x, int y, int color)
 {
     #if SILVERLIGHT
       bmp.Pixels[y * bmp.PixelWidth + x] = color;
     #else
     bmp.Lock();
     unsafe
     {
         var pixels = (int*) bmp.BackBuffer;
         pixels[y*bmp.BackBufferStride/SizeOfArgb + x] = color;
     }
     bmp.AddDirtyRect(new Int32Rect(x, y, 1, 1));
     bmp.Unlock();
     #endif
 }
        /// <summary>
        /// Draws a colored line by connecting two points using a DDA algorithm (Digital Differential Analyzer).
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="x1">The x-coordinate of the start point.</param>
        /// <param name="y1">The y-coordinate of the start point.</param>
        /// <param name="x2">The x-coordinate of the end point.</param>
        /// <param name="y2">The y-coordinate of the end point.</param>
        /// <param name="color">The color for the line.</param>
        public static void DrawLineDDA(this WriteableBitmap bmp, int x1, int y1, int x2, int y2, int color)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
#if SILVERLIGHT
         int[] pixels = bmp.Pixels;
#else
            bmp.Lock();
            unsafe
            {
                var pixels = (int*) bmp.BackBuffer;
#endif
                // Distance start and end point
                int dx = x2 - x1;
                int dy = y2 - y1;

                // Determine slope (absoulte value)
                int len = dy >= 0 ? dy : -dy;
                int lenx = dx >= 0 ? dx : -dx;
                if (lenx > len)
                {
                    len = lenx;
                }

                // Prevent divison by zero
                if (len != 0)
                {
                    // Init steps and start
                    float incx = dx/(float) len;
                    float incy = dy/(float) len;
                    float x = x1;
                    float y = y1;

                    // Walk the line!
                    for (int i = 0; i < len; i++)
                    {
                        if (y < h && y >= 0 && x < w && x >= 0)
                        {
                            pixels[(int) y*w + (int) x] = color;
                        }
                        x += incx;
                        y += incy;
                    }
                }
#if !SILVERLIGHT
            }
            bmp.Unlock();
            bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
#endif
        }
 /// <summary>
 /// Sets the color of the pixel including the alpha value and using a precalculated index (faster).
 /// </summary>
 /// <param name="bmp">The WriteableBitmap.</param>
 /// <param name="index">The coordinate index.</param>
 /// <param name="a">The alpha value of the color.</param>
 /// <param name="r">The red value of the color.</param>
 /// <param name="g">The green value of the color.</param>
 /// <param name="b">The blue value of the color.</param>
 public static void SetPixeli(this WriteableBitmap bmp, int index, byte a, byte r, byte g, byte b)
 {
     int argb = (a << 24) | (r << 16) | (g << 8) | b;
     #if SILVERLIGHT
       bmp.Pixels[index] = argb;
     #else
     bmp.Lock();
     unsafe
     {
         var pixels = (int*) bmp.BackBuffer;
         pixels[index] = argb;
     }
     //TODO: compute dirty rect
     bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
     bmp.Unlock();
     #endif
 }
        public static void DrawLineEFLA(this WriteableBitmap bmp, int x1, int y1, int x2, int y2, int color, EFLAMode mode)
        {
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
            bmp.Lock();

            bool yLonger;
            int incrementVal, endVal;
            int shortLen;
            int longLen;

            unsafe
            {
                var pixels = (int*) bmp.BackBuffer;
                int x, y;

                switch (mode)
                {
                    case EFLAMode.Div:
                        yLonger = false;

                        shortLen = y2 - y1;
                        longLen = x2 - x1;

                        if (Math.Abs(shortLen) > Math.Abs(longLen))
                        {
                            int swap = shortLen;
                            shortLen = longLen;
                            longLen = swap;
                            yLonger = true;
                        }

                        if (longLen < 0) incrementVal = -1;
                        else incrementVal = 1;

                        double divDiff;
                        if (shortLen == 0) divDiff = longLen;
                        else divDiff = longLen/(double) shortLen;
                        if (yLonger)
                        {
                            for (int i = 0; i != longLen; i += incrementVal)
                            {
                                x = x1 + (int) (i/divDiff);
                                y = y1 + i;
                                pixels[y*w + x] = color;
                            }
                        }
                        else
                        {
                            for (int i = 0; i != longLen; i += incrementVal)
                            {
                                x = x1 + i;
                                y = y1 + (int) (i/divDiff);
                                pixels[y*w + x] = color;
                            }
                        }
                        break;
                    case EFLAMode.Mul:
                        yLonger = false;
                        shortLen = y2 - y1;
                        longLen = x2 - x1;

                        if (Math.Abs(shortLen) > Math.Abs(longLen))
                        {
                            int swap = shortLen;
                            shortLen = longLen;
                            longLen = swap;
                            yLonger = true;
                        }

                        if (longLen < 0) incrementVal = -1;
                        else incrementVal = 1;

                        double multDiff;
                        if (longLen == 0.0) multDiff = shortLen;
                        else multDiff = shortLen/(double) longLen;
                        if (yLonger)
                        {
                            for (int i = 0; i != longLen; i += incrementVal)
                            {
                                x = x1 + (int) (i*multDiff);
                                y = y1 + i;
                                pixels[y*w + x] = color;
                            }
                        }
                        else
                        {
                            for (int i = 0; i != longLen; i += incrementVal)
                            {
                                x = x1 + i;
                                y = y1 + (int) (i*multDiff);
                                pixels[y*w + x] = color;
                            }
                        }
                        break;
                    case EFLAMode.Add:
                        yLonger = false;

                        shortLen = y2 - y1;
                        longLen = x2 - x1;
                        if (Math.Abs(shortLen) > Math.Abs(longLen))
                        {
                            int swap = shortLen;
                            shortLen = longLen;
                            longLen = swap;
                            yLonger = true;
                        }

                        endVal = longLen;
                        if (longLen < 0)
                        {
                            incrementVal = -1;
                            longLen = -longLen;
                        }
                        else incrementVal = 1;

                        double decInc;
                        if (longLen == 0) decInc = shortLen;
                        else decInc = (shortLen/(double) longLen);
                        double j = 0.0;
                        if (yLonger)
                        {
                            for (int i = 0; i != endVal; i += incrementVal)
                            {
                                x = x1 + (int) j;
                                y = y1 + i;
                                pixels[y*w + x] = color;
                                j += decInc;
                            }
                        }
                        else
                        {
                            for (int i = 0; i != endVal; i += incrementVal)
                            {
                                x = x1 + i;
                                y = y1 + (int) j;
                                pixels[y*w + x] = color;
                                j += decInc;
                            }
                        }
                        break;
                    case EFLAMode.AddFixed:
                        yLonger = false;
                        shortLen = y2 - y1;
                        longLen = x2 - x1;
                        if (Math.Abs(shortLen) > Math.Abs(longLen))
                        {
                            int swap = shortLen;
                            shortLen = longLen;
                            longLen = swap;
                            yLonger = true;
                        }
                        endVal = longLen;
                        if (longLen < 0)
                        {
                            incrementVal = -1;
                            longLen = -longLen;
                        }
                        else incrementVal = 1;

                        int decIncI = 0;
                        if (longLen == 0) decInc = 0;
                        else decIncI = (shortLen << 16)/longLen;
                        int jI = 0;
                        if (yLonger)
                        {
                            for (int i = 0; i != endVal; i += incrementVal)
                            {
                                x = x1 + (jI >> 16);
                                y = y1 + i;
                                pixels[y*w + x] = color;
                                jI += decIncI;
                            }
                        }
                        else
                        {
                            for (int i = 0; i != endVal; i += incrementVal)
                            {
                                x = x1 + i;
                                y = y1 + (jI >> 16);
                                pixels[y*w + x] = color;
                                jI += decIncI;
                            }
                        }

                        break;
                    case EFLAMode.AddFixedPreCal:
                        break;
                    default:
                        throw new ArgumentOutOfRangeException("mode");
                }
            }
            bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
            bmp.Unlock();
        }
 /// <summary>
 /// Sets the color of the pixel using an extra alpha value and a precalculated index (faster).
 /// </summary>
 /// <param name="bmp">The WriteableBitmap.</param>
 /// <param name="index">The coordinate index.</param>
 /// <param name="a">The alpha value of the color.</param>
 /// <param name="color">The color.</param>
 public static void SetPixeli(this WriteableBitmap bmp, int index, byte a, Color color)
 {
     // Add one to use mul and cheap bit shift for multiplicaltion
     int ai = a + 1;
     int argb = (a << 24)
                | ((byte) ((color.R*ai) >> 8) << 16)
                | ((byte) ((color.G*ai) >> 8) << 8)
                | ((byte) ((color.B*ai) >> 8));
     #if SILVERLIGHT
       bmp.Pixels[index] = argb;
     #else
     bmp.Lock();
     unsafe
     {
         var pixels = (int*) bmp.BackBuffer;
         pixels[index] = argb;
     }
     //TODO: compute dirty rect
     bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
     bmp.Unlock();
     #endif
 }
        /// <summary>
        /// Draws a quad.
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="x1">The x-coordinate of the 1st point.</param>
        /// <param name="y1">The y-coordinate of the 1st point.</param>
        /// <param name="x2">The x-coordinate of the 2nd point.</param>
        /// <param name="y2">The y-coordinate of the 2nd point.</param>
        /// <param name="x3">The x-coordinate of the 3rd point.</param>
        /// <param name="y3">The y-coordinate of the 3rd point.</param>
        /// <param name="x4">The x-coordinate of the 4th point.</param>
        /// <param name="y4">The y-coordinate of the 4th point.</param>
        /// <param name="color">The color.</param>
        public static void DrawQuad(this WriteableBitmap bmp, int x1, int y1, int x2, int y2, int x3, int y3, int x4,
                                    int y4, int color)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
#if SILVERLIGHT
         int[] pixels = bmp.Pixels;
#else
            bmp.Lock();
            IntPtr pixels = bmp.BackBuffer;
#endif

            DrawLine(pixels, w, h, x1, y1, x2, y2, color);
            DrawLine(pixels, w, h, x2, y2, x3, y3, color);
            DrawLine(pixels, w, h, x3, y3, x4, y4, color);
            DrawLine(pixels, w, h, x4, y4, x1, y1, color);

#if !SILVERLIGHT
            bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
            bmp.Unlock();
#endif
        }
 /// <summary>
 /// Sets the color of the pixel using a precalculated index (faster).
 /// </summary>
 /// <param name="bmp">The WriteableBitmap.</param>
 /// <param name="index">The coordinate index.</param>
 /// <param name="color">The color.</param>
 public static void SetPixeli(this WriteableBitmap bmp, int index, int color)
 {
     #if SILVERLIGHT
       bmp.Pixels[index] = color;
     #else
     bmp.Lock();
     unsafe
     {
         var pixels = (int*) bmp.BackBuffer;
         pixels[index] = color;
     }
     //TODO: compute dirty rect
     bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
     bmp.Unlock();
     #endif
 }
        /// <summary>
        /// A Fast Bresenham Type Algorithm For Drawing Ellipses http://homepage.smc.edu/kennedy_john/belipse.pdf 
        /// Uses a different parameter representation than DrawEllipse().
        /// </summary>
        /// <param name="bmp">The WriteableBitmap.</param>
        /// <param name="xc">The x-coordinate of the ellipses center.</param>
        /// <param name="yc">The y-coordinate of the ellipses center.</param>
        /// <param name="xr">The radius of the ellipse in x-direction.</param>
        /// <param name="yr">The radius of the ellipse in y-direction.</param>
        /// <param name="color">The color for the line.</param>
        public static void DrawEllipseCentered(this WriteableBitmap bmp, int xc, int yc, int xr, int yr, int color)
        {
            // Use refs for faster access (really important!) speeds up a lot!
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
#if SILVERLIGHT
          int[] pixels = bmp.Pixels;
#else
            bmp.Lock();
            unsafe
            {
                var pixels = (int*) bmp.BackBuffer;
#endif
                // Init vars
                int uh, lh, uy, ly, lx, rx;
                int x = xr;
                int y = 0;
                int xrSqTwo = (xr*xr) << 1;
                int yrSqTwo = (yr*yr) << 1;
                int xChg = yr*yr*(1 - (xr << 1));
                int yChg = xr*xr;
                int err = 0;
                int xStopping = yrSqTwo*xr;
                int yStopping = 0;

                // Draw first set of points counter clockwise where tangent line slope > -1.
                while (xStopping >= yStopping)
                {
                    // Draw 4 quadrant points at once
                    uy = yc + y; // Upper half
                    ly = yc - y; // Lower half
                    if (uy < 0) uy = 0; // Clip
                    if (uy >= h) uy = h - 1; // ...
                    if (ly < 0) ly = 0;
                    if (ly >= h) ly = h - 1;
                    uh = uy*w; // Upper half
                    lh = ly*w; // Lower half

                    rx = xc + x;
                    lx = xc - x;
                    if (rx < 0) rx = 0; // Clip
                    if (rx >= w) rx = w - 1; // ...
                    if (lx < 0) lx = 0;
                    if (lx >= w) lx = w - 1;
                    pixels[rx + uh] = color; // Quadrant I (Actually an octant)
                    pixels[lx + uh] = color; // Quadrant II
                    pixels[lx + lh] = color; // Quadrant III
                    pixels[rx + lh] = color; // Quadrant IV

                    y++;
                    yStopping += xrSqTwo;
                    err += yChg;
                    yChg += xrSqTwo;
                    if ((xChg + (err << 1)) > 0)
                    {
                        x--;
                        xStopping -= yrSqTwo;
                        err += xChg;
                        xChg += yrSqTwo;
                    }
                }

                // ReInit vars
                x = 0;
                y = yr;
                uy = yc + y; // Upper half
                ly = yc - y; // Lower half
                if (uy < 0) uy = 0; // Clip
                if (uy >= h) uy = h - 1; // ...
                if (ly < 0) ly = 0;
                if (ly >= h) ly = h - 1;
                uh = uy*w; // Upper half
                lh = ly*w; // Lower half
                xChg = yr*yr;
                yChg = xr*xr*(1 - (yr << 1));
                err = 0;
                xStopping = 0;
                yStopping = xrSqTwo*yr;

                // Draw second set of points clockwise where tangent line slope < -1.
                while (xStopping <= yStopping)
                {
                    // Draw 4 quadrant points at once
                    rx = xc + x;
                    lx = xc - x;
                    if (rx < 0) rx = 0; // Clip
                    if (rx >= w) rx = w - 1; // ...
                    if (lx < 0) lx = 0;
                    if (lx >= w) lx = w - 1;
                    pixels[rx + uh] = color; // Quadrant I (Actually an octant)
                    pixels[lx + uh] = color; // Quadrant II
                    pixels[lx + lh] = color; // Quadrant III
                    pixels[rx + lh] = color; // Quadrant IV

                    x++;
                    xStopping += yrSqTwo;
                    err += xChg;
                    xChg += yrSqTwo;
                    if ((yChg + (err << 1)) > 0)
                    {
                        y--;
                        uy = yc + y; // Upper half
                        ly = yc - y; // Lower half
                        if (uy < 0) uy = 0; // Clip
                        if (uy >= h) uy = h - 1; // ...
                        if (ly < 0) ly = 0;
                        if (ly >= h) ly = h - 1;
                        uh = uy*w; // Upper half
                        lh = ly*w; // Lower half
                        yStopping -= xrSqTwo;
                        err += yChg;
                        yChg += xrSqTwo;
                    }
                }
#if !SILVERLIGHT
            }
            bmp.AddDirtyRect(new Int32Rect(0, 0, bmp.PixelWidth, bmp.PixelHeight));
            bmp.Unlock();
#endif
        }
Exemplo n.º 24
0
        public static void SetPixel(this WriteableBitmap wb, int x, int y, Color c)
        {
            if (y > wb.PixelHeight - 1 || x > wb.PixelWidth - 1)
            {
                return;
            }

            if (y < 0 || x < 0)
            {
                return;
            }

            if (!wb.Format.Equals(PixelFormats.Bgra32))
            {
                return;
            }

            wb.Lock();
            IntPtr buff = wb.BackBuffer;
            int stride = wb.BackBufferStride;

            unsafe
            {
                byte* pbuff = (byte*)buff.ToPointer();
                int loc = y * stride + x * 4;
                pbuff[loc]     = c.B;
                pbuff[loc + 1] = c.G;
                pbuff[loc + 2] = c.R;
                pbuff[loc + 3] = c.A;
            }

            wb.AddDirtyRect(new Int32Rect(x, y, 1, 1));
            wb.Unlock();
        }