Преобразование объекта Icon в byte [] и обратно приводит к снижению качества - PullRequest
0 голосов
/ 07 октября 2018

Я создаю приложение WPF, в котором Image имеет ImageSource от объекта Icon.

Чтобы сохранить его на диске, я преобразую их в byte[], и получательдля ImageSource конвертируйте byte[] обратно в ImageSource.

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

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

XAML

<Window x:Class="POCicon.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:POCicon"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MyViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Image Source="{Binding WithConversion}" MaxHeight="32" MaxWidth="32" Stretch="Fill" ></Image>
        <Image Grid.Column="1" Source="{Binding NoConversion}" MaxHeight="32" MaxWidth="32" Stretch="Fill" ></Image>
    </Grid>
</Window>

C # ViewModel

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace POCicon
{
    public class MyViewModel
    {
        private System.Drawing.Icon Icon;
        public MyViewModel()
        {
            Icon= System.Drawing.Icon.ExtractAssociatedIcon("C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe");
        }
        public ImageSource WithConversion
        {
            get
            {
                byte[] byteArray;
                using (MemoryStream serializer = new MemoryStream())
                {
                    Icon.Save(serializer);
                    byteArray = serializer.ToArray();
                }
                using (MemoryStream deserializer = new MemoryStream(byteArray))
                {
                    BitmapImage image = new BitmapImage();
                    image.BeginInit();
                    // image.CreateOptions = BitmapCreateOptions.PreservePixelFormat; //totally useless unfortunately
                    image.StreamSource = deserializer;
                    image.EndInit();
                    return image;
                }
            }
        }

        public ImageSource NoConversion
        {
            get
            {
                var imgSource = Imaging.CreateBitmapSourceFromHIcon(Icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                return imgSource;
            }
        }

    }
}

Есть ли способ исправить этот метод или получить желаемый результат по другому маршруту?Требование заключается в том, что в какой-то момент это должен быть Icon объект, а в конечном итоге - byte[].

Большое спасибо

1 Ответ

0 голосов
/ 07 октября 2018

Вместо использования Icon.Save() используйте Icon.ToBitmap() для создания System.Drawing.Bitmap из Icon и сохраните его:

var icon = System.Drawing.Icon.ExtractAssociatedIcon(
    @"C:\Program Files (x86)\JetBrains\dotPeek\v1.1\Bin\dotpeek32.exe");
var bitmap = icon.ToBitmap();

byte[] buffer;

using (var memoryStream = new MemoryStream())
{
    bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
    buffer = memoryStream.ToArray();
}

В качестве альтернативы создайте byte[] после преобразования в BitmapSource:

var icon = System.Drawing.Icon.ExtractAssociatedIcon(
    @"C:\Program Files (x86)\JetBrains\dotPeek\v1.1\Bin\dotpeek32.exe");
var bitmapSource = Imaging.CreateBitmapSourceFromHIcon(
    icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));

byte[] buffer;

using (var memoryStream = new MemoryStream())
{
    encoder.Save(memoryStream);
    buffer = memoryStream.ToArray();
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...