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));
        }
Пример #2
0
        /// <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);
Пример #3
0
        /// <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))));
 }
Пример #6
0
        /// <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));
        }
Пример #7
0
        /// <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);
        }
    }
Пример #8
0
        /// <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)));
 }