/// <summary> /// Resizes the SurfaceImage with the given size and redraws the SurfaceImage by loading /// image from the new Uri. /// </summary> /// <param name="uri">Uri of the image to be loaded onto the SurfaceImage.</param> /// <param name="size">New size of the SurfaceImage</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> /// <returns>Task</returns> public async Task RedrawAsync(Uri uri, Size size, CompositionSurfaceImageOptions options) { // If the given Uri differs from the previously stored Uri // dispose the existing canvasBitmap if (!_uri.IsEqualTo(uri)) { _canvasBitmap?.Dispose(); _canvasBitmap = null; } // Set the image options Options = options; // Resize the surface only if AutoResize option is disabled if (!Options.AutoResize) { // resize the SurfaceImage _generator.ResizeDrawingSurface(_surfaceLock, _surface, size); // Set the size Size = _surface?.Size ?? new Size(0, 0); } // Set the new Uri of the image to be loaded _uri = uri; // Reload the SurfaceImage await RedrawSurfaceImageInternalAsync(); }
/// <summary> /// Redraws the SurfaceImage with the given image options /// </summary> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> /// <returns>Task</returns> public void Redraw(CompositionSurfaceImageOptions options) { // Set the image options Options = options; // Redraw the SurfaceImage RedrawSurfaceImageInternal(); }
/// <summary> /// Disposes the resources used by the SurfaceImage /// </summary> public void Dispose() { _surface?.Dispose(); if (_generator != null) { _generator.DeviceReplaced -= OnDeviceReplaced; } _canvasBitmap?.Dispose(); _canvasBitmap = null; _surface = null; _generator = null; _uri = null; Options = null; }
/// <summary> /// Resizes the SurfaceImage to the new size. /// </summary> /// <param name="size">New size of the SurfaceImage</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> public void Resize(Size size, CompositionSurfaceImageOptions options) { // Set the image options Options = options; // Resize the surface only if AutoResize option is disabled if (!Options.AutoResize) { // resize the SurfaceImage _generator.ResizeDrawingSurface(_surfaceLock, _surface, size); // Set the size Size = _surface?.Size ?? new Size(0, 0); } // resize the SurfaceImage RedrawSurfaceImageInternal(); }
/// <summary> /// Redraws the SurfaceImage by loading image from the new Uri and image options /// </summary> /// <param name="uri">Uri of the image to be loaded on to the image surface.</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> /// <returns>Task</returns> public Task RedrawAsync(Uri uri, CompositionSurfaceImageOptions options) { // If the given Uri differs from the previously stored Uri // dispose the existing canvasBitmap if (!_uri.IsEqualTo(uri)) { _canvasBitmap?.Dispose(); _canvasBitmap = null; } // Set the new Uri of the image to be loaded _uri = uri; // Set the image options Options = options; // Reload the SurfaceImage return(RedrawSurfaceImageInternalAsync()); }
/// <summary> /// Constructor /// </summary> /// <param name="generator">ICompositionMaskGeneratorInternal object</param> /// <param name="uri">Uri of the image to be loaded onto the SurfaceImage.</param> /// <param name="size">Size of the SurfaceImage</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> public CompositionSurfaceImage(ICompositionGeneratorInternal generator, Uri uri, Size size, CompositionSurfaceImageOptions options) { if (generator == null) { throw new ArgumentNullException(nameof(generator), "CompositionGenerator cannot be null!"); } _generator = generator; _surfaceLock = new object(); // Create the Surface of the SurfaceImage _surface = _generator.CreateDrawingSurface(_surfaceLock, size); Size = _surface?.Size ?? new Size(0, 0); _uri = uri; _canvasBitmap = null; // Set the image options Options = options; // Subscribe to DeviceReplaced event _generator.DeviceReplaced += OnDeviceReplaced; }
/// <summary> /// Resizes the SurfaceImage to the given size and redraws the SurfaceImage by loading /// image from the new Uri. It returns the CanvasBitmap so that it can be cached for efficiency. /// </summary> /// <param name="surfaceLock">The object to lock to prevent multiple threads /// from accessing the surface at the same time.</param> /// <param name="surface">CompositionDrawingSurface</param> /// <param name="uri">Uri of the image to be loaded onto the SurfaceImage.</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> /// <param name="canvasBitmap">The CanvasBitmap on which the image is loaded.</param> /// <returns>CanvasBitmap</returns> public async Task <CanvasBitmap> RedrawSurfaceImageAsync(object surfaceLock, CompositionDrawingSurface surface, Uri uri, CompositionSurfaceImageOptions options, CanvasBitmap canvasBitmap) { if ((canvasBitmap == null) && (uri != null)) { try { canvasBitmap = await CanvasBitmap.LoadAsync(_canvasDevice, uri); } catch (IOException) { // Do nothing here as RenderBitmap method will fill the surface // with options.SurfaceBackgroundColor as the image failed to load // from Uri } } // Render the image to the surface RenderBitmap(surfaceLock, surface, canvasBitmap, options); return(canvasBitmap); }
/// <summary> /// Renders the CanvasBitmap on the CompositionDrawingSurface based on the given options. /// </summary> /// <param name="surfaceLock">The object to lock to prevent multiple threads /// from accessing the surface at the same time.</param> /// <param name="surface">CompositionDrawingSurface on which the CanvasBitmap has to be rendered.</param> /// <param name="canvasBitmap">CanvasBitmap created by loading the image from the Uri</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> private static void RenderBitmap(object surfaceLock, CompositionDrawingSurface surface, CanvasBitmap canvasBitmap, CompositionSurfaceImageOptions options) { var surfaceSize = surface.Size; // If the canvasBitmap is null, then just fill the surface with the SurfaceBackgroundColor if (canvasBitmap == null) { // No need to render if the width and/or height of the surface is zero if (surfaceSize.IsEmpty || surfaceSize.Width.IsZero() || surfaceSize.Height.IsZero()) { return; } // // Since multiple threads could be trying to get access to the device/surface // at the same time, we need to do any device/surface work under a lock. // lock (surfaceLock) { using (var session = CanvasComposition.CreateDrawingSession(surface)) { // Clear the surface with the SurfaceBackgroundColor session.Clear(options.SurfaceBackgroundColor); } // No need to proceed further return; } } // // Since multiple threads could be trying to get access to the device/surface // at the same time, we need to do any device/surface work under a lock. // lock (surfaceLock) { // Is AutoResize Enabled? if (options.AutoResize) { // If AutoResize is allowed and the canvasBitmap size and surface size are // not matching then resize the surface to match the canvasBitmap size. // // NOTE: HorizontalAlignment, Vertical Alignment and Stretch will be // handled by the CompositionSurfaceBrush created using this surface. // if (canvasBitmap.Size != surfaceSize) { // Resize the surface CanvasComposition.Resize(surface, canvasBitmap.Size); surfaceSize = canvasBitmap.Size; } // No need to render if the width and/or height of the surface is zero if (surfaceSize.IsEmpty || surface.Size.Width.IsZero() || surface.Size.Height.IsZero()) { return; } // Draw the image to the surface using (var session = CanvasComposition.CreateDrawingSession(surface)) { // Render the image session.DrawImage(canvasBitmap, // CanvasBitmap new Rect(0, 0, surfaceSize.Width, surfaceSize.Height), // Target Rectangle new Rect(0, 0, canvasBitmap.Size.Width, canvasBitmap.Size.Height), // Source Rectangle options.Opacity, // Opacity options.Interpolation); // Interpolation } } else { // No need to render if the width and/or height of the surface is zero if (surfaceSize.IsEmpty || surface.Size.Width.IsZero() || surface.Size.Height.IsZero()) { return; } var bitmapSize = canvasBitmap.Size; var sourceWidth = bitmapSize.Width; var sourceHeight = bitmapSize.Height; var ratio = sourceWidth / sourceHeight; var targetWidth = 0d; var targetHeight = 0d; var left = 0d; var top = 0d; // Stretch Mode switch (options.Stretch) { case Stretch.None: targetWidth = sourceWidth; targetHeight = sourceHeight; break; case Stretch.Fill: targetWidth = surfaceSize.Width; targetHeight = surfaceSize.Height; break; case Stretch.Uniform: // If width is greater than height if (ratio > 1.0) { targetHeight = Math.Min(surfaceSize.Width / ratio, surfaceSize.Height); targetWidth = targetHeight * ratio; } else { targetWidth = Math.Min(surfaceSize.Height * ratio, surfaceSize.Width); targetHeight = targetWidth / ratio; } break; case Stretch.UniformToFill: // If width is greater than height if (ratio > 1.0) { targetHeight = Math.Max(surfaceSize.Width / ratio, surfaceSize.Height); targetWidth = targetHeight * ratio; } else { targetWidth = Math.Max(surfaceSize.Height * ratio, surfaceSize.Width); targetHeight = targetWidth / ratio; } break; } // Horizontal Alignment switch (options.HorizontalAlignment) { case AlignmentX.Left: left = 0; break; case AlignmentX.Center: left = (surfaceSize.Width - targetWidth) / 2.0; break; case AlignmentX.Right: left = surfaceSize.Width - targetWidth; break; } // Vertical Alignment switch (options.VerticalAlignment) { case AlignmentY.Top: top = 0; break; case AlignmentY.Center: top = (surfaceSize.Height - targetHeight) / 2.0; break; case AlignmentY.Bottom: top = surfaceSize.Height - targetHeight; break; } // Draw the image to the surface using (var session = CanvasComposition.CreateDrawingSession(surface)) { // Clear the surface with the SurfaceBackgroundColor session.Clear(options.SurfaceBackgroundColor); // Render the image session.DrawImage(canvasBitmap, // CanvasBitmap new Rect(left, top, targetWidth, targetHeight), // Target Rectangle new Rect(0, 0, sourceWidth, sourceHeight), // Source Rectangle options.Opacity, // Opacity options.Interpolation); // Interpolation } } } }
/// <summary> /// Resizes the SurfaceImage to the given size and redraws the SurfaceImage /// by resizing the existing canvasBitmap /// </summary> /// <param name="surfaceLock">The object to lock to prevent multiple threads /// from accessing the surface at the same time.</param> /// <param name="surface">CompositionDrawingSurface</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> /// <param name="canvasBitmap">The CanvasBitmap on which the image is loaded.</param> public void RedrawSurfaceImage(object surfaceLock, CompositionDrawingSurface surface, CompositionSurfaceImageOptions options, CanvasBitmap canvasBitmap) { // Render the image to the surface RenderBitmap(surfaceLock, surface, canvasBitmap, options); }
/// <summary> /// Creates a CompositionSurfaceImage having the given size onto which an image (based on the Uri /// and the options) is loaded. /// </summary> /// <param name="uri">Uri of the image to be loaded onto the SurfaceImage.</param> /// <param name="size">New size of the SurfaceImage</param> /// <param name="options">Describes the image's resize and alignment options in the allocated space.</param> /// <returns>ICompositionSurfaceImage</returns> public async Task <ICompositionSurfaceImage> CreateSurfaceImageAsync(Uri uri, Size size, CompositionSurfaceImageOptions options) { // Initialize the SurfaceImage ICompositionSurfaceImage surfaceImage = new CompositionSurfaceImage(this, uri, size, options); // Render the image onto the surface await surfaceImage.RedrawAsync(); return(surfaceImage); }