/// <summary> /// Sets the contents of the region to the specified path. /// </summary> /// <param name="region">The region to set the path into.</param> /// <param name="path">The path object.</param> /// <param name="usePathBounds">Whether to set the region's new bounds to the bounds of the path itself.</param> internal static bool SetPath(this SKRegion region, SKPath path, bool usePathBounds) { if (usePathBounds && path.GetBounds(out SKRect bounds)) { using SKRegion clip = new SKRegion(); clip.SetRect(SKRectI.Ceiling(bounds)); return(region.SetPath(path, clip)); } else { return(region.SetPath(path)); } }
//Default resolution makes 10 points per line segment private bool IsInside(SKPath pInput, SKPath pBoundary) { var input = new SKRegion(); var boundary = new SKRegion(); input.SetRect(ToIntRect(pInput.Bounds)); boundary.SetRect(ToIntRect(pBoundary.Bounds)); input.SetPath(pInput); boundary.SetPath(pBoundary); var contained = boundary.Contains(input); return(contained); }
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) { SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); int radius = 10; // Create circular path using (SKPath circlePath = new SKPath()) { circlePath.AddCircle(0, 0, radius); // Create circular region using (SKRegion circleRegion = new SKRegion()) { circleRegion.SetRect(new SKRectI(-radius, -radius, radius, radius)); circleRegion.SetPath(circlePath); // Set transform to move it to center and scale up canvas.Translate(info.Width / 2, info.Height / 2); canvas.Scale(Math.Min(info.Width / 2, info.Height / 2) / radius); // Fill region using (SKPaint fillPaint = new SKPaint()) { fillPaint.Style = SKPaintStyle.Fill; fillPaint.Color = SKColors.Orange; canvas.DrawRegion(circleRegion, fillPaint); } // Stroke path for comparison using (SKPaint strokePaint = new SKPaint()) { strokePaint.Style = SKPaintStyle.Stroke; strokePaint.Color = SKColors.Blue; strokePaint.StrokeWidth = 0.1f; canvas.DrawPath(circlePath, strokePaint); } } } }
public void SetPathWithClipDoesCreatesCorrectRegion() { var clipRect = new SKRectI(25, 25, 50, 50); var clip = new SKRegion(); clip.SetRect(clipRect); var rect = new SKRectI(10, 20, 30, 40); var path = new SKPath(); path.AddRect(rect); var region = new SKRegion(); var isNonEmpty = region.SetPath(path, clip); Assert.IsTrue(isNonEmpty); Assert.AreEqual(SKRectI.Intersect(clipRect, rect), region.Bounds); }
void DisplayClipOp(SKCanvas canvas, SKRect rect, SKRegionOperation regionOp) { float textSize = textPaint.TextSize; canvas.DrawText(regionOp.ToString(), rect.MidX, rect.Top + textSize, textPaint); rect.Top += textSize; float radius = 0.9f * Math.Min(rect.Width / 3, rect.Height / 2); float xCenter = rect.MidX; float yCenter = rect.MidY; SKRectI recti = new SKRectI((int)rect.Left, (int)rect.Top, (int)rect.Right, (int)rect.Bottom); using (SKRegion wholeRectRegion = new SKRegion()) { wholeRectRegion.SetRect(recti); using (SKRegion region1 = new SKRegion(wholeRectRegion)) using (SKRegion region2 = new SKRegion(wholeRectRegion)) { using (SKPath path1 = new SKPath()) { path1.AddCircle(xCenter - radius / 2, yCenter, radius); region1.SetPath(path1); } using (SKPath path2 = new SKPath()) { path2.AddCircle(xCenter + radius / 2, yCenter, radius); region2.SetPath(path2); } region1.Op(region2, regionOp); canvas.Save(); canvas.ClipRegion(region1); canvas.DrawPaint(fillPaint); canvas.Restore(); } } }
/// <summary> /// Process image pipeline /// <para>Region THEN Size THEN Rotation THEN Quality THEN Format</para> /// </summary> /// <param name="imageUri">The <see cref="Uri"/> of the source image</param> /// <param name="request">The parsed and validated IIIF Image API request</param> /// <param name="quality">Image output encoding quality settings</param> /// <param name="allowSizeAboveFull">Allow output image dimensions to exceed that of the source image</param> /// <param name="pdfMetadata">Optional PDF metadata fields</param> /// <returns></returns> public async Task <Stream> ProcessImage(Uri imageUri, ImageRequest request, Conf.ImageQuality quality, bool allowSizeAboveFull, Conf.PdfMetadata pdfMetadata) { var encodingStrategy = GetEncodingStrategy(request.Format); if (encodingStrategy == EncodingStrategy.Unknown) { throw new ArgumentException("Unsupported format", "format"); } var loader = new ImageLoader { HttpClient = HttpClient, Log = Log }; (var state, var imageRegion) = await loader.ExtractRegion(imageUri, request, allowSizeAboveFull, quality); using (imageRegion) { var expectedWidth = state.OutputWidth; var expectedHeight = state.OutputHeight; var alphaType = request.Quality == ImageQuality.bitonal ? SKAlphaType.Opaque : SKAlphaType.Premul; (var angle, var originX, var originY, var newImgWidth, var newImgHeight) = Rotate(expectedWidth, expectedHeight, request.Rotation.Degrees); using (var surface = SKSurface.Create(width: newImgWidth, height: newImgHeight, colorType: SKImageInfo.PlatformColorType, alphaType: alphaType)) using (var canvas = surface.Canvas) using (var region = new SKRegion()) { // If the rotation parameter includes mirroring ("!"), the mirroring is applied before the rotation. if (request.Rotation.Mirror) { canvas.Translate(newImgWidth, 0); canvas.Scale(-1, 1); } canvas.Translate(originX, originY); canvas.RotateDegrees(angle, 0, 0); // reset clip rects to rotated boundaries region.SetRect(new SKRectI(0 - (int)originX, 0 - (int)originY, newImgWidth, newImgHeight)); canvas.ClipRegion(region); // quality if (request.Quality == ImageQuality.gray || request.Quality == ImageQuality.bitonal) { var contrast = request.Quality == ImageQuality.gray ? 0.1f : 1f; using (var cf = SKColorFilter.CreateHighContrast(true, SKHighContrastConfigInvertStyle.NoInvert, contrast)) using (var paint = new SKPaint()) { paint.FilterQuality = SKFilterQuality.High; paint.ColorFilter = cf; canvas.DrawImage(imageRegion, new SKRect(0, 0, expectedWidth, expectedHeight), paint); } } else { using (var paint = new SKPaint()) { paint.FilterQuality = SKFilterQuality.High; canvas.DrawImage(imageRegion, new SKRect(0, 0, expectedWidth, expectedHeight), paint); } } return(Encode(surface, expectedWidth, expectedHeight, encodingStrategy, request.Format, quality.GetOutputFormatQuality(request.Format), pdfMetadata, state.HorizontalResolution, state.VerticalResolution)); } } }
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) { SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); float xCenter = info.Width / 2; float yCenter = info.Height / 2; float radius = 0.24f * Math.Min(info.Width, info.Height); using (SKRegion wholeScreenRegion = new SKRegion()) { wholeScreenRegion.SetRect(new SKRectI(0, 0, info.Width, info.Height)); using (SKRegion leftRegion = new SKRegion(wholeScreenRegion)) using (SKRegion rightRegion = new SKRegion(wholeScreenRegion)) using (SKRegion topRegion = new SKRegion(wholeScreenRegion)) using (SKRegion bottomRegion = new SKRegion(wholeScreenRegion)) { using (SKPath circlePath = new SKPath()) { // Make basic circle path circlePath.AddCircle(xCenter, yCenter, radius); // Left leaf circlePath.Transform(SKMatrix.MakeTranslation(-radius, 0)); leftRegion.SetPath(circlePath); // Right leaf circlePath.Transform(SKMatrix.MakeTranslation(2 * radius, 0)); rightRegion.SetPath(circlePath); // Make union of right with left leftRegion.Op(rightRegion, SKRegionOperation.Union); // Top leaf circlePath.Transform(SKMatrix.MakeTranslation(-radius, -radius)); topRegion.SetPath(circlePath); // Combine with bottom leaf circlePath.Transform(SKMatrix.MakeTranslation(0, 2 * radius)); bottomRegion.SetPath(circlePath); // Make union of top with bottom bottomRegion.Op(topRegion, SKRegionOperation.Union); // Exclusive-OR left and right with top and bottom leftRegion.Op(bottomRegion, SKRegionOperation.XOR); // Set that as clip region canvas.ClipRegion(leftRegion); // Set transform for drawing lines from center canvas.Translate(xCenter, yCenter); // Draw 360 lines for (double angle = 0; angle < 360; angle++) { float x = 2 * radius * (float)Math.Cos(Math.PI * angle / 180); float y = 2 * radius * (float)Math.Sin(Math.PI * angle / 180); using (SKPaint strokePaint = new SKPaint()) { strokePaint.Color = SKColors.Green; strokePaint.StrokeWidth = 2; canvas.DrawLine(0, 0, x, y, strokePaint); } } } } } }