简体   繁体   English

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

[英]Draw shadow on image while drawing on DrawingContext

I draw an image in OnRender method of my custom FrameworkElement. 我在自定义FrameworkElement的OnRender方法中绘制图像。 I would like to draw a shadow of this image as well. 我也想绘制此图像的阴影。 I need to do this in code, and I would not like to use DropShadowBitmapEffect because it is obsolete. 我需要在代码中执行此操作,并且我不想使用DropShadowBitmapEffect,因为它已过时。 How can I achieve this? 我该如何实现?

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

    }

Note that the solution suggested by SvenG below, to add an effect to the underlying element, doesn't work for me because it gives a shadow to the whole element, not the individual images I draw. 请注意,下面的SvenG建议的为基础元素添加效果的解决方案对我不起作用,因为它为整个元素(而不是我绘制的单个图像)提供了阴影。 For example, if I were to have two overlapping DrawImage, the suggested solution will draw shadow considering the whole. 例如,如果我有两个重叠的DrawImage,建议的解决方案将考虑整个阴影。 The shadow of upper image will not be drawn on the lower image. 上方图像的阴影不会在下方图像上绘制。

Additionally, I want to create a bitmap using the getBitmap function as shown above to export the drawn image with the shadows. 另外,我想使用如上所述的getBitmap函数创建位图,以导出带有阴影的绘制图像。

There is an old PushEffect() call on DrawingContext that would have done what you required, but like BitmapEffect this is obsolete. DrawingContext上有一个旧的PushEffect()调用可以完成您所需的操作,但是像BitmapEffect一样,这已过时。

BitmapEffect 's replacement is the Effect class. BitmapEffect的替代物是Effect类。 There is a subclass called DropShadowEffect that is exactly what you are after, but unfortunately as SvenG says, this cannot be applied directly to bitmaps. 确实有一个叫做DropShadowEffect的子类,但很遗憾,正如SvenG所说,它不能直接应用于位图。

The lowest level element that supports applying effects is the DrawingVisual class. 支持应用效果的最低级别的元素是DrawingVisual类。 This isn't too bad because DrawingVisual is a pretty lightweight class. 这还不错,因为DrawingVisual是一个非常轻量级的类。 There is no layout overhead. 没有布局开销。 Your best bet would be to create each bitmap in its own DrawingVisual , and set the Effect property of the visual to a DropShadowEffect . 最好的选择是在其自己的DrawingVisual创建每个位图,并将视觉Effect属性设置为DropShadowEffect Obviously if you have thousands of bitmaps it may not be a viable solution. 显然,如果您有成千上万个位图,那可能不是一个可行的解决方案。

All this can be done in code, although not OnRender() since each visual has its own render context. 所有这些都可以用代码来完成,尽管不是OnRender()因为每个视觉都有自己的渲染上下文。 However, for child DrawingVisuals to render properly, you need to tell the framework about them. 但是,为了使子DrawingVisuals正确呈现,您需要告诉框架有关它们的信息。

You need to override two methods in your custom element in order to see these visuals: VisualChildrenCount to say how many children you have, and GetVisualChild() to return them to the system. 您需要重写自定义元素中的两个方法才能看到这些视觉效果: VisualChildrenCount表示您有多少个孩子,而GetVisualChild()则将它们返回到系统。 Because of this you will need to keep a collection of visuals available. 因此,您将需要保留一组可用的视觉效果。 You can also call AddVisualChild() and AddLogicalChild() if you want to do hit testing against them. 如果要对它们进行命中测试,也可以调用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);
    }
}

Add the following code to your OnRenderMethod: 将以下代码添加到您的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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM