/// <summary> /// Renders the passed in images over top the source image, masking with elliptical or rectangular opacity mask as specified, returns an image of this. /// </summary> /// <param name="sourceImage">Image to be overlaid</param> /// <param name="overlayPositions">Positions to draw facesToOverlay on sourceImage</param> /// <param name="facesToOverlay">Images to be overlaid on sourceimage</param> /// <param name="howToClip">Rectangular or elliptical clipping</param> /// <returns></returns> private static BitmapSource _AddOverlay(BitmapSource sourceImage, IList <Rect> overlayPositions, IList <ImageSource> overlayImages, ClipAlgorithm howToClip) { Verify.IsNotNull(sourceImage, "sourceImage"); Verify.IsNotNull(overlayPositions, "overlayPositions"); Verify.IsNotNull(overlayImages, "facesToOverlay"); var imageCompositor = new Canvas { Width = sourceImage.PixelWidth, Height = sourceImage.PixelHeight, }; imageCompositor.Children.Add(new Image { Source = sourceImage }); // Note that the overlay rects and images may not match in length. // The user may not have enough friends to fill in the splash screen. This is okay. foreach (var pair in overlayPositions.Zip(overlayImages, (rect, img) => new { Img = img, Rect = rect })) { imageCompositor.Children.Add(_GetCanvasOverlay(pair.Img, pair.Rect, howToClip)); } return(Utility.GenerateBitmapSource(imageCompositor, imageCompositor.Width, imageCompositor.Height, true)); }
// Creates an element with Canvas attached DPs and appropriate masking if specified. private static UIElement _GetCanvasOverlay(ImageSource overlaySource, Rect overlayPosition, ClipAlgorithm howToClip) { Brush opacityBrush = null; switch (howToClip) { case ClipAlgorithm.Elliptical: double dimensionDelta = overlayPosition.Height - overlayPosition.Width; opacityBrush = new DrawingBrush { Drawing = new GeometryDrawing { Geometry = new EllipseGeometry(overlayPosition), Brush = new RadialGradientBrush { GradientOrigin = new Point(0.5, 0.5), Center = new Point(0.5, 0.5), // Since we subtracted Height From Width above (arbitrary) to normalize radii for // the gradient, subtract for Width and add for Height (I can show this on paper but this "works" for stretching radius. RadiusX = 0.5 - (0.5 * (dimensionDelta / overlayPosition.Height)), RadiusY = 0.5 + (0.5 * (dimensionDelta / overlayPosition.Width)), GradientStops = { new GradientStop(Colors.White, 0.0), new GradientStop(Colors.White, 0.85), new GradientStop(Colors.Transparent, 1.0), }, }, } }; break; case ClipAlgorithm.Rectangular: // TODO: Do we care to do any gradient opacity masking here? // Doesnt't need to be answered until we have a splash screen w/ rectangular overlays. break; } var rect = new Rectangle { Width = overlayPosition.Width, Height = overlayPosition.Height, Fill = new ImageBrush { ImageSource = overlaySource, Stretch = Stretch.UniformToFill, AlignmentX = AlignmentX.Center, AlignmentY = AlignmentY.Center }, OpacityMask = opacityBrush, }; Canvas.SetLeft(rect, overlayPosition.Left); Canvas.SetTop(rect, overlayPosition.Top); return(rect); }