RenderTargetBitmap Проблема низкого качества WPF - PullRequest
0 голосов
/ 12 октября 2019

У меня есть приложение, которое отображает изображение в 3D Viewport, и вы можете поместить в него тег. Когда я пытался визуализировать трехмерный видовой экран, качество отличалось от того, которое отображалось в видовом окне, и конечный результат.

Эта фотография была сделана с использованием снимка экрана в Windows: Из снимка экрана

В то время как этот с использованием RenderBitmapTarget: Из RenderBitmapTarget

Я прочитал, что RenderBitmapTarget выводит изображение более низкого качества, потому что (если я правильно помню) оно рендерило его с помощью программного обеспечениявозможности, а не аппаратные возможности. но я все еще хочу подтвердить, что если есть какой-либо другой способ сделать выходное изображение по-прежнему хорошим без использования Screenshot.

Проблема с использованием функции Screenshot заключается в том, что когда окна выходят за границы, он создает черный фон начасть, где окна не отображаются на экране, поскольку это был скриншот.

Снимок экрана за окном

Многие предлагали решить проблему с использованием SlimDX или SharpDX, ноЯ не могу найти учебник для справки. Большая часть учебника, который я нашел о SharpDX, - это «Рендеринг изображения в приложение», а не «Рендеринг визуала в файл изображения». Так что, если кто-нибудь знает другой хороший способ рендеринга изображения в окне просмотра, который я могу попробовать, он может дать то же качество, что и отображение в окне просмотра ?

Вот код, для которого я использую. ... RenderBitmapTarget, я пробую 2 варианта, используя VisualBrush или просто визуализирую его напрямую:

public static void SaveCaptureImage(Viewport3D visual, string filePath, MainWindow x, PanoView testView)
    {
        Rect bounds = VisualTreeHelper.GetDescendantBounds(testView);
        /*
        var dpiScale = 300.0 / 96.0;
        var testVWidth = visual.ActualWidth * dpiScale;
        var testVHeight = visual.ActualHeight * dpiScale;
        var bitmap = new RenderTargetBitmap((int)testVWidth,
            (int)testVHeight, 300.0, 300.0, PixelFormats.Pbgra32);//96
        bitmap.Render(visual);
        using (var os = new FileStream(filePath, FileMode.Create))
        {
            var encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(bitmap));
            encoder.Save(os);
        }
        */
        var dpiScale = 200.0 / 96.0;
        var testVWidth = testView.ActualWidth * dpiScale;
        var testVHeight = testView.ActualHeight * dpiScale;
        var bitmap = new RenderTargetBitmap((int)testVWidth,
            (int)testVHeight, 200.0, 200.0, PixelFormats.Pbgra32);//96

        var drwVisual = new DrawingVisual();
        VisualBrush vb = new VisualBrush(testView);
        using (DrawingContext ctx = drwVisual.RenderOpen())
        {
            ctx.DrawRectangle(vb,null,new Rect(new System.Windows.Point(0,0),bounds.Size));
        }
        bitmap.Render(drwVisual);

        using (var os = new FileStream(filePath, FileMode.Create))
        {
            var encoder = new PngBitmapEncoder();
            encoder.Interlace = PngInterlaceOption.On;
            encoder.Frames.Add(BitmapFrame.Create(bitmap));
            encoder.Save(os);
            os.Close();
        }
        //System.Runtime.InteropServices.Marshal.Copy();
    }

ScreenShot, я изменяю положение окна, чтобы оно вписывалось в экран и снимал скриншот, и возвращаю его обратно в исходное положение, нолично это не очень хорошее решение, поскольку заикание окна за доли секунды перемещается:

public static void TestCaptureImage(PanoView visual, MainWindow masterContainer, string filePath)
        {
            Console.WriteLine(masterContainer.Left+"<-Left Top->"+masterContainer.Top);
            var prevX = masterContainer.Left; var prevY = masterContainer.Top;
            Console.WriteLine(masterContainer.Left + "<-Left Top->" + masterContainer.Top);
            masterContainer.Left = 0;
            masterContainer.Top = 0;

            var locationWindow = visual.TranslatePoint(new System.Windows.Point(-10,-42), masterContainer);//10,42 For Margin Purpose
            var locationWindowEdge = visual.TranslatePoint(new System.Windows.Point(-10+masterContainer.Width-350-20-2, -42+masterContainer.Height-234-16-2), masterContainer);
            var locationFromScreen = visual.PointToScreen(locationWindow);
            var locationFromScreenEdge = visual.PointToScreen(locationWindowEdge);

            var testWidth = (int)locationFromScreenEdge.X - (int)locationFromScreen.X;
            var testHeight = (int)locationFromScreenEdge.Y - (int)locationFromScreen.Y;

            var bitmap = new Bitmap(testWidth,
                                    testHeight,
                                    System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            var SS = Graphics.FromImage(bitmap);
            SS.CopyFromScreen((int)locationFromScreen.X,
                              (int)locationFromScreen.Y,
                              0,0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Size,
                              CopyPixelOperation.SourceCopy);
            using (var os = new FileStream(filePath,FileMode.Create))
            {
                bitmap.Save(os,ImageFormat.Jpeg);
            }
            masterContainer.Left = prevX;
            masterContainer.Top = prevY;
        }
...