|
■No86116 (Hongliang さん) に返信
> 2017/12/19(Tue) 11:14:32 編集(投稿者)
>
> new Bitmapする際に、適切なPixelFormatを与えてください。
> System.Windows.Media.PixelFormatからSystem.Drawing.Imaging.PixelFormatへの変換は確か標準ライブラリには存在しなかったので、自分でマッピングする必要があるでしょう。
>
> // Bitmap::GetHiconする際だったか、Icon.FromHandleする際だったかにすごい勢いの画質劣化があったような記憶が…。
> // 確か強制的に4bppに変換されたような…?
var bitmap = new Bitmap(width, height, stride, System.Drawing.Imaging.PixelFormat.Format64bppPArgb, intPtr)
上記のようにPixelFormatを指定することで、Iconへの変換、Iconファイルとしての保存が出来るようになりました。
ただ、色劣化が酷く、元の画像とは似ても似つかないものになってしまいました。
どのPixelFormatが適当なのか、全て試してみます。
現在のところ、以下のようなコードとなっています。
try
{
IconBitmap iconBitmap = (IconBitmap)this.listView1.SelectedItem;
BitmapSource bitmapSource = iconBitmap.BitmapSource;
#region 過去コード
/*
// フォーマットが異なるならば変換
if (bitmapSource.Format != PixelFormats.Bgr32)
{
bitmapSource = new FormatConvertedBitmap(bitmapSource, PixelFormats.Bgr32, null, 0);
bitmapSource.Freeze();
}
// ピクセルデータをコピー
int width = (int)bitmapSource.Width;
int height = (int)bitmapSource.Height;
int stride = width * 4;
byte[] datas = new byte[stride * height];
bitmapSource.CopyPixels(datas, stride, 0);
// Bitmap へピクセルデータ書き出し
Bitmap dest = new Bitmap(width, height, Imaging::PixelFormat.Format32bppArgb);
Imaging::BitmapData destBits = null;
try
{
destBits = dest.LockBits(new System.Drawing.Rectangle(0, 0, width, height), Imaging::ImageLockMode.WriteOnly, Imaging::PixelFormat.Format32bppArgb);
Marshal.Copy(datas, 0, destBits.Scan0, datas.Length);
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "変換失敗");
dest.Dispose();
dest = null;
throw;
}
finally
{
if (dest != null && destBits != null)
{
dest.UnlockBits(destBits);
}
}
*/
#endregion
// BitmapSourceをBitmapに変換
int width = bitmapSource.PixelWidth;
int height = bitmapSource.PixelHeight;
//int stride = width * ((bitmapSource.Format.BitsPerPixel + 7) / 8); // 行の長さは色深度によらず8の倍数のため
int stride = (((width * bitmapSource.Format.BitsPerPixel) + 31) / 32) * 4;
IntPtr intPtr = IntPtr.Zero;
intPtr = Marshal.AllocCoTaskMem(height * stride);
bitmapSource.CopyPixels(new Int32Rect(0, 0, width, height), intPtr, height * stride, stride);
using (var bitmap = new Bitmap(width, height, stride, System.Drawing.Imaging.PixelFormat.Format64bppPArgb, intPtr))
{
try
{
// BitmapをIconに変換
//System.Drawing.Icon icon = System.Drawing.Icon.FromHandle(bitmap.GetHicon());
//System.Drawing.Icon icon = System.Drawing.Icon.FromHandle(IntPtr.Zero);
IntPtr Hicon = bitmap.GetHicon();
Icon newIcon = System.Drawing.Icon.FromHandle(Hicon);
try
{
// 保存
SaveFileDialog dialog = new SaveFileDialog();
dialog.FileName = "新しいアイコン.ico";
dialog.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
dialog.Filter = "アイコンファイル(*.ico)|*.ico|すべてのファイル(*.*)|*.*";
dialog.FilterIndex = 0;
dialog.Title = "保存先のファイルを指定して下さい";
dialog.RestoreDirectory = true;
dialog.OverwritePrompt = true;
dialog.CheckPathExists = true;
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
String newIconFile = dialog.FileName;
using (FileStream fileStream = new FileStream(newIconFile, FileMode.Create, FileAccess.Write))
{
newIcon.Save(fileStream);
fileStream.Close();
}
}
}
catch (Exception exception)
{
System.Windows.Forms.MessageBox.Show(exception.Message, "Iconの保存失敗");
return;
}
DestroyIcon(Hicon);
}
catch (Exception exception)
{
System.Windows.Forms.MessageBox.Show(exception.Message, "BitmapをIconに変換失敗");
return;
}
}
}
catch (Exception exception)
{
System.Windows.Forms.MessageBox.Show(exception.Message, "変換失敗");
}
|