- - PR -
C#[WPF] BitmapEncoderが機能しない
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2008-05-11 18:20
「C#(WPF) DrawingImageオブジェクトをJPEGファイルに保存する方法」という題目で掲載しましたが、
問題をきちんと把握しないまま質問してしまいすみませんでした。 より具体的に質問できる状態になりましたので、再トライしてみたいと考え掲載することにしました。 宜しくお願いします サンプルコードをご参照願います。 【現象】 ・JPEGファイルが生成されるが、中身は真っ黒なままである。 ・画面には丸底フラスコが表示されることを確認済みである。 【課題】 水で満たされた丸底フラスコをImageコントロール(WPF)を使って画面表示する。 また、描画内容をJPEG形式のファイルに保存する。 【質問1】 Bitmapファイルの中身が真っ黒なままの原因が分かりません。 (FurasukoLibのSaveBmp()の記述に問題があると考えています) 【質問2】 RenderTargetBitmap render = new RenderTargetBitmap(100, 200, 96, 96, PixelFormats.Pbgra32); のPixelFormats.Pbgra32を別の形式に変更すると実行時エラーが発生し、変更できない原因が分かりません。 24bitRGB形式で出力にしたいのですが、どうすればよいのでしょうか? 以下、サンプルコード (呼び出し元、呼び出し先の2つに分かれています) // 呼び出し元のソースコード // XAML連携の相互作用ロジックと記載されていますが、実際はWindowを呼び出しているだけで、 // XAMLで特別な処理をしているわけではありません。必要な参照があれば実行できるはずです。 using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; [assembly: CLSCompliant(true)] namespace WpfApplication1 { /// <summary> /// Window1.xaml の相互作用ロジック /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { Image img = new Image(); // 水を120満たした丸底フラスコを作成します。 // Fura.CreateFura()はDrasingImageを返します。 img.Source = FurasukoLib.CreateFura(120); img.Width = 100; img.Height = 200; img.Stretch = Stretch.None; // JPEGファイルを作成します。(Bitmapファイルが作成されるが、画像は真っ黒である) FurasukoLib.SaveJpeg("new.jpg", img.Source); Window wnd = new Window(); wnd.Content = img; // 水に満たされた丸底フラスコを表示します。(正しく表示できることを確認済み) wnd.ShowDialog(); } } } // 呼び出し先のソースコード using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; namespace WpfApplication1 { public static class FurasukoLib { /// <summary> /// 丸底フラスコを描画オブジェクトを作成します。 /// </summary> /// <param name="waterDepth">水深</param> /// <returns>描画オブジェクト</returns> public static DrawingImage CreateFura(double waterDepth) { // 丸底フラスコの底 EllipseGeometry sokoPgeo = new EllipseGeometry(new Rect(0, 0, 100, 100)); // 丸底フラスコの首 RectangleGeometry kubiPgeo = new RectangleGeometry(new Rect(0, 0, 50, 150)); // 水の領域(深さが変化します) // 練習のためRectangleGeometryを使わず線分から組み立てます。 // STEP1 線分を作成します。 // 始点は(0,200)を想定しています。 PolyLineSegment mizuSeg = new PolyLineSegment(); mizuSeg.Points.Add(new Point(100, 200)); mizuSeg.Points.Add(new Point(100, 200 - waterDepth)); mizuSeg.Points.Add(new Point(0, 200 - waterDepth)); // STEP2 ジオメトリのサブセクション=2次元幾何学セグメントを作成します。 PathFigure mizuFig = new PathFigure(); mizuFig.StartPoint = new Point(0, 200); mizuFig.Segments.Add(mizuSeg); mizuFig.IsFilled = true; mizuFig.IsClosed = true; // STEP3 ジオメトリに変換します PathGeometry mizuPgeo = new PathGeometry(); mizuPgeo.Figures.Add(mizuFig); // STEP4 複数のジオメトリを組み合わせます。 // 変換を使って底を首を平行移動します。 sokoPgeo.Transform = new TranslateTransform(0, 100); // 底をY軸方向に100平行移動 kubiPgeo.Transform = new TranslateTransform(25, 0); // 首をX軸方向に25平行移動 // 底と首を結合して丸底フラスコを完成させます。 CombinedGeometry furaGeo = new CombinedGeometry(sokoPgeo, kubiPgeo); furaGeo.GeometryCombineMode = GeometryCombineMode.Union; // 丸底フラスコのうち水で満たされている領域を抽出します。 CombinedGeometry mizufuraGeo = new CombinedGeometry(furaGeo, mizuPgeo); mizufuraGeo.GeometryCombineMode = GeometryCombineMode.Intersect; // 重なっているる領域 // ここまでの操作で、必要なジオメトリが準備できましたので描画に移ります。 // STEP5 GeometryDrawingを作成します。 // 丸底フラスコ全体の描画 GeometryDrawing furaGdwg = new GeometryDrawing(); furaGdwg.Geometry = furaGeo; furaGdwg.Brush = Brushes.Transparent; // 透明で塗りつぶす。 furaGdwg.Pen = new Pen(Brushes.Black, 0.5); // 黒色でふちどる // 丸底フラスコのうち水で満たされている領域の描画 GeometryDrawing mizufuraGdwg = new GeometryDrawing(); mizufuraGdwg.Geometry = mizufuraGeo; mizufuraGdwg.Brush = Brushes.LightBlue; // 水色で塗りつぶす mizufuraGdwg.Pen = new Pen(Brushes.Blue, 1); // 青色でふちどる // STEP6 丸底フラスコ全体と水で満たされている領域をグループ化します。 DrawingGroup furaDwgg = new DrawingGroup(); furaDwgg.Children.Add(furaGdwg); furaDwgg.Children.Add(mizufuraGdwg); // STEP7 DrawingImageに変換します。 DrawingImage dwgImg = new DrawingImage(); dwgImg.Drawing = furaDwgg; return dwgImg; } /// <summary> /// ImageSourceをBitmapファイルに変換します。 /// </summary> /// <param name="path">ファイルの作成先のPath</param> /// <param name="imgSource">イメージソース</param> public static void SaveJpeg(string path, ImageSource imgSource) { Image img = new Image(); img.Width = 100; img.Height = 200; img.Source = imgSource; DrawingVisual dv = new DrawingVisual(); dv.Children.Add(img); RenderTargetBitmap render = new RenderTargetBitmap(100, 200, 96, 96, PixelFormats.Pbgra32); render.Render(dv); BitmapEncoder enc = new JpegBitmapEncoder(); enc.Frames.Add(BitmapFrame.Create(render)); using (System.IO.FileStream stream = new System.IO.FileStream(path, System.IO.FileMode.Create)) { enc.Save(stream); } } } } | ||||
|
投稿日時: 2008-05-11 18:23
リンク先が反映されなかったようなので、掲載します。
前回の質問(参考) http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=44486&forum=7 | ||||
|
投稿日時: 2008-05-11 19:16
右上の「参照元記事」になっているのがそうじゃないですか? で、本題ですが、このスレッドの記述で何が分かりませんか? http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=42480&forum=7&2 [追記] どうせ JpegBitmapEncoder がエンコードする際に 24bpp に変更しますが、それじゃ不都合なのでしょうか? [/追記] [ メッセージ編集済み 編集者: Hongliang 編集日時 2008-05-11 19:33 ] | ||||
|
投稿日時: 2008-05-14 00:06
ご回答ありがとうございます。
Hongliangさんにはとても感謝しています。 やっと、JPEGファイルを作成することができました。 ソースコードを下記のように修正することで、 水色のフラスコが描かれたJPEGファイルが生成しました。(背景が黒色のままですが) 未だDrowVisual,DrawContext,RenderTargetBtimap,BitmapEncorderの役割が きっちりふにおちているわけではありませんが、私にとっては前進です。 MSDNを見ながら、頭を整理しようと思います。 /// <summary> /// ImageSourceをBitmapファイルに変換します。 /// </summary> /// <param name="path">ファイルの作成先のPath</param> /// <param name="imgSource">イメージソース</param> public static void SaveJpeg(string path, ImageSource imgSource) { Image img = new Image(); img.Width = 100; img.Height = 200; img.Source = imgSource; DrawingVisual dv = new DrawingVisual(); DrawingContext dc = dv.RenderOpen(); dc.DrawImage(imgSource, new Rect(0, 0, 100, 200)); dc.Close(); RenderTargetBitmap render = new RenderTargetBitmap(100, 200, 96, 96, PixelFormats.Pbgra32); render.Render(dv); BitmapEncoder enc = new JpegBitmapEncoder(); enc.Frames.Add(BitmapFrame.Create(render)); using (System.IO.FileStream stream = new System.IO.FileStream(path, System.IO.FileMode.Create)) { enc.Save(stream); } } |
1