質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

2回答

6210閲覧

【C#】【WPF】byte[]型からBitmapSourceを作成した場合に背景が黒くなってしまう

OXamarin

総合スコア59

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

0クリップ

投稿2019/07/30 17:16

編集2019/07/30 17:58

##前提
環境:VS2019
言語:C# WPF

##分からない事
byte[]型からBitmapSourceを作成した場合に画像の背景が黒くなってしまうが、透明なままにするにはどうすればよいか。

##具体的な内容
画像をシリアライズする方法がわからず、過去に以下の質問をさせていただきました。
MessagePack for C# でBitmapSource型をシリアライズするには?

BitmapSourceを直接シリアライズする事ができないので、一度byte[]型へ変換したものをシリアライズするという方法で実装しました。簡易的ですが、以下の様に実装しています。

C#

1//アイコンの取得(BitmapSource型) 2var icon = Utility.GetIcon(filePath); 3 4//byte[]型へ変換 5var byteArray = icon.ToByteArray(); 6 7/// <summary> 8/// ファイルパスのアイコンを取得する 9/// </summary> 10/// <param name="filePath"></param> 11/// <returns></returns> 12public static BitmapSource GetIcon(string filePath) 13{ 14 using (var file = ShellFile.FromFilePath(filePath)) 15 { 16 file.Thumbnail.FormatOption = ShellThumbnailFormatOption.IconOnly; 17 return file.Thumbnail.SmallBitmapSource; 18 } 19} 20/// <summary> 21/// BitmapSourceをbyte[]型へ変換 22/// </summary> 23/// <param name="bs"></param> 24/// <returns></returns> 25public static byte[] ToByteArray(this BitmapSource bs) 26{ 27 using (var ms = new MemoryStream()) 28 { 29 var encoder = new BmpBitmapEncoder(); 30 encoder.Frames.Add(BitmapFrame.Create(bs)); 31 encoder.Save(ms); 32 return ms.GetBuffer(); 33 } 34}

この時点では、アイコンの背景は黒くなっていません。
イメージ説明]

byte[]型でシリアライズできたので、シリアライズしたものを以下のメソッドでbyte[]型からBitmapSource型へ変換しました。

C#

1/// <summary> 2/// byte[]型をBitmapSourceへ変換 3/// </summary> 4/// <param name="byteArray"></param> 5/// <returns></returns> 6public static BitmapSource ToBitmapSource(this byte[] byteArray) 7{ 8 using (var ms = new MemoryStream(byteArray)) 9 { 10 var image = new BitmapImage(); 11 12 ms.Seek(0, SeekOrigin.Begin); 13 image.BeginInit(); 14 image.CacheOption = BitmapCacheOption.OnLoad; 15 image.CreateOptions = BitmapCreateOptions.PreservePixelFormat; 16 image.StreamSource = ms; 17 image.EndInit(); 18 image.Freeze(); 19 return image; 20 21 //上記だとFormatがBgr32だったのでBgra32に変換するが、これもダメ 22 var bitmap = new FormatConvertedBitmap(image, PixelFormats.Bgra32, null, 0); 23 return bitmap; 24 } 25}

そうすると、何故かアイコンの背景色が黒くなってしまいます。
イメージ説明

どのようにすれば、画像の背景を透明なままに、byte[]型からBitmapSource型へ変換できるのでしょうか。

###調べた事
・背景色を透明にできるかどうかは、α値を持っているかどうかに依るということです。α値を持っているのは、GIF・PNG・ICONなのでそれ以外は背景色が透明の場合は黒くなってしまう。

・アイコンを取得した直後と、デシリアライズしたbyte[]型からアイコンを生成した場合のプロパティを全て比較してみました。違いとしては一点で、

  • アイコンを取得した直後のフォーマットがBgra32 だったのに対して、
  • デシリアライズしたbyte[]型からアイコンを生成した場合のフォーマットがBgr32 でした。

なので、FormatConvertedBitmapでBgra32へ変換してみたが、それでも背景は黒いままでした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

BmpBitmapEncoderはおそらく透過情報の保存に対応していませんので(未確認)、PNGエンコーダーにしてみてください。
(と、前回PNG形式を推したつもりでしたが)

BMP形式自体はアルファチャンネルを保持できるようになっていますが、それはを解釈できるかはエンコーダーデコーダー次第なんだと思われます。

投稿2019/07/31 00:31

編集2019/07/31 00:37
takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

OXamarin

2019/07/31 13:02

前回に引き続き答えて頂きありがとうございます。 透明度も考慮したリンクだったのですね。意図を汲み取れずすみません。 無事に圧縮前のアイコンに戻すことができました。
guest

0

WPFはあまり分からないので軽く検索した結果ですが、
送信側のBmpBitmapEncoderでbyte[]にしている時点でα値の情報が抜け落ちているのではないですか?
α値をサポートしているPngBitmapEncoderを使ってみるとか

投稿2019/07/30 23:30

YAmaGNZ

総合スコア10242

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

OXamarin

2019/07/31 13:01

仰る通りでPngBitmapEncoderを使う事で透明度を保持できたままバイナリにできました。ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問