我正在尝试获取图像并对其施加阴影,然后另存为图像。
到目前为止,不使用第三方解决方案的唯一方法是在DropShadowEffect
中使用DrawingVisual
:
var drawingVisual = new DrawingVisual();
drawingVisual.Effect = new DropShadowEffect
{
Color = Color.FromArgb(255, 0, 0, 0),
BlurRadius = 5,
Opacity = 1,
Direction = 45,
ShadowDepth = 6
};
using (var drawingContext = drawingVisual.RenderOpen())
{
var left = 0; //??
var top = 0; //??
var totalWidth = left + image.Width; //??
var totalHeight = top + image.Height; //??
//Background.
drawingContext.DrawRectangle(new SolidColorBrush(Colors.White), null, new Rect(0,0, totalWidth, totalHeight));
//Image.
drawingContext.DrawImage(image, new Rect(left, top, image.Width, image.Height));
}
var frameHeight = image.PixelHeight; //??
var frameWidth = image.PixelWidth; //??
//Converts the Visual (DrawingVisual) into a BitmapSource.
var bmp = new RenderTargetBitmap(frameWidth, frameHeight, imageDpi, imageDpi, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
//Creates a PngBitmapEncoder and adds the BitmapSource to the frames of the encoder.
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
//Saves the image into a file using the encoder.
using (Stream stream = File.Create(frame.Path))
encoder.Save(stream);
我不知道检测给定DropShadowEffect
各个面的精确像素偏移所需的数学。
是否有内置的方法可以对其进行测量,还是应该手动进行?如何手动完成?
[如果您查看.NET source code for the DropShadowEffect,有一种内部方法GetRenderBounds
,可用于制定所需的答案。
虽然无法使用GetRenderBounds,但是代码很简单,您可以创建自己的帮助器方法。
以下是参考代码:
/// <summary>
/// Takes in content bounds, and returns the bounds of the rendered
/// output of that content after the Effect is applied.
/// </summary>
internal override Rect GetRenderBounds(Rect contentBounds)
{
Point topLeft = new Point();
Point bottomRight = new Point();
double radius = BlurRadius;
topLeft.X = contentBounds.TopLeft.X - radius;
topLeft.Y = contentBounds.TopLeft.Y - radius;
bottomRight.X = contentBounds.BottomRight.X + radius;
bottomRight.Y = contentBounds.BottomRight.Y + radius;
double depth = ShadowDepth;
double direction = Math.PI/180 * Direction;
double offsetX = depth * Math.Cos(direction);
double offsetY = depth * Math.Sin(direction);
// If the shadow is horizontally aligned or to the right of the original element...
if (offsetX >= 0.0f)
{
bottomRight.X += offsetX;
}
// If the shadow is to the left of the original element...
else
{
topLeft.X += offsetX;
}
// If the shadow is above the original element...
if (offsetY >= 0.0f)
{
topLeft.Y -= offsetY;
}
// If the shadow is below the original element...
else
{
bottomRight.Y -= offsetY;
}
return new Rect(topLeft, bottomRight);
}
我希望这会有所帮助。