ryanba29 Ответов: 1

Как я могу уменьшить размер растрового источника перед отправкой его на клипборд?


Я использую следующий код для рендеринга FrameworkElement в BitmapSource, а затем копирую его на клипборд. Все работает так, как задумано, за исключением того, что размер изображения составляет 2,5 МБ+. Если я вставлю его в MS paint и сохраню в виде PNG-файла, то размер уменьшится до 25 КБ. Как уменьшить размер изображения перед копированием на клипборд?

public static BitmapSource ConvertToBitmapSource(FrameworkElement element)
        {
            var pageSize = new System.Windows.Size(element.ActualWidth, element.ActualHeight);

            element.Measure(pageSize);
            element.Arrange(new Rect(pageSize));
            element.UpdateLayout();

            RenderTargetBitmap bmp = new RenderTargetBitmap((int)pageSize.Width, (int)pageSize.Height, 96, 96, PixelFormats.Pbgra32);
            bmp.Render(element);            
            
            return bmp;
        }

Затем я использую это для копирования на клипборд.
Clipboard.SetImage(bitmapsource);


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

Я пытался уменьшить качество PixelFormat, но WPF использует Pbgra32. Может быть, я упускаю что-то очень простое. Я новичок в WPF imaging.

Dave Kreskowiak

В итоге получается 25 тысяч на диске, а не в памяти. В памяти он по-прежнему составляет 2,5 МБ.

ryanba29

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

Dave Kreskowiak

Как файл, конечно. Но как представление изображения, оно все равно будет 32 бита на пиксель для всего изображения. Если вы измените глубину пикселя и создадите новый объект изображения, он будет меньше, но у вас больше не будет исходного изображения. Он будет более низкого качества, потому что глубина цвета будет потеряна.

ryanba29

Обновление. - Вы правы. Мое изображение уменьшается до 66k, как только я вставляю его туда, где это необходимо. Если вы хотите опубликовать ответ, говорящий то же самое, я его приму.

1 Ответов

Рейтинг:
8

Jochen Arndt

Проверьте, какие форматы изображений принимаются принимающим приложением через буфер обмена. Если принимающее приложение принимает PNG-изображения, вы можете создать PNG-изображение из растрового изображения в памяти и поместить его в буфер обмена.

Но меня бы не волновал размер 2,5 МБ. как только изображение было передано в буфер обмена, оно может быть удалено в вашем приложении, если не используется anmyore. Затем у вас есть 2,5 МБ, используемых системой, которые освобождаются всякий раз, когда другие данные копируются в буфер обмена. А 2,5 МБ-это не так уж много в наши дни, когда системы имеют ГБ памяти.


ryanba29

Спасибо, что нашли время ответить,но мой размер беспокоит вас здесь, на клиповой доске или в приложении finial. Дэйв Кресковяк прав: большой размер в памяти не имеет значения, потому что он уменьшается до соответствующего размера после использования с клиповой платы.

Jochen Arndt

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

Конечное приложение обычно снова создает растровое изображение (например, Paint преобразует PNG обратно в растровое изображение в памяти, которое снова имеет исходный размер, где не имеет значения, скопирован ли PNG из буфера обмена или загружен из файла.

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

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

Для буфера обмена было бы решение все еще присутствующее со старых времен более низкой памяти:
Передача данных cliboard в виде файловых потоков. Это создание потока файлов (IStream), запись растрового изображения в него и передача потока в буфер обмена (IDataObject), который владеет им, и удаление файла, когда новые данные помещаются в буфер обмена или запрашивают опустошение буфера обмена. Тогда изображение хранится не в памяти, а во временном файле.

Но не спрашивайте меня, как это сделать с C#.