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

时间:2012-01-17 13:24:44

标签: c# .net 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));
        }

    }

请注意,下面SvenG建议的解决方案,为底层元素添加效果,对我来说不起作用,因为它给整个元素带来了阴影,而不是我绘制的单个图像。例如,如果我有两个重叠的DrawImage,建议的解决方案将考虑整体绘制阴影。上部图像的阴影不会在下部图像上绘制。

此外,我想使用getBitmap函数创建一个位图,如上所示,以使用阴影导出绘制的图像。

2 个答案:

答案 0 :(得分:4)

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);
    }
}

答案 1 :(得分:1)

将以下代码添加到OnRenderMethod:

  ....

  dc.DrawImage(bi, new Rect(50, 50, 100, 100));

  // Create DropShadow
  DropShadowEffect effect = new DropShadowEffect();
  effect = new DropShadowEffect();
  effect.Color = Colors.Gray;
  effect.Direction = 45;
  this.Effect = effect;