I'm trying to get an image and apply a drop shadow to it and save back as an image.
So far, the only way to do that, while not using third party solutions is to use the DropShadowEffect in 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);
I have no idea the math required to detect the exact pixel offsets at all sides for a given DropShadowEffect.
Is there any built in way to measure it or should I do it manually? How can be done manually?
If you take a look at the .NET source code for the DropShadowEffect there is an internal method
GetRenderBoundsthat you can use to formulate the answer you're looking for.While GetRenderBounds is not available for you to use, the code is simple enough that you can create your own helper method.
Here's the code for reference:
I hope this helps.
Update from the author of the question
Here's the actual code that I'm using: