将Icon对象转换为byte []会导致质量损失

问题描述 投票:1回答:1

我正在制作一个WPF应用程序,其中Image有来自ImageSource对象的Icon

为了将它保存在磁盘上,我将它们转换为byte[],而ImageSource的getter将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[]

非常感谢

c# .net wpf type-conversion icons
1个回答
3
投票

而不是使用Icon.Save(),使用Icon.ToBitmap()从Icon创建一个System.Drawing.Bitmap,并保存:

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();
}

或者,在转换为BitmapSource后创建byte[]

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();
}

© www.soinside.com 2019 - 2024. All rights reserved.