在DrawingContext上绘制时在图像上绘制阴影

Ama*_*der 3 .net c# wpf

我在自定义FrameworkElement的OnRender方法中绘制图像。我也想绘制此图像的阴影。我需要在代码中执行此操作,并且我不想使用DropShadowBitmapEffect,因为它已过时。我该如何实现?

    public class MyDrawingView : FrameworkElement
    {
        protected override void OnRender(System.Windows.Media.DrawingContext dc)
        {
             drawImagesOnDrawingContext(dc);
        }

        public RenderTargetBitmap getBitmap()
        {
            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext dcMine = dv.RenderOpen())
            {
                drawImagesOnDrawingContext(dcMine);
                dcMine.Close();
            }
            RenderTargetBitmap rtb = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32);
            rtb.Render(dv);
            return rtb;
        }

        private void drawImagesOnDrawingContext(System.Windows.Media.DrawingContext dc)
        {
            //how to draw shadow on bi?
            BitmapImage bi = new BitmapImage(new Uri(@"D:\mytemp\img1.jpg"));
            dc.DrawImage(bi, new Rect(50, 50, 100, 100));

            //how to draw shadow on bi1
            BitmapImage bi1 = new BitmapImage(new Uri(@"D:\mytemp\img2.jpg"));
            dc.DrawImage(bi1, new Rect(30, 30, 100, 100));
        }

    }
Run Code Online (Sandbox Code Playgroud)

请注意,下面的SvenG建议的为基础元素添加效果的解决方案对我不起作用,因为它为整个元素(而不是我绘制的单个图像)提供了阴影。例如,如果我有两个重叠的DrawImage,建议的解决方案将考虑整个阴影。上方图像的阴影不会在下方图像上绘制。

另外,我想使用如上所述的getBitmap函数创建位图,以导出带有阴影的绘制图像。

Gaz*_*yer 5

有一个旧的PushEffect()调用DrawingContext可以满足您的要求,但是像BitmapEffect一样,这已经过时了。

BitmapEffect的替代者是Effect阶级。有一个子类DropShadowEffect正是您所追求的,但是不幸的是,正如SvenG所说,它不能直接应用于位图。

支持应用效果的最低级别的元素是DrawingVisual类。这还不错,因为它DrawingVisual是一个非常轻量级的类。没有布局开销。最好的选择是单独创建每个位图DrawingVisual,然后将Effect视觉效果的属性设置为DropShadowEffect。显然,如果您有成千上万个位图,那可能不是一个可行的解决方案。

所有这些都可以用代码完成,尽管OnRender()由于每种视觉效果都有其自己的渲染上下文,所以这不能做到。但是,为了使子DrawingVisuals正确呈现,您需要告诉框架有关它们的信息。

您需要重写自定义元素中的两个方法才能看到这些视觉效果:VisualChildrenCount说出您有多少个孩子,以及GetVisualChild()将它们返回给系统。因此,您将需要保留一组可用的视觉效果。您也可以致电AddVisualChild()AddLogicalChild()如果您想对他们进行命中测试。

public class MyDrawingView : FrameworkElement
{
    List<DrawingVisual> _visuals = new List<DrawingVisual>();

    public MyDrawingView()
    {
        CreateVisuals();
    }

    //Gets a bitmap rendering of the visual and its children for saving as image file
    public RenderTargetBitmap GetBitmap()
    {
        var rtb = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32);
        rtb.Render(this);
        return rtb;
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return _visuals.Count;
        }
    }

    protected override Visual GetVisualChild(int index)
    {
        return _visuals[index];
    }

    private void CreateVisuals()
    {
        CreateVisualForBitmap(@"D:\mytemp\img1.jpg", new Rect(50, 50, 100, 100));
        CreateVisualForBitmap(@"D:\mytemp\img2.jpg", new Rect(30, 30, 100, 100));
    }

    private void CreateVisualForBitmap(string bitmapPath, Rect bounds)
    {
        var bitmap    = new BitmapImage(new Uri(bitmapPath));
        var visual    = new DrawingVisual();
        visual.Effect = new DropShadowEffect();

        using (DrawingContext dc = visual.RenderOpen())
        {
            dc.DrawImage(bitmap, bounds);
        }

        _visuals.Add(visual);
        AddVisualChild(visual);
        AddLogicalChild(visual);
    }
}
Run Code Online (Sandbox Code Playgroud)