ブログ用 画像ユーティリティ ⑦ 画像のデコードと保存
ユーザーコントロールVgaImageUC クラスはファイルに保存する Save() メソッドを公開します。自分がロードされていないとき(App.xaml.csから呼び出されたとき)自分が持っているVGAサイズの画像を保存し、自分がロードされているときは、モザイク画像が含まれた(モザイク画像がないことのほうが多いかもしれませんが...)合成画像を生成するもので、Visual を引数として取り、RenderTargetBitmap 経由で Bitmapを生成してから保存します。どちらも jpg にエンコードして保存する EncodeAndSave メソッドに BitmapFrame を渡します。
EncodeAndSave メソッドでは、まずファイル名の先頭に「_」、.jpgの前に「VGA」を追加して(VGAVGAと続くとかっこわるかったので、一度処理したものは「_」だけを追加)、出力用の FileStream を作成します。「_」を加えたのは、ブログにアップロードするときのファイルオープンダイアログで一番先頭に表示させるためです。そして渡された BitmapFrame をJpegBitmapEncoder に与えて、作成した FileStream に保存します。JpegBitmapEncoder のSDKサンプルでは QualityLevel が30でしたが、30だと画像が荒すぎて不評だったので、80にしました。結果のファイルは数十KB程度の大きさになります。
/// <summary>
/// Canvasから画像を保存
/// </summary>
public void Save()
{
BitmapFrame bmf;
if (this.IsLoaded)
{
RenderTargetBitmap rtb =
new RenderTargetBitmap((int)myImage.Width,
(int)myImage.Height,
96.0, 96.0,
PixelFormats.Pbgra32);
rtb.Render(myCanvas);
bmf = BitmapFrame.Create(rtb);
}
else
{
BitmapImage bi =
CreateSmallImage(_vgaWidth, this.FileName);
bmf = BitmapFrame.Create(bi);
}
EncodeAndSave(bmf,this.FileName);
}
/// <summary>
/// BitmapFrameから画像を保存
/// </summary>
private void EncodeAndSave(BitmapFrame bmf, string filename)
{
// ファイル名の設定
string name = System.IO.Path.GetFileName(filename);
bool IsShrinked = false;
if (name.Contains("_") && name.Contains("VGA."))
IsShrinked = true; // 一度処理済み
string newname = "_" + name;
string fileOut = filename.Replace(name, newname);
if (!IsShrinked)
fileOut = (filename.Contains(".jpg")) ?
fileOut.Replace(".jpg", "VGA.jpg") :
fileOut.Replace(".JPG", "VGA.JPG");
FileStream stream = new FileStream(fileOut, FileMode.Create);
// jpgにエンコード
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.FlipHorizontal = false;
encoder.FlipVertical = false;
encoder.QualityLevel = 80;
encoder.Rotation = Rotation.Rotate0;
encoder.Frames.Add(bmf);
encoder.Save(stream);
stream.Close();
}