グダグダと書く前にまず答えから。
次の Convert
メソッドで System.Windows.Media.Imaging.BitmapSource
クラスのオブジェクトを System.Drawing.Bitmap
クラスのオブジェクトに変換できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
| - | - - | | | | ! - - ! | - | | | | | | ! | - ! | | | | | - ! | | | | | - | | | | | ! | - | | | ! | - | - | ! ! | | ! ! ! |
|
この例では、必ずARGB形式となるように必要に応じてソースのフォーマットを変換しています。
任意のフォーマットで変換したい場合はソースのフォーマットに応じた処理を行う必要があります。
GoogleでWPFの BitmapSource
からGDIの Bitmap
への変換について検索すると、 BmpBitmapEncoder
を用いる方法が多く紹介されています(2011年8月現在)。
この方法は、一旦エンコーダによってBMP形式へ落とし込むことにより、ソースのフォーマットを気にすることなく変換できるのが利点といえます。
しかしこの方法は言ってしまえば一度BMPファイルにしてから読み込み直すのと変わらないため、速度面でのコストが気になります。
また、BMP形式では不透明度を扱えない為、不透明度を保持したい場合は PngBitmapEncoder
等を用いることになり、更に処理時間が掛かることになります。
「フォーマットは固定でも構わないのでより高速に変換したい」という要求がある場合、今回紹介した CopyPixels
メソッドを用いる方法に軍配が上がります。
どれほど速度に差が出るのか、次のようなベンチマークプログラムで実験してみました。
なお、上述の Sample
クラスが定義済みであるものとします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
| - | - - | | | | | | | ! | - - ! | | - ! | - | | | - - | ! ! ! | | ! | - | | | | ! - - ! | | | | | | | - ! | - | ! | - ! | | | | - ! | | | ! | - | | | | | | | ! | | | - - ! | | - | ! | | - ! | | | | - ! - | ! ! | - | | | ! - - ! | - ! | | | | | | | | | | | ! | - | | ! - | | | ! ! ! |
|
このプログラムは、
の各形式の BitmapSource
について、
CopyPixels
メソッドを用いる方法。BmpBitmapEncoder
クラスを用いる方法。PngBitmapEncoder
クラスを用いる方法。の各方法による Bitmap
への変換処理を各100回実行し、その処理時間を出力するものです。
また、ついでにその際生成される Bitmap
をPNG画像ファイルとして保存しています。
このプログラムを私の環境(Windows7 64bit)で実行した結果は次の通りです。
数値の単位はミリ秒です。
Bgra32-CopyPixels : 126.398125 Bgra32-BmpBitmapEncoder : 989.100697 Bgra32-PngBitmapEncoder : 1797.793503 Bgr24-CopyPixels : 227.051113 Bgr24-BmpBitmapEncoder : 986.993156 Bgr24-PngBitmapEncoder : 1504.336953 Indexed8-CopyPixels : 689.379903 Indexed8-BmpBitmapEncoder : 1367.630629 Indexed8-PngBitmapEncoder : 1188.354228
ご覧の通り、元となる BitmapSource
のフォーマットによって比率に差はあるものの、すべてにおいて CopyPixels
メソッドを用いる方法が最も高速になりました。
特にフォーマット変換不要な32ビットBGRA形式においては、 BmpBitmapEncoder
を用いる場合の約8倍、 PngBitmapEncoder
を用いる場合の約15倍高速になりました。
今まで BmpBitmapEncoder
クラスを用いていた方は、検討の余地があるのではないでしょうか。