RenderTargetBitmap 低图像质量问题

RenderTargetBitmap low image quality issue

我尝试使用 RenderTargetBitmap 方法生成 300 dpi 图像。

当我尝试使用 RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(315, 195, 300, 300, PixelFormats.Pbgra32);

图片变大了。

如何解决?

RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(315, 195, 96, 96, PixelFormats.Pbgra32);
renderTargetBitmap.Render(gridCard);
PngBitmapEncoder pngImage = new PngBitmapEncoder();
pngImage.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (Stream fileStream = File.Create(path))
{
    pngImage.Save(fileStream);
}

我需要按所需的 DPI(即 300)除以默认 DPI(即 96)来缩放位图的大小。

double w = 315;
double h = 195;
double dpi = 300;
double scale = dpi / 96;

RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(
    (int)(w * scale), (int)(h * scale), dpi, dpi, PixelFormats.Pbgra32);

更新 #1 完整解决方案(打印 WPF 控件是专用打印机 MAGiCARD Enduro 3E 的代理卡)

private void BtnPrint_Click(object sender, RoutedEventArgs e)
{
   try
   {
       var size = GetElementPixelSize(gridCard);
       double w = size.Width;
       double h = size.Height;
       double dpiScale = 300.0 / 99.9;
       double dpiX = 300.0;
       double dpiY = 300.0;
       RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(Convert.ToInt32((w) * dpiScale), Convert.ToInt32((h) * dpiScale), dpiX, dpiY, PixelFormats.Pbgra32);

       renderTargetBitmap.Render(gridCard);

       PngBitmapEncoder pngImage = new PngBitmapEncoder();
       pngImage.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
       var biRotated = new BitmapImage();
       using (Stream fileStream = new MemoryStream()) 
       {
            pngImage.Save(fileStream);
            fileStream.Seek(0, SeekOrigin.Begin);

            biRotated.BeginInit();
            biRotated.CacheOption = BitmapCacheOption.OnLoad;
            biRotated.StreamSource = fileStream;
            // biRotated.Rotation = Rotation.Rotate90; // if you need it
            biRotated.EndInit();
       }

       var vis = new DrawingVisual();
       var dc = vis.RenderOpen();
       dc.DrawImage(biRotated, new Rect { Width = biRotated.Width, Height = biRotated.Height });
       dc.Close();

       var pdialog = new System.Windows.Controls.PrintDialog();
       if (pdialog.ShowDialog() == true)
       {
           pdialog.PrintVisual(vis, "Proxy-card");
          }
   }
   catch (Exception ex)
   {
       System.Windows.MessageBox.Show("Print error " + ex.Message);
   }
}

// 
public Size GetElementPixelSize(UIElement element)
{
    Matrix transformToDevice;
    var source = PresentationSource.FromVisual(element);
    if (source != null)
      transformToDevice = source.CompositionTarget.TransformToDevice;
    else
    {
      // IntPtr hWnd = source.Handle;
      using (var source1 = new HwndSource(new HwndSourceParameters()))
      {
          transformToDevice = source1.CompositionTarget.TransformToDevice;
      }
    }
    if (element.DesiredSize == new Size())
                element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

     return (Size)transformToDevice.Transform((Vector)element.DesiredSize);
}