在DrawingContext上绘制时在图像上绘制阴影
本文关键字:绘制 阴影 图像 DrawingContext | 更新日期: 2023-09-27 18:20:28
我在自定义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函数创建一个位图,以导出带有阴影的绘制图像。
在DrawingContext
上有一个旧的PushEffect()
调用,它本可以完成您需要的操作,但与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);
}
}
将以下代码添加到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;