public static PipelineBuilder FromTiles(Uri uri, DpiMode dpiMode = DpiMode.DisplayDpiWith96AsLowerBound, CacheMode cacheMode = CacheMode.Default) { var image = FromImage(uri, dpiMode, cacheMode); async ValueTask <IGraphicsEffectSource> Factory() => new BorderEffect { ExtendX = CanvasEdgeBehavior.Wrap, ExtendY = CanvasEdgeBehavior.Wrap, Source = await image.sourceProducer() }; return(new PipelineBuilder(image, Factory)); }
/// <summary> /// Loads a <see cref="CompositionSurfaceBrush"/> from the input <see cref="System.Uri"/>, and prepares it to be used in a tile effect /// </summary> /// <param name="creator">The resource creator to use to load the image bitmap (it can be the same <see cref="CanvasDevice"/> used later)</param> /// <param name="compositor">The compositor instance to use to create the final brush</param> /// <param name="canvasDevice">The device to use to process the Win2D image</param> /// <param name="uri">The path to the image to load</param> /// <param name="dpiMode">Indicates the desired DPI mode to use when loading the image</param> private static async Task <CompositionSurfaceBrush> LoadSurfaceBrushAsync( ICanvasResourceCreator creator, Compositor compositor, CanvasDevice canvasDevice, Uri uri, DpiMode dpiMode) { CanvasBitmap bitmap = null; try { // Load the bitmap with the appropriate settings DisplayInformation display = DisplayInformation.GetForCurrentView(); float dpi = display.LogicalDpi; switch (dpiMode) { case DpiMode.UseSourceDpi: bitmap = await CanvasBitmap.LoadAsync(creator, uri); break; case DpiMode.Default96Dpi: bitmap = await CanvasBitmap.LoadAsync(creator, uri, 96); break; case DpiMode.DisplayDpi: bitmap = await CanvasBitmap.LoadAsync(creator, uri, dpi); break; case DpiMode.DisplayDpiWith96AsLowerBound: bitmap = await CanvasBitmap.LoadAsync(creator, uri, dpi >= 96?dpi : 96); break; default: throw new ArgumentOutOfRangeException(nameof(dpiMode), "Unsupported DPI mode"); } // Get the device and the target surface CompositionGraphicsDevice device = CanvasComposition.CreateCompositionGraphicsDevice(compositor, canvasDevice); CompositionDrawingSurface surface = device.CreateDrawingSurface(default, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
/// <summary> /// Loads a <see cref="CompositionBrush"/> instance with the target image from the shared <see cref="CanvasDevice"/> instance /// </summary> /// <param name="uri">The path to the image to load</param> /// <param name="dpiMode">Indicates the desired DPI mode to use when loading the image</param> /// <param name="cacheMode">Indicates the cache option to use to load the image</param> /// <returns>A <see cref="Task{T}"/> that returns the loaded <see cref="CompositionBrush"/> instance</returns> public static async Task <CompositionBrush> LoadImageAsync(Uri uri, DpiMode dpiMode, CacheMode cacheMode = CacheMode.Default) { var compositor = Window.Current.Compositor; // Lock and check the cache first using (await Win2DMutex.LockAsync()) { uri = uri.ToAppxUri(); if (cacheMode == CacheMode.Default && Cache.TryGetValue(compositor, uri, out var cached)) { return(cached); } // Load the image CompositionBrush brush; try { // This will throw and the canvas will re-initialize the Win2D device if needed var sharedDevice = CanvasDevice.GetSharedDevice(); brush = await LoadSurfaceBrushAsync(sharedDevice, compositor, uri, dpiMode); } catch { // Device error brush = null; } // Cache when needed and return the result if (brush != null && cacheMode != CacheMode.Disabled) { Cache.AddOrUpdate(compositor, uri, brush); } return(brush); } }
public static PipelineBuilder FromTiles(string relativePath, DpiMode dpiMode = DpiMode.DisplayDpiWith96AsLowerBound, CacheMode cacheMode = CacheMode.Default) { return(FromTiles(relativePath.ToAppxUri(), dpiMode, cacheMode)); }
public static PipelineBuilder FromImage(Uri uri, DpiMode dpiMode = DpiMode.DisplayDpiWith96AsLowerBound, CacheMode cacheMode = CacheMode.Default) { return(new PipelineBuilder(() => new ValueTask <CompositionBrush>(SurfaceLoader.LoadImageAsync(uri, dpiMode, cacheMode)))); }
/// <summary> /// Loads a <see cref="CompositionSurfaceBrush"/> instance with the target image /// </summary> /// <param name="canvas">The <see cref="CanvasControl"/> to use to load the target image</param> /// <param name="uri">The path to the image to load</param> /// <param name="dpiMode">Indicates the desired DPI mode to use when loading the image</param> /// <param name="cache">Indicates the cache option to use to load the image</param> public static Task <CompositionSurfaceBrush> LoadImageAsync(this CanvasControl canvas, Uri uri, DpiMode dpiMode, CacheMode cache = CacheMode.Default) { return(LoadImageAsync(Window.Current.Compositor, canvas, uri, dpiMode, cache)); }
/// <summary> /// Loads a <see cref="CompositionBrush"/> from the input <see cref="System.Uri"/>, and prepares it to be used in a tile effect /// </summary> /// <param name="canvasDevice">The device to use to process the Win2D image</param> /// <param name="compositor">The compositor instance to use to create the final brush</param> /// <param name="uri">The path to the image to load</param> /// <param name="dpiMode">Indicates the desired DPI mode to use when loading the image</param> /// <returns>A <see cref="Task{T}"/> that returns the loaded <see cref="CompositionBrush"/> instance</returns> private static async Task <CompositionBrush> LoadSurfaceBrushAsync( CanvasDevice canvasDevice, Compositor compositor, Uri uri, DpiMode dpiMode) { var displayInformation = DisplayInformation.GetForCurrentView(); float dpi = displayInformation.LogicalDpi; // Load the bitmap with the appropriate settings using CanvasBitmap bitmap = dpiMode switch { DpiMode.UseSourceDpi => await CanvasBitmap.LoadAsync(canvasDevice, uri), DpiMode.Default96Dpi => await CanvasBitmap.LoadAsync(canvasDevice, uri, 96), DpiMode.DisplayDpi => await CanvasBitmap.LoadAsync(canvasDevice, uri, dpi), DpiMode.DisplayDpiWith96AsLowerBound => await CanvasBitmap.LoadAsync(canvasDevice, uri, dpi >= 96?dpi : 96), _ => throw new ArgumentOutOfRangeException(nameof(dpiMode), dpiMode, $"Invalid DPI mode: {dpiMode}") }; // Calculate the surface size Size size = bitmap.Size, sizeInPixels = new Size(bitmap.SizeInPixels.Width, bitmap.SizeInPixels.Height); // Get the device and the target surface using CompositionGraphicsDevice graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, canvasDevice); // Create the drawing surface var drawingSurface = graphicsDevice.CreateDrawingSurface( sizeInPixels, DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); // Create a drawing session for the target surface using (var drawingSession = CanvasComposition.CreateDrawingSession(drawingSurface, new Rect(0, 0, sizeInPixels.Width, sizeInPixels.Height), dpi)) { // Fill the target surface drawingSession.Clear(Color.FromArgb(0, 0, 0, 0)); drawingSession.DrawImage(bitmap, new Rect(0, 0, size.Width, size.Height), new Rect(0, 0, size.Width, size.Height)); drawingSession.EffectTileSize = new BitmapSize { Width = (uint)size.Width, Height = (uint)size.Height }; } // Setup the effect brush to use var surfaceBrush = compositor.CreateSurfaceBrush(drawingSurface); surfaceBrush.Stretch = CompositionStretch.None; double pixels = displayInformation.RawPixelsPerViewPixel; // Adjust the scale if the DPI scaling is greater than 100% if (pixels > 1) { surfaceBrush.Scale = new Vector2((float)(1 / pixels)); surfaceBrush.BitmapInterpolationMode = CompositionBitmapInterpolationMode.NearestNeighbor; } return(surfaceBrush); } }
/// <summary> /// Starts a new <see cref="PipelineBuilder"/> pipeline from a Win2D image /// </summary> /// <param name="uri">The path for the image to load</param> /// <param name="dpiMode">Indicates the desired DPI mode to use when loading the image</param> /// <param name="cache">The cache mode to use to load the image</param> public static PipelineBuilder FromImage(Uri uri, DpiMode dpiMode = DpiMode.DisplayDpiWith96AsLowerBound, CacheMode cache = CacheMode.Default) { return(new PipelineBuilder(() => Win2DImageHelper.LoadImageAsync(Window.Current.Compositor, uri, dpiMode, cache).ContinueWith(t => t.Result as CompositionBrush))); }
public static PipelineBuilder FromImage(Uri uri, DpiMode dpiMode = DpiMode.DisplayDpiWith96AsLowerBound, CacheMode cacheMode = CacheMode.Default) { return(new PipelineBuilder(async() => await SurfaceLoader.LoadImageAsync(uri, dpiMode, cacheMode))); }