/// <summary> /// Sets the color of the pixel. /// For best performance this method should not be used in iterative real-time scenarios. Implement the code directly inside a loop. /// </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 BitmapBuffer bmp, int x, int y, ColorInt color) { using (BitmapContext context = bmp.GetBitmapContext()) { context.Pixels[y * context.Width + x] = color.ToPreMultAlphaColor(); } }
/// <summary> /// Sets the color of the pixel using an extra alpha value and a precalculated index (faster). /// For best performance this method should not be used in iterative real-time scenarios. Implement the code directly inside a loop. /// </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 BitmapBuffer bmp, int index, byte a, ColorInt color) { using (BitmapContext context = bmp.GetBitmapContext()) { context.Pixels[index] = color.ToPreMultAlphaColor(); } }
public static void Clear(this BitmapContext context, ColorInt color) { int colr = color.ToPreMultAlphaColor(); int[] pixels = context.Pixels; int w = context.Width; int h = context.Height; int len = w * ARGB_SIZE; // Fill first line for (int x = 0; x < w; x++) { pixels[x] = colr; } // Copy first line int blockHeight = 1; int y = 1; while (y < h) { BitmapContext.BlockCopy(context, 0, context, y * len, blockHeight * len); y += blockHeight; blockHeight = Math.Min(2 * blockHeight, h - y); } }
/// <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 BitmapBuffer bmp, ColorInt color) { using (BitmapContext context = bmp.GetBitmapContext()) { Clear(context, color); } }
/// <summary> /// Sets the color of the pixel using an extra alpha value. /// For best performance this method should not be used in iterative real-time scenarios. Implement the code directly inside a loop. /// </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 BitmapBuffer bmp, int x, int y, byte a, ColorInt color) { using (BitmapContext context = bmp.GetBitmapContext()) { // Add one to use mul and cheap bit shift for multiplicaltion context.Pixels[y * context.Width + x] = color.ToPreMultAlphaColor(); } }
/// <summary> /// Draws circles that decrease in size to build a flower that is animated /// </summary> private void DrawEllipsesFlower(BitmapBuffer writeableBmp) { // Init some size vars int w = writeableBmp.PixelWidth - 2; int h = writeableBmp.PixelHeight - 2; // Wrap updates in a GetContext call, to prevent invalidation and nested locking/unlocking during this block using (writeableBmp.GetBitmapContext()) { // Increment frame counter if (++frameCounter >= int.MaxValue || frameCounter < 1) { frameCounter = 1; } double s = Math.Sin(frameCounter * 0.01); if (s < 0) { s *= -1; } // Clear writeableBmp.Clear(); // Draw center circle int xc = w >> 1; int yc = h >> 1; // Animate base size with sine int r0 = (int)((w + h) * 0.07 * s) + 10; BitmapBufferEx.ColorInt color_brown = BitmapBufferEx.ColorInt.FromArgb( 255, System.Drawing.Color.Brown.R, System.Drawing.Color.Brown.G, System.Drawing.Color.Brown.B); writeableBmp.DrawEllipseCentered(xc, yc, r0, r0, color_brown); // Draw outer circles int dec = (int)((w + h) * 0.0045f); int r = (int)((w + h) * 0.025f); int offset = r0 + r; for (int i = 1; i < 6 && r > 1; i++) { for (double f = 1; f < 7; f += 0.7) { // Calc postion based on unit circle int xc2 = (int)(Math.Sin(frameCounter * 0.002 * i + f) * offset + xc); int yc2 = (int)(Math.Cos(frameCounter * 0.002 * i + f) * offset + yc); int col = (int)(0xFFFF0000 | (uint)(0x1A * i) << 8 | (uint)(0x20 * f)); writeableBmp.DrawEllipseCentered(xc2, yc2, r, r, col); } // Next ring offset += r; r -= dec; offset += r; } // Invalidates on exit of using block } }
public static ColorInt CreateNew(ColorInt oldColor, byte a) { ColorInt c = new ColorInt(); c._r = oldColor._r; c._g = oldColor._g; c._b = oldColor._b; c._a = a; return(c); }
public static ColorInt FromArgb(byte a, byte r, byte g, byte b) { ColorInt c = new ColorInt(); c._r = r; c._g = g; c._b = b; c._a = a; return(c); }
public static ColorInt FromArgb(int argb) { ColorInt c = new ColorInt(); c._a = (byte)((argb >> 24)); c._r = (byte)((argb >> 16) & 0xff); c._g = (byte)((argb >> 8) & 0xff); c._b = (byte)((argb >> 0) & 0xff); return(c); }
public override bool Equals(object obj) { if (obj is ColorInt) { ColorInt c = (ColorInt)obj; return(c._a == this._a && c._b == this._b && c._r == this._r && c._g == this._g); } return(false); }
/// <summary> /// Gets the color of the pixel at the x, y coordinate as a Color struct. /// For best performance this method should not be used in iterative real-time scenarios. Implement the code directly inside a loop. /// </summary> /// <param name="bmp">The WriteableBitmap.</param> /// <param name="x">The x coordinate of the pixel.</param> /// <param name="y">The y coordinate of the pixel.</param> /// <returns>The color of the pixel at x, y as a Color struct.</returns> public static ColorInt dbugGetPixel(this BitmapBuffer bmp, int x, int y) { using (BitmapContext context = bmp.GetBitmapContext(ReadWriteMode.ReadOnly)) { int c = context.Pixels[y * context.Width + x]; byte a = (byte)(c >> 24); // Prevent division by zero int ai = a; if (ai == 0) { ai = 1; } // Scale inverse alpha to use cheap integer mul bit shift ai = ((255 << 8) / ai); return(ColorInt.FromArgb(a, (byte)((((c >> 16) & 0xFF) * ai) >> 8), (byte)((((c >> 8) & 0xFF) * ai) >> 8), (byte)((((c & 0xFF) * ai) >> 8)))); } }
/// <summary> /// check if this color is equals on another compare on RGB only, not alpha /// </summary> /// <param name="another"></param> /// <returns></returns> public bool EqualsOnRGB(ref ColorInt c2) { return((uint)((R << 16) | (G << 8) | (B)) == (uint)((c2.R << 16) | (c2.G << 8) | (c2.B))); }
public static ColorInt CreateNew(ColorInt oldColor, byte a) => new ColorInt(a, oldColor.R, oldColor.G, oldColor.B);
/// <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> /// <param name="clipRect">The region in the image to restrict drawing to.</param> public static void DrawLineBresenham(this BitmapBuffer bmp, int x1, int y1, int x2, int y2, ColorInt color, RectD?clipRect = null) { bmp.DrawLineBresenham(x1, y1, x2, y2, color.ToPreMultAlphaColor(), clipRect); }
/// <summary> /// Draws an anti-aliased line with a desired stroke thickness /// <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> /// <param name="strokeThickness">The stroke thickness of the line.</param> /// </summary> public static void DrawLineAa(this BitmapBuffer bmp, int x1, int y1, int x2, int y2, ColorInt color, int strokeThickness, RectD?clipRect = null) { using (BitmapContext context = bmp.GetBitmapContext()) { AAWidthLine(bmp.PixelWidth, bmp.PixelHeight, context, x1, y1, x2, y2, strokeThickness, color.ToPreMultAlphaColor(), clipRect); } }
/// <summary> /// Draws an anti-aliased line with a desired stroke thickness /// <param name="context">The context containing the pixels as int RGBA value.</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> /// <param name="strokeThickness">The stroke thickness of the line.</param> /// </summary> public static void DrawLineAa(BitmapContext context, int pixelWidth, int pixelHeight, int x1, int y1, int x2, int y2, ColorInt color, int strokeThickness, RectD?clipRect = null) { AAWidthLine(pixelWidth, pixelHeight, context, x1, y1, x2, y2, strokeThickness, color.ToPreMultAlphaColor(), clipRect); }
/// <summary> /// Draws the different types of shapes. /// </summary> private void DrawStaticShapes(BitmapBuffer writeableBmp) { // HideShapeCountText(); // Wrap updates in a GetContext call, to prevent invalidation and nested locking/unlocking during this block using (writeableBmp.GetBitmapContext()) { // Init some size vars int w = writeableBmp.PixelWidth; int h = writeableBmp.PixelHeight; int w3 = w / 3; int h3 = h / 3; int w6 = w3 >> 1; int h6 = h3 >> 1; int w12 = w6 >> 1; int h12 = h6 >> 1; // Clear writeableBmp.Clear(); // Fill closed concave polygon var p = new int[] { w12 >> 1, h12, w6, h3 - (h12 >> 1), w3 - (w12 >> 1), h12, w6 + w12, h12, w6, h6 + h12, w12, h12, w12 >> 1, h12, }; writeableBmp.FillPolygonsEvenOdd(new[] { p }, GetRandomColor()); // Fill closed convex polygon p = new int[] { w3 + w6, h12 >> 1, w3 + w6 + w12, h12, w3 + w6 + w12, h6 + h12, w3 + w6, h6 + h12 + (h12 >> 1), w3 + w12, h6 + h12, w3 + w12, h12, w3 + w6, h12 >> 1, }; writeableBmp.FillPolygon(p, GetRandomColor()); // Fill Triangle + Quad writeableBmp.FillTriangle(2 * w3 + w6, h12 >> 1, 2 * w3 + w6 + w12, h6 + h12, 2 * w3 + w12, h6 + h12, GetRandomColor()); writeableBmp.FillQuad(w6, h3 + (h12 >> 1), w6 + w12, h3 + h6, w6, h3 + h6 + h12 + (h12 >> 1), w12, h3 + h6, GetRandomColor()); // Fill Ellipses writeableBmp.FillEllipse(rand.Next(w3, w3 + w6), rand.Next(h3, h3 + h6), rand.Next(w3 + w6, 2 * w3), rand.Next(h3 + h6, 2 * h3), GetRandomColor()); writeableBmp.FillEllipseCentered(2 * w3 + w6, h3 + h6, w12, h12, GetRandomColor()); // Fill closed Cardinal Spline curve p = new int[] { w12 >> 1, 2 * h3 + h12, w6, h - (h12 >> 1), w3 - (w12 >> 1), 2 * h3 + h12, w6 + w12, 2 * h3 + h12, w6, 2 * h3 + (h12 >> 1), w12, 2 * h3 + h12, }; writeableBmp.FillCurveClosed(p, 0.5f, GetRandomColor()); // Fill closed Beziér curve p = new int[] { w3 + w12, 2 * h3 + h6 + h12, w3 + w6 + (w12 >> 1), 2 * h3, w3 + w6 + w12 + (w12 >> 1), 2 * h3, w3 + w6 + w12, 2 * h3 + h6 + h12, }; writeableBmp.FillBeziers(p, GetRandomColor()); // Fill Rectangle writeableBmp.FillRectangle(rand.Next(2 * w3, 2 * w3 + w6), rand.Next(2 * h3, 2 * h3 + h6), rand.Next(2 * w3 + w6, w), rand.Next(2 * h3 + h6, h), GetRandomColor()); // Fill another rectangle with alpha blending writeableBmp.FillRectangle(rand.Next(2 * w3, 2 * w3 + w6), rand.Next(2 * h3, 2 * h3 + h6), rand.Next(2 * w3 + w6, w), rand.Next(2 * h3 + h6, h), GetRandomColor(), true); BitmapBufferEx.ColorInt black = BitmapBufferEx.ColorInt.FromArgb(255, 0, 0, 0); // Draw Grid writeableBmp.DrawLine(0, h3, w, h3, Colors.Black); writeableBmp.DrawLine(0, 2 * h3, w, 2 * h3, Colors.Black); writeableBmp.DrawLine(w3, 0, w3, h, Colors.Black); writeableBmp.DrawLine(2 * w3, 0, 2 * w3, h, Colors.Black); // Invalidates on exit of Using block } }
/// <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 BitmapBuffer bmp, int x1, int y1, int cx1, int cy1, int cx2, int cy2, int x2, int y2, ColorInt color) { bmp.DrawBezier(x1, y1, cx1, cy1, cx2, cy2, x2, y2, color.ToPreMultAlphaColor()); }
/// <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 BitmapBuffer bmp, int[] points, float tension, ColorInt color) { bmp.DrawCurveClosed(points, tension, color.ToPreMultAlphaColor()); }
/// <summary> /// Draws a series of cubic Beziér splines each defined by start, end and two control points. /// The ending point of the previous curve is used as starting point for the next. /// Therefore the initial curve needs four points and the subsequent 3 (2 control and 1 end point). /// </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, cx1, cy1, cx2, cy2, x2, y2, cx3, cx4 ..., xn, yn).</param> /// <param name="color">The color for the spline.</param> public static void DrawBeziers(this BitmapBuffer bmp, int[] points, ColorInt color) { bmp.DrawBeziers(points, color.ToPreMultAlphaColor()); }
/// <summary> /// check if this color is equals on another compare on RGB only, not alpha /// </summary> /// <param name="another"></param> /// <returns></returns> public bool EqualsOnRGB(ref ColorInt c2) { return((uint)((this._r << 16) | (this._g << 8) | (this._b)) == (uint)((c2._r << 16) | (c2._g << 8) | (c2._b))); }