Как сохранить нечеткое изображение элемента управления в WPF?
Я использую DrawingContext для рисования изображений. Затем я отображаю результат в RenderTargetBitmap. Я также визуализирую Canvas для того же RenderTargetBitmap. Хотя границы пикселей на экране четкие, при сохранении они становятся размытыми и размытыми.
На снимке экрана ниже вы можете увидеть проблему (с BitmapScalingMode = NearestNeighbor).
Вот это с BitmapScalingMode = HighQuality. Это гладко, но не свежо и чисто.
Вот соответствующий раздел моего кода. Вы можете видеть, что я пытался установить RenderOptions в нескольких местах, но, похоже, это не имеет никакого эффекта.
DrawingVisual drawingVisual = new DrawingVisual();
RenderTargetBitmap result = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32);
RenderOptions.SetBitmapScalingMode(drawingVisual, BitmapScalingMode.NearestNeighbor); // This forces the scaling to be on even-pixel boundaries
RenderOptions.SetBitmapScalingMode(drawCanvas, BitmapScalingMode.NearestNeighbor); // This forces the scaling to be on even-pixel boundaries
RenderOptions.SetBitmapScalingMode(result, BitmapScalingMode.NearestNeighbor); // This forces the scaling to be on even-pixel boundaries
using (DrawingContext context = drawingVisual.RenderOpen()) {
context.DrawRectangle(Brushes.Black, null, new Rect(new Point(), new Size(size.Width, size.Height)));
if (layers.Count >= 1 && layers[0].LayerImage != null && layers[0].LayerImage.Source != null && gridImage.Children[1].Visibility == System.Windows.Visibility.Visible)
context.DrawImage(layers[0].LayerImage.Source, new Rect(size)); // Draw first image.
context.Close();
}
result.Render(drawingVisual);
drawCanvas.Measure(drawCanvas.RenderSize);
drawCanvas.Arrange(new Rect(drawCanvas.RenderSize));
for (int i = 0; i < drawCanvas.Children.Count; i++) {
RenderOptions.SetBitmapScalingMode(drawCanvas.Children[i], BitmapScalingMode.NearestNeighbor); // This forces the scaling to be on even-pixel boundaries
}
result.Render(drawCanvas);
BitmapEncoder encoder = new PngBitmapEncoder();
if (result!= null) {
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)result));
encoder.Save(fileStream);
}
2 ответа
Я не знаю, исправили ли вы это, но эта функция очень хорошо работает на моей стороне.
public BitmapSource SnapShotPNG(UIElement source)
{
double actualWidth = source.RenderSize.Width;
double actualHeight = source.RenderSize.Height;
RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)actualWidth, (int)actualHeight, 96, 96, PixelFormats.Pbgra32);
DrawingVisual visual = new DrawingVisual();
using (DrawingContext context = visual.RenderOpen())
{
VisualBrush sourceBrush = new VisualBrush(source);
context.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));
}
source.Measure(source.RenderSize); //Important
source.Arrange(new Rect(source.RenderSize)); //Important
renderTarget.Render(visual);
try
{
return new CroppedBitmap(renderTarget, new Int32Rect(0, 0, (int)actualWidth, (int)actualHeight));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return null;
}
}
public static BitmapSource CaptureScreen(this UIElement visualElement, int? desiredLongestEdge = null)
{
double scale = 1;
if (desiredLongestEdge.HasValue)
{
if (visualElement.RenderSize.Width > visualElement.RenderSize.Height)
{
scale = desiredLongestEdge.Value/ visualElement.RenderSize.Width;
}
else
{
scale = desiredLongestEdge.Value / visualElement.RenderSize.Height ;
}
}
var targetBitmap =
new RenderTargetBitmap(
(int) Math.Ceiling(scale * (visualElement.RenderSize.Width + 1)),
(int) Math.Ceiling(scale * (visualElement.RenderSize.Height + 1)),
scale * 96,
scale * 96,
PixelFormats.Pbgra32);
visualElement.Measure(visualElement.RenderSize); //Important
visualElement.Arrange(new Rect(visualElement.RenderSize)); //Important
targetBitmap.Render(visualElement);
return targetBitmap;
}