##前提
環境:VS2019
言語:C# WPF
##最終的に達成したい事
リッチテキストボックスに、より多くの画像を高速に表示したい。
##悩んでいる事
以前、以下のような質問をしました。
【C#】【WPF】リッチテキストボックスに貼り付けた画像をバイナリーに保存して次回起動した際に表示したい
自己解決したのですが、ある程度運用していて気付いたのが、FlowDocumentをそのままバイナリにするととてつもなく重いという問題に直面しました。なんてことのない画像1枚を貼った場合でも、5MB程になっています。
この問題を解消する為に、画像のみをバイナリ化し、アプリケーション起動時にFlowDocumentを構築するようにしたいと思いました。
現状、以下のような方法で画像をバイナリ化しています。
C#
1/// <summary> 2/// BitmapSourceをbyte[]型へ変換 3/// </summary> 4/// <param name="bs"></param> 5/// <returns></returns> 6public static byte[] ToBinary(this BitmapSource bs) 7{ 8 if (bs == null) return null; 9 using (var ms = new MemoryStream()) 10 { 11 var encoder = new PngBitmapEncoder(); 12 encoder.Frames.Add(BitmapFrame.Create(bs)); 13 encoder.Save(ms); 14 ms.Seek(0, SeekOrigin.Begin); 15 return ms.GetBuffer(); 16 } 17}
85KBのPNGをこのメソッドを通してバイナリ化すると129KBになりました。
目標値などはありませんが、これ以上に圧縮する事は可能でしょうか?
エンコードは以下の様なコードです。
これだとメモリリークすると、どこかで拝見したことあります。タスクマネージャーでメモリをみる限りだとそんな事はないように見えていますが、より高速に、メモリリークのない正しいデコードの仕方などはありますでしょうか。
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 //当初はアイコンのみを扱うつもりだったが様々なサイズの画像を扱うためコメントアウト 15 //image.DecodePixelHeight = 16; 16 //image.DecodePixelWidth = 16; 17 image.CacheOption = BitmapCacheOption.OnLoad; 18 image.CreateOptions = BitmapCreateOptions.PreservePixelFormat; 19 image.StreamSource = ms; 20 image.EndInit(); 21 image.Freeze(); 22 return image; 23 } 24}
##試してみた事
-
PNGとJPEGでは当然、JPEGの方が軽いでしょうと思い、JpenBitmapEncoderを使用してみましたが増加してしまい、257KBとなりました。
-
PngBitmapEncoderにはありませんが、JpenBitmapEncoderにはQualityLevelプロパティがあり、最低品質の1に設定すると、20KBになりました。デコードして確認してみたところ、違和感はないようですが、やはり品質を落とすぐらいしかないのでしょうか。。
-
バイナリをBase64に変換して使用する文字数を減らすことで圧縮率が上がるのでは?と考えましたが、171KBに増えました。(1.33倍になるのは本当でした)
回答4件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/08/31 06:04
2019/08/31 13:47