OSDN Git Service

e502964759ebf388e1542a3cfc9368d797e36e98
[strokestylet/CsWin10Desktop3.git] / FDK24 / メディア / 画像.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4
5 namespace FDK.メディア
6 {
7         public class 画像 : Activity
8         {
9                 public bool 生成成功 => ( null != this.Bitmap );
10                 public bool 生成失敗 => ( null == this.Bitmap );
11
12                 /// <summary>
13                 /// 画像は、設計単位で作成される。
14                 /// </summary>
15                 public SharpDX.Size2F サイズdpx => new SharpDX.Size2F( (float) this.Bitmap.PixelSize.Width, (float) this.Bitmap.PixelSize.Height );
16
17                 // あまり頻繁に変更されないであろう描画パラメータは、メソッド引数ではなくプロパティにしておく。
18                 public SharpDX.Direct2D1.InterpolationMode 補正モード { get; set; } = SharpDX.Direct2D1.InterpolationMode.Linear;
19                 public bool 加算合成 { get; set; } = false;
20
21                 public 画像( string 画像ファイルパス )
22                 {
23                         this.画像ファイルパス = FDK.フォルダ.絶対パスに含まれるフォルダ変数を展開して返す( 画像ファイルパス );
24                 }
25                 protected override void Onデバイス依存リソースの作成( デバイスリソース dr )
26                 {
27                         this.画像を生成する( dr );
28                 }
29                 protected override void Onデバイス依存リソースの解放( デバイスリソース dr )
30                 {
31                         FDK.Utilities.解放する( ref this.Bitmap );
32
33                         string 変数付きファイルパス = フォルダ.絶対パスをフォルダ変数付き絶対パスに変換して返す( this.画像ファイルパス );
34                         //Log.Info( $"{Utilities.現在のメソッド名}: 画像を解放しました。[{変数付きファイルパス}]" );
35                 }
36
37                 /// <summary>
38                 /// 画像を描画する。
39                 /// </summary>
40                 /// <param name="dr">デバイスリソース。</param>
41                 /// <param name="左位置dpx">画像の描画先範囲の左上隅X座標。</param>
42                 /// <param name="上位置dpx">画像の描画先範囲の左上隅Y座標。</param>
43                 /// <param name="不透明度0to1">不透明度。(0:透明~1:不透明)</param>
44                 /// <param name="X方向拡大率">画像の横方向の拡大率。</param>
45                 /// <param name="Y方向拡大率">画像の縦方向の拡大率。</param>
46                 /// <param name="転送元矩形dpx">画像の転送元範囲。画像は設計単位で作成されている。</param>
47                 /// <param name="変換行列3Dpx">射影行列。Direct2D の仕様により、設計単位ではなく物理単位で構築すること。</param>
48                 public virtual void 進行描画する(
49                         FDK.メディア.デバイスリソース dr,
50                         float 左位置dpx,
51                         float 上位置dpx,
52                         float 不透明度0to1 = 1.0f,
53                         float X方向拡大率 = 1.0f,
54                         float Y方向拡大率 = 1.0f,
55                         SharpDX.RectangleF? 転送元矩形dpx = null,
56                         SharpDX.Matrix? 変換行列3Dpx = null )
57                 {
58                         var 変換行列2Dpx = SharpDX.Matrix3x2.Identity
59                                 * SharpDX.Matrix3x2.Scaling( X方向拡大率, Y方向拡大率 )   // スケーリング。
60                                 * dr.行列を単位変換するDPXtoPX( SharpDX.Matrix3x2.Translation( 左位置dpx, 上位置dpx ) );   // 平行移動(物理単位)。
61
62                         this.進行描画する( dr, 変換行列2Dpx, 変換行列3Dpx, 不透明度0to1, 転送元矩形dpx );
63                 }
64
65                 /// <summary>
66                 /// 画像を描画する。
67                 /// </summary>
68                 /// <param name="dr">デバイスリソース。</param>
69                 /// <param name="変換行列2Dpx">Transform に適用する行列。Direct2D の仕様により、設計単位ではなく物理単位で構築すること。</param>
70                 /// <param name="変換行列3Dpx">射影行列。Direct2D の仕様により、設計単位ではなく物理単位で構築すること。</param>
71                 /// <param name="不透明度0to1">不透明度。(0:透明~1:不透明)</param>
72                 /// <param name="転送元矩形dpx">描画する画像範囲。画像は設計単位で作成されている。</param>
73                 public virtual void 進行描画する(
74                         FDK.メディア.デバイスリソース dr,
75                         SharpDX.Matrix3x2? 変換行列2Dpx = null,
76                         SharpDX.Matrix? 変換行列3Dpx = null,
77                         float 不透明度0to1 = 1.0f,
78                         SharpDX.RectangleF? 転送元矩形dpx = null )
79                 {
80                         Debug.Assert( this.活性化している );
81
82                         if( null == this.Bitmap )
83                                 return;
84
85                         Utilities.D2DBatchDraw( dr.D2DContext1, () => {
86
87                                 // 変換行列とブレンドモードをD2Dレンダーターゲットに設定する。
88                                 dr.D2DContext1.Transform = 変換行列2Dpx ?? SharpDX.Matrix3x2.Identity;
89                                 dr.D2DContext1.PrimitiveBlend = ( this.加算合成 ) ? SharpDX.Direct2D1.PrimitiveBlend.Add : SharpDX.Direct2D1.PrimitiveBlend.SourceOver;
90
91                                 // D2Dレンダーターゲットに this.Bitmap を描画する。
92                                 dr.D2DContext1.DrawBitmap(
93                                         bitmap: this.Bitmap,
94                                         destinationRectangle: null,
95                                         opacity: 不透明度0to1,
96                                         interpolationMode: this.補正モード,
97                                         sourceRectangle: 転送元矩形dpx,  // this.Bitmap は設計単位で作成されている。
98                                         erspectiveTransformRef: 変換行列3Dpx ); // null 指定可。
99                         } );
100                 }
101
102                 protected string 画像ファイルパス = null;
103                 protected SharpDX.Direct2D1.Bitmap1 Bitmap = null;
104
105                 protected void 画像を生成する( FDK.メディア.デバイスリソース dr, SharpDX.Direct2D1.BitmapProperties1 bitmapProperties1 = null )
106                 {
107                         var decoder = (SharpDX.WIC.BitmapDecoder) null;
108                         var sourceFrame = (SharpDX.WIC.BitmapFrameDecode) null;
109                         var converter = (SharpDX.WIC.FormatConverter) null;
110
111                         string 変数付きファイルパス = フォルダ.絶対パスをフォルダ変数付き絶対パスに変換して返す( this.画像ファイルパス );
112                         try
113                         {
114                                 #region " 画像ファイルパスの有効性を確認する。"
115                                 //-----------------
116                                 if( string.IsNullOrEmpty( this.画像ファイルパス ) )
117                                 {
118                                         Log.ERROR( $"画像ファイルパスが null または空文字列です。[{変数付きファイルパス}]" );
119                                         return;
120                                 }
121                                 if( false == System.IO.File.Exists( this.画像ファイルパス ) )
122                                 {
123                                         Log.ERROR( $"画像ファイルが存在しません。[{変数付きファイルパス}]" );
124                                         return;
125                                 }
126                                 //-----------------
127                                 #endregion
128                                 #region " 画像ファイルに対応できるデコーダを見つける。"
129                                 //-----------------
130                                 try
131                                 {
132                                         decoder = new SharpDX.WIC.BitmapDecoder(
133                                                 dr.WicImagingFactory2,
134                                                 this.画像ファイルパス,
135                                                 SharpDX.IO.NativeFileAccess.Read,
136                                                 SharpDX.WIC.DecodeOptions.CacheOnLoad );
137                                 }
138                                 catch( SharpDX.SharpDXException e )
139                                 {
140                                         Log.ERROR( $"画像ファイルに対応するコーデックが見つかりません。(0x{e.HResult:x8})[{変数付きファイルパス}]" );
141                                         return;
142                                 }
143                                 //-----------------
144                                 #endregion
145                                 #region " 最初のフレームをデコードし、取得する。"
146                                 //-----------------
147                                 try
148                                 {
149                                         sourceFrame = decoder.GetFrame( 0 );
150                                 }
151                                 catch( SharpDX.SharpDXException e )
152                                 {
153                                         Log.ERROR( $"画像ファイルの最初のフレームのデコードに失敗しました。(0x{e.HResult:x8})[{変数付きファイルパス}]" );
154                                         return;
155                                 }
156                                 //-----------------
157                                 #endregion
158                                 #region " 32bitPBGRA へのフォーマットコンバータを生成する。"
159                                 //-----------------
160                                 try
161                                 {
162                                         // WICイメージングファクトリから新しいコンバータを生成。
163                                         converter = new SharpDX.WIC.FormatConverter( dr.WicImagingFactory2 );
164
165                                         // コンバータに変換元フレームや変換後フォーマットなどを設定。
166                                         converter.Initialize(
167                                                 sourceRef: sourceFrame,
168                                                 dstFormat: SharpDX.WIC.PixelFormat.Format32bppPBGRA,
169                                                 dither: SharpDX.WIC.BitmapDitherType.None,
170                                                 paletteRef: null,
171                                                 alphaThresholdPercent: 0.0,
172                                                 paletteTranslate: SharpDX.WIC.BitmapPaletteType.MedianCut );
173                                 }
174                                 catch( SharpDX.SharpDXException e )
175                                 {
176                                         Log.ERROR( $"32bitPBGRA へのフォーマットコンバータの生成または初期化に失敗しました。(0x{e.HResult:x8})[{変数付きファイルパス}]" );
177                                         return;
178                                 }
179                                 //-----------------
180                                 #endregion
181                                 #region " コンバータを使って、フレームを WICビットマップ経由で D2D ビットマップに変換する。"
182                                 //-----------------
183                                 try
184                                 {
185                                         // WIC ビットマップを D2D ビットマップに変換する。
186                                         this.Bitmap?.Dispose();
187                                         this.Bitmap = SharpDX.Direct2D1.Bitmap1.FromWicBitmap(
188                                                 dr.D2DContext1,
189                                                 converter,
190                                                 bitmapProperties1 );
191                                 }
192                                 catch( SharpDX.SharpDXException e )
193                                 {
194                                         Log.ERROR( $"Direct2D1.Bitmap1 への変換に失敗しました。(0x{e.HResult:x8})[{変数付きファイルパス}]" );
195                                         return;
196                                 }
197                                 //-----------------
198                                 #endregion
199
200                                 //Log.Info( $"{Utilities.現在のメソッド名}: 画像を生成しました。[{変数付きファイルパス}]" );
201                         }
202                         finally
203                         {
204                                 converter?.Dispose();
205                                 sourceFrame?.Dispose();
206                                 decoder?.Dispose();
207                         }
208                 }
209         }
210 }