tool__ Ответов: 2

Низкое качество изображения, полученного с помощью моментального снимка. В WPF


Приведенная ниже программа создает моментальный снимок с содержимым главного окна самого приложения. Однако качество полученного изображения не эквивалентно программе print screen Windows 10, которая выдает желаемый результат.

Вот снимок запущенной программы, сделанный с помощью программы print screen Windows 10, увеличенной в масштабе:

https://ibb.co/wz4pb4d

А вот снимок, который производит приведенная ниже программа, увеличенный в масштабе:

https://ibb.co/DLsNb8X

Есть ли что-то, что мы можем попытаться улучшить качество снимка, который производит эта программа?

Я попробовал Bitmap Encoder , но это тот же результат, только без прозрачности, (не нужно иметь прозрачность) также попробовал некоторые другие форматы пикселей, но я получаю ошибки, только Pbgra32, кажется, работает так, как программа.

Заранее спасибо

Что я уже пробовал:

<pre> if (e.Key == Key.P)
            {
                //Set scrollviewer's Content property as UI element to capture full content
                FrameworkElement element = UxVisual as FrameworkElement;
                Uri path = new Uri(@"C:\Users\4gry\Desktop\screenshot.png");
                CaptureScreen(element, path);
            }

        }
            public void CaptureScreen(FrameworkElement source, Uri destination)
            {
            RenderOptions.SetEdgeMode(source, EdgeMode.Aliased);
            try
                {
                    double Height, ActualHeight, Width, ActualWidth;

                    Height = ActualHeight = source.RenderSize.Height;
                    Width = ActualWidth = source.RenderSize.Width;

                    //Specification for target bitmap like width/height pixel etc.
                    RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)ActualWidth, (int)ActualHeight, 96, 96, PixelFormats.Pbgra32);
                    //creates Visual Brush of UIElement
                    VisualBrush visualBrush = new VisualBrush(source);

                    DrawingVisual drawingVisual = new DrawingVisual();
                    using (DrawingContext drawingContext = drawingVisual.RenderOpen())
                    {
                        //draws image of element
                        drawingContext.DrawRectangle(visualBrush, null, new Rect(source.RenderSize));
                    }
                    

                    //renders image
                    renderTarget.Render(drawingVisual);

                    //PNG encoder for creating PNG file
                    PngBitmapEncoder encoder = new PngBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(renderTarget));
                    using (FileStream stream = new FileStream(destination.LocalPath, FileMode.Create, FileAccess.Write))
                    {
                        encoder.Save(stream);
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString());
                }
            }


код XAML

<Window x:Name="mainwindow" x:Class="WpfApp2.MainWindow"
        
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="mainwindow" Height="397.265" Width="603.147" Icon="images2/Untitled-1.gif" ResizeMode="CanMinimize" WindowStartupLocation="Manual" AutomationProperties.Name="Grid" IsTabStop="True" KeyDown="Mainwindow_KeyDown" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0">
    <Border x:Name="UxVisual" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="367" Margin="10,0,0,0" VerticalAlignment="Top" Width="583">
        <Grid Margin="0,0,0,13">

            <Image Stretch="None" Source="images2/screenshot copy.gif" IsEnabled="False" Margin="0,0,-28,0" HorizontalAlignment="Left" Width="625" Height="347" VerticalAlignment="Top"/>

            <Image x:Name="linevertical" HorizontalAlignment="Left" Height="343" Margin="108,76,-21,0" VerticalAlignment="Top" Width="705" Source="images2/Untitled-1.gif" Stretch="None" Visibility="Hidden" RenderTransformOrigin="0.46,0.52"/>
            <Image x:Name="lineo" HorizontalAlignment="Left" Height="171" Margin="173,76,0,0" VerticalAlignment="Top" Width="193" Source="images2/Untitled-3.gif" Stretch="None" Visibility="visible"/>
            <Image HorizontalAlignment="Left" Height="100" Margin="10,16,0,0" VerticalAlignment="Top" Width="189" Source="images2/Untitled-1.gif" Stretch="None" Visibility="hidden"/>
            <Image HorizontalAlignment="Left" Height="100" Margin="73,10,0,0" VerticalAlignment="Top" Width="100" Source="images2/Untitled-3.gif" Stretch="None" Visibility="visible"/>
            <Button HorizontalAlignment="Left" Margin="173,61,0,0" VerticalAlignment="Top" Width="225" Height="121" Opacity="0"  Click="Button_Click"/>
            <Button Content="" HorizontalAlignment="Left" Margin="464,247,0,0" VerticalAlignment="Top" Width="194" Height="144" Opacity="0" Click="Button_Click_1"/>
            <Image HorizontalAlignment="Left" Height="100" Margin="428,-11,-40,0" VerticalAlignment="Top" Width="206" Stretch="None" Source="images2/Untitled-1.gif"/>

        </Grid>
    </Border>
</Window>

2 Ответов

Рейтинг:
20

Gerry Schmitz

Я создаю "визуальный" (т. е. FrameworkElement), который я хочу захватить, а затем использую фактические размеры:

RenderTargetBitmap rtb = new RenderTargetBitmap(
            (int) printVisual.ActualWidth,
            (int) printVisual.ActualHeight, 96, 96, PixelFormats.Pbgra32 );


Цитата:
FrameworkElement-это класс реализации уровня фреймворка WPF, который строится на UIElement и добавляет определенные взаимодействия с уровнем фреймворка WPF. FrameworkElement добавляет и определяет следующие возможности:

Дополнительные характеристики компоновки, зависящие от конкретной структуры

Поддержка расширенной отчетности метаданных о свойствах

Специфичная для класса реализация определенных входных базовых классов и их присоединенных свойств или присоединенных событий

Поддержка стиля

Дальнейшая поддержка анимации


Другими словами, Вы должны работать с FrameworkElement, а не с элементом пользовательского интерфейса. Я часто использую ссылку на "границу" (видимую или нет) вокруг моего основного целевого визуального объекта.


tool__

Я не знаю, как использовать ваш код, если вы можете изменить код, который я опубликовал выше для меня...

В любом случае вы, вероятно, правы, что проблема связана с некоторыми изменениями размера, которые происходят... Я не заметил, что продуцируемая картинка моментального снимка немного меньше, чем окно самой запущенной программы... вероятно, достаточно маленький, чтобы произвести этот эффект размытия...
Однако я почти готов навсегда отказаться от идеи моментального снимка из-за этой проблемы и некоторых других проблем с выравниванием, которые возникли... результат неутешителен... Я выбираю более простую программу, с кодом, который я могу обрабатывать, меньше функций для программы, больше мозговых клеток для меня.

Тогда Спасибо за ваше время

Gerry Schmitz

Ты подключаешься к этой штуке в туманности, которая называется Windows.Контент и кастинг как элемент пользовательского интерфейса, когда я сказал вам использовать элемент фреймворка, например границу, для ссылки. В какой части я не совсем понимаю?

tool__

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

Gerry Schmitz

<окно>
<border x:name="UxVisual">
... вещи в рамке, например сетка с текстовыми полями.



Вы можете сделать все это в памяти без окна, но в вашем случае, вероятно, лучше попробовать WYSIWYG. Теперь ссылайтесь на границу по имени (в данном случае) как на элемент фреймворка (вместо использования WINDOW.Контент как "тупой" элемент пользовательского интерфейса). Или вы не понимаете ни одного кода, который вы разместили?

tool__

Я отредактировал код в оригинальном посте, проверьте его, пожалуйста.
в этой строке:
Элемент FrameworkElement = UxVisual.Содержание как класс FrameworkElement;

Слово "содержание" подчеркнуто красным, и на нем написано::

'Border' не содержит определения для 'content', и не может быть найден доступный метод расширения 'Content', принимающий первый аргумент типа 'Border'. (вам не хватает директивы using или реферирования сборки?)

tool__

Я понял это, ссылаясь только на его название ... снимок теперь пустой и содержит только границу...

хотя таким образом Вы имеете полный контроль над тем, что находится на границе ... и граница сама по себе выглядит пиксельно идеальной до сих пор... она пуста... никакие другие объекты не появляются в моментальном снимке, которые находятся в программе при запуске...

во всяком случае, это большое улучшение по сравнению с тем, что было раньше, чувак... спасибо

Gerry Schmitz

"Контент" - это "свойство" , которое элементы управления, производные от "content control", используют для добавления одного дочернего элемента к этому "родителю". Поэтому, когда вы ссылаетесь на "границу", то это "имя", а не свойство "содержание".

И ваши вещи (в границе), вероятно, не отображаются, потому что они являются "изображениями", и вы, вероятно, не обрабатываете их должным образом (я могу сказать это по беспорядку свойств выравнивания). Начните с текстового блока и некоторого текста.

tool__

Я ходил на многие форумы с этой проблемой

https://stackoverflow.com/questions/55772622/low-quality-picture-produced-by-snapshot-wpf

И они дали мне всевозможные решения, я перепробовал их все, ни одно не работает... Кажется, только ты знаешь, что происходит...
С помощью вашего метода я могу иметь полный контроль над тем, что находится в моментальном снимке, и более того, каждый объект, находящийся в пределах границы, отображается в моментальном снимке пиксельно идеально... именно так... Я могу дать вам только 5 звезд.

Gerry Schmitz

ОК... Хорошо. Похоже, у тебя все получилось. Эта ссылка может дать вам больше информации (хотя я не рассматривал ее подробно).

https://code.msdn.microsoft.com/windowsdesktop/Capturing-UI-Elements-in-dfd2dc66

Рейтинг:
1

Richard MacCutchan

PixelFormats.Pbgra32

Попробуйте формат с более высоким разрешением.


tool__

я перепробовал все пиксельные форматы этой страницы,
https://docs.microsoft.com/en-us/dotnet/api/system.windows.media.pixelformats?view=netframework-4.8
никто не работает, он говорит, что формат не поддерживается, за исключением Pbgra32

Richard MacCutchan

Тогда, я думаю, вам придется жить с более низким качеством изображения.