void DrawBitmap(MemBitmap memBmp, double left, double top, int srcX, int srcY, int srcW, int srcH) { //check image caching system if (_renderQuality == RenderQuality.Fast) { TempMemPtr tmp = MemBitmap.GetBufferPtr(memBmp); unsafe { BitmapBuffer srcBmp = new BitmapBuffer(memBmp.Width, memBmp.Height, tmp.Ptr, tmp.LengthInBytes); try { var src = new BitmapBufferEx.RectD(srcX, srcY, srcW, srcH); var dest = new BitmapBufferEx.RectD(left, top, srcW, srcH); BitmapBuffer bmpBuffer = new BitmapBuffer(memBmp.Width, memBmp.Height, tmp.Ptr, tmp.LengthInBytes); _bxt.CopyBlit(dest, bmpBuffer, src); } catch (Exception ex) { } } return; } //save, restore later... bool useSubPix = UseSubPixelLcdEffect; //before render an image we turn off vxs subpixel rendering this.UseSubPixelLcdEffect = false; if (_orientation == RenderSurfaceOrientation.LeftTop) { //place left upper corner at specific x y _aggsx.Render(memBmp, left, this.Height - (top + memBmp.Height), srcX, srcY, srcW, srcH); } else { //left-bottom as original //place left-lower of the img at specific (x,y) _aggsx.Render(memBmp, left, top, srcX, srcY, srcW, srcH); } //restore... this.UseSubPixelLcdEffect = useSubPix; }
void DrawBitmap(ActualBitmap actualBmp, double left, double top, int srcX, int srcY, int srcW, int srcH) { //check image caching system if (this._renderQuality == RenderQualtity.Fast) { BitmapBuffer srcBmp = new BitmapBuffer(actualBmp.Width, actualBmp.Height, ActualBitmap.GetBuffer(actualBmp)); try { var src = new BitmapBufferEx.RectD(srcX, srcY, srcW, srcH); var dest = new BitmapBufferEx.RectD(left, top, srcW, srcH); BitmapBuffer bmpBuffer = new BitmapBuffer(actualBmp.Width, actualBmp.Height, ActualBitmap.GetBuffer(actualBmp)); this._bxt.CopyBlit(dest, bmpBuffer, src); } catch (Exception ex) { } return; } //save, restore later... bool useSubPix = UseSubPixelLcdEffect; //before render an image we turn off vxs subpixel rendering this.UseSubPixelLcdEffect = false; _aggsx.UseSubPixelRendering = false; if (this._orientation == DrawBoardOrientation.LeftTop) { //place left upper corner at specific x y this._aggsx.Render(actualBmp, left, this.Height - (top + actualBmp.Height), srcX, srcY, srcW, srcH); } else { //left-bottom as original //place left-lower of the img at specific (x,y) this._aggsx.Render(actualBmp, left, top, srcX, srcY, srcW, srcH); } //restore... this.UseSubPixelLcdEffect = useSubPix; _aggsx.UseSubPixelRendering = useSubPix; }
/// <summary> /// Compute the bit code for a point (x, y) using the clip rectangle /// bounded diagonally by (xmin, ymin), and (xmax, ymax) /// ASSUME THAT xmax , xmin , ymax and ymin are global constants. /// </summary> /// <param name="extents">The extents.</param> /// <param name="x">The x.</param> /// <param name="y">The y.</param> /// <returns></returns> private static byte ComputeOutCode(RectD extents, double x, double y) { // initialized as being inside of clip window byte code = INSIDE; if (x < extents.Left) // to the left of clip window { code |= LEFT; } else if (x > extents.Right) // to the right of clip window { code |= RIGHT; } if (y > extents.Bottom) // below the clip window { code |= BOTTOM; } else if (y < extents.Top) // above the clip window { code |= TOP; } return(code); }
private bool IntersectsWithInclusive(RectD r) { return(!((Left > r.Right) || (Right < r.Left) || (Top > r.Bottom) || (Bottom < r.Top))); }
public abstract RectD TransformBounds(RectD r1);
internal static bool CohenSutherlandLineClipWithViewPortOffset(RectD viewPort, ref float xi0, ref float yi0, ref float xi1, ref float yi1, int offset) { RectD viewPortWithOffset = new RectD(viewPort.X - offset, viewPort.Y - offset, viewPort.Width + 2 * offset, viewPort.Height + 2 * offset); return(CohenSutherlandLineClip(viewPortWithOffset, ref xi0, ref yi0, ref xi1, ref yi1)); }
/// <summary> /// Draws a line using a pen / stamp for the line /// </summary> /// <param name="context">The context containing the pixels as int RGBA value.</param> /// <param name="w">The width of one scanline in the pixels array.</param> /// <param name="h">The height of the bitmap.</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="pen">The pen context.</param> public static void DrawLinePenned(BitmapContext context, int w, int h, int x1, int y1, int x2, int y2, BitmapContext pen, RectD?clipRect = null) { // Edge case where lines that went out of vertical bounds clipped instead of disappearing if ((y1 < 0 && y2 < 0) || (y1 > h && y2 > h)) { return; } if (x1 == x2 && y1 == y2) { return; } // Perform cohen-sutherland clipping if either point is out of the viewport if (!CohenSutherlandLineClip(clipRect ?? new RectD(0, 0, w, h), ref x1, ref y1, ref x2, ref y2)) { return; } int size = pen.WriteableBitmap.PixelWidth; int pw = size; var srcRect = new RectD(0, 0, size, size); // 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; var destRect = new RectD(x, y, size, size); if (y < h && y >= 0 && x < w && x >= 0) { //Blit(context.WriteableBitmap, new Rect(x,y,3,3), pen.WriteableBitmap, new Rect(0,0,3,3)); Blit(context, w, h, destRect, pen, srcRect, pw); //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) { //Blit(context, w, h, destRect, pen, srcRect, pw); Blit(context, w, h, new RectD(x, y, size, size), pen, srcRect, pw); //Blit(context.WriteableBitmap, destRect, pen.WriteableBitmap, srcRect); //pixels[y * w + x] = color; } } }
/// <summary> /// Draws a colored line by connecting two points using an optimized DDA. /// Uses the pixels array and the width directly for best performance. /// </summary> /// <param name="context">The context containing the pixels as int RGBA value.</param> /// <param name="pixelWidth">The width of one scanline in the pixels array.</param> /// <param name="pixelHeight">The height of the bitmap.</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 unsafe void DrawLine(BitmapContext context, int pixelWidth, int pixelHeight, int x1, int y1, int x2, int y2, int color, RectD?clipRect = null) { // Get clip coordinates int clipX1 = 0; int clipX2 = pixelWidth; int clipY1 = 0; int clipY2 = pixelHeight; if (clipRect.HasValue) { RectD c = clipRect.Value; clipX1 = (int)c.X; clipX2 = (int)(c.X + c.Width); clipY1 = (int)c.Y; clipY2 = (int)(c.Y + c.Height); } // Perform cohen-sutherland clipping if either point is out of the viewport if (!CohenSutherlandLineClip(new RectD(clipX1, clipY1, clipX2 - clipX1, clipY2 - clipY1), ref x1, ref y1, ref x2, ref y2)) { return; } int *pixels = context.Pixels._inf32Buffer; // Distance start and end point int dx = x2 - x1; int dy = y2 - y1; const int PRECISION_SHIFT = 8; // Determine slope (absolute value) int lenX, lenY; if (dy >= 0) { lenY = dy; } else { lenY = -dy; } if (dx >= 0) { lenX = dx; } else { lenX = -dx; } if (lenX > lenY) { // x increases by +/- 1 if (dx < 0) { int t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } // Init steps and start int incy = (dy << PRECISION_SHIFT) / dx; int y1s = y1 << PRECISION_SHIFT; int y2s = y2 << PRECISION_SHIFT; int hs = pixelHeight << PRECISION_SHIFT; if (y1 < y2) { if (y1 >= clipY2 || y2 < clipY1) { return; } if (y1s < 0) { if (incy == 0) { return; } int oldy1s = y1s; // Find lowest y1s that is greater or equal than 0. y1s = incy - 1 + ((y1s + 1) % incy); x1 += (y1s - oldy1s) / incy; } if (y2s >= hs) { if (incy != 0) { // Find highest y2s that is less or equal than ws - 1. // y2s = y1s + n * incy. Find n. y2s = hs - 1 - (hs - 1 - y1s) % incy; x2 = x1 + (y2s - y1s) / incy; } } } else { if (y2 >= clipY2 || y1 < clipY1) { return; } if (y1s >= hs) { if (incy == 0) { return; } int oldy1s = y1s; // Find highest y1s that is less or equal than ws - 1. // y1s = oldy1s + n * incy. Find n. y1s = hs - 1 + (incy - (hs - 1 - oldy1s) % incy); x1 += (y1s - oldy1s) / incy; } if (y2s < 0) { if (incy != 0) { // Find lowest y2s that is greater or equal than 0. // y2s = y1s + n * incy. Find n. y2s = y1s % incy; x2 = x1 + (y2s - y1s) / incy; } } } if (x1 < 0) { y1s -= incy * x1; x1 = 0; } if (x2 >= pixelWidth) { x2 = pixelWidth - 1; } int ys = y1s; // Walk the line! int y = ys >> PRECISION_SHIFT; int previousY = y; int index = x1 + y * pixelWidth; int k = incy < 0 ? 1 - pixelWidth : 1 + pixelWidth; for (int x = x1; x <= x2; ++x) { pixels[index] = color; ys += incy; y = ys >> PRECISION_SHIFT; if (y != previousY) { previousY = y; index += k; } else { ++index; } } } else { // Prevent division by zero if (lenY == 0) { return; } if (dy < 0) { int t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } // Init steps and start int x1s = x1 << PRECISION_SHIFT; int x2s = x2 << PRECISION_SHIFT; int ws = pixelWidth << PRECISION_SHIFT; int incx = (dx << PRECISION_SHIFT) / dy; if (x1 < x2) { if (x1 >= clipX2 || x2 < clipX1) { return; } if (x1s < 0) { if (incx == 0) { return; } int oldx1s = x1s; // Find lowest x1s that is greater or equal than 0. x1s = incx - 1 + ((x1s + 1) % incx); y1 += (x1s - oldx1s) / incx; } if (x2s >= ws) { if (incx != 0) { // Find highest x2s that is less or equal than ws - 1. // x2s = x1s + n * incx. Find n. x2s = ws - 1 - (ws - 1 - x1s) % incx; y2 = y1 + (x2s - x1s) / incx; } } } else { if (x2 >= clipX2 || x1 < clipX1) { return; } if (x1s >= ws) { if (incx == 0) { return; } int oldx1s = x1s; // Find highest x1s that is less or equal than ws - 1. // x1s = oldx1s + n * incx. Find n. x1s = ws - 1 + (incx - (ws - 1 - oldx1s) % incx); y1 += (x1s - oldx1s) / incx; } if (x2s < 0) { if (incx != 0) { // Find lowest x2s that is greater or equal than 0. // x2s = x1s + n * incx. Find n. x2s = x1s % incx; y2 = y1 + (x2s - x1s) / incx; } } } if (y1 < 0) { x1s -= incx * y1; y1 = 0; } if (y2 >= pixelHeight) { y2 = pixelHeight - 1; } int index = x1s; int indexBaseValue = y1 * pixelWidth; // Walk the line! int inc = (pixelWidth << PRECISION_SHIFT) + incx; for (int y = y1; y <= y2; ++y) { pixels[indexBaseValue + (index >> PRECISION_SHIFT)] = color; index += inc; } } }
/// <summary> /// Cohen–Sutherland clipping algorithm clips a line from /// P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with /// diagonal from (xmin, ymin) to (xmax, ymax). /// </summary> /// <remarks>See http://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm for details</remarks> /// <returns>a list of two points in the resulting clipped line, or zero</returns> internal static bool CohenSutherlandLineClip(RectD extents, ref double x0, ref double y0, ref double x1, ref double y1) { // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle byte outcode0 = ComputeOutCode(extents, x0, y0); byte outcode1 = ComputeOutCode(extents, x1, y1); // No clipping if both points lie inside viewport if (outcode0 == INSIDE && outcode1 == INSIDE) { return(true); } bool isValid = false; while (true) { // Bitwise OR is 0. Trivially accept and get out of loop if ((outcode0 | outcode1) == 0) { isValid = true; break; } // Bitwise AND is not 0. Trivially reject and get out of loop else if ((outcode0 & outcode1) != 0) { break; } else { // failed both tests, so calculate the line segment to clip // from an outside point to an intersection with clip edge double x, y; // At least one endpoint is outside the clip rectangle; pick it. byte outcodeOut = (outcode0 != 0) ? outcode0 : outcode1; // Now find the intersection point; // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0) if ((outcodeOut & TOP) != 0) { // point is above the clip rectangle x = x0 + (x1 - x0) * (extents.Top - y0) / (y1 - y0); y = extents.Top; } else if ((outcodeOut & BOTTOM) != 0) { // point is below the clip rectangle x = x0 + (x1 - x0) * (extents.Bottom - y0) / (y1 - y0); y = extents.Bottom; } else if ((outcodeOut & RIGHT) != 0) { // point is to the right of clip rectangle y = y0 + (y1 - y0) * (extents.Right - x0) / (x1 - x0); x = extents.Right; } else if ((outcodeOut & LEFT) != 0) { // point is to the left of clip rectangle y = y0 + (y1 - y0) * (extents.Left - x0) / (x1 - x0); x = extents.Left; } else { x = double.NaN; y = double.NaN; } // Now we move outside point to intersection point to clip // and get ready for next pass. if (outcodeOut == outcode0) { x0 = x; y0 = y; outcode0 = ComputeOutCode(extents, x0, y0); } else { x1 = x; y1 = y; outcode1 = ComputeOutCode(extents, x1, y1); } } } return(isValid); }
/// <summary> /// Intersect Method /// </summary> /// /// <remarks> /// Replaces the Rectangle with the intersection of itself /// and another Rectangle. /// </remarks> public void Intersect(RectD rect) { this = RectD.Intersect(this, rect); }
/// <summary> /// Creates a new cropped WriteableBitmap. /// </summary> /// <param name="bmp">The WriteableBitmap.</param> /// <param name="region">The rectangle that defines the crop region.</param> /// <returns>A new WriteableBitmap that is a cropped version of the input.</returns> public static BitmapBuffer Crop(this BitmapBuffer bmp, RectD region) { return(bmp.Crop((int)region.X, (int)region.Y, (int)region.Width, (int)region.Height)); }