0

我正在尝试获取图像并对其应用阴影并另存为图像。

到目前为止,在不使用第三方解决方案的情况下,唯一的方法是使用DropShadowEffectin a 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

有没有内置的方法来测量它,还是我应该手动测量?怎么可以手动完成?

4

1 回答 1

1

如果您查看DropShadowEffect 的 .NET 源代码,您可以使用一种内部方法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);
}

我希望这有帮助。

问题作者的更新

这是我正在使用的实际代码:

//Draws image with shadow.
using (var drawingContext = drawingVisual.RenderOpen())
{
    //Measure drop shadow space.
    var point1 = new Point(0 - model.BlurRadius / 2d, 0 - model.BlurRadius / 2d);
    var point2 = new Point(image.PixelWidth + model.BlurRadius / 2d, image.PixelHeight + model.BlurRadius / 2d);

   var num1 = Math.PI / 180.0 * model.Direction;
   var num2 = model.Depth * Math.Cos(num1);
   var num3 = model.Depth * Math.Sin(num1);

   if (num2 >= 0.0)
       point2.X += num2; //If the shadow is horizontally aligned or to the right of the original element...
   else
       point1.X += num2; //If the shadow is to the left of the original element...

   if (num3 >= 0.0)
       point1.Y -= num3; //If the shadow is above the original element...
   else
       point2.Y -= num3; //If the shadow is below the original element...

   var left = Math.Abs(point1.X);
   var top = Math.Abs(point1.Y);
   var totalWidth = left + point2.X;
   var totalHeight = top + point2.Y;

   //Image.
   drawingContext.DrawImage(image, new Rect((int)left, (int)top, image.PixelWidth, image.PixelHeight));

   frameHeight = (int)totalHeight;
   frameWidth = (int)totalWidth;
}
于 2019-10-02T19:17:47.183 回答