画像をアプリに埋め込んでアプリで利用するまでの手順メモ
dobon.net
最初はこの方法で試してみたけど、WPF+.NET Coreっていう違いのためかうまくできなくて
dobon.net
ここと
smdn.jp
ここを参考にしてできた
でも全く同じじゃなくて微妙に違うところもあったのでメモ
環境
- Visual Studio Community 2019
- .NET Core 3.1
- WPF
埋め込む画像
ファイル名は「grayScale.bmp」
新しくプロジェクト作成したところ
名前は「画像の埋め込みと取得」にした、namespaceもこれになる、今回は普段気にしないnamespaceが重要
画像ファイル埋め込み
ソリューションエクスプローラーのアプリの名前を右クリック→追加→既存の項目
または
メニューのプロジェクト→既存の項目の追加から
画像ファイルの選択
grayScale.bmpを選択して追加
ソリューションエクスプローラーで確認できる
ビルドアクションの変更
追加したファイル名の右クリックメニューからプロパティを開いて
初期状態ではビルドアクションが「なし」になっているので、ドロップダウンメニューから
「埋め込みリソース」を選択
ビルドアクションが埋め込みリソースになった、これで埋め込みは完了
取り出して表示
MyImageという名前をつけたImage要素に画像を表示する場合
string path = "画像の埋め込みと取得.grayScale.bmp"; var assembly = System.Reflection.Assembly.GetExecutingAssembly(); using (var stream = assembly.GetManifestResourceStream(path)) { if (stream != null) { MyImage.Source = BitmapFrame.Create(stream); } }
ファイルを指定するパスはnamespaceの後ろにピリオドをつけて、その後にファイル名にする
ファイル名はgrayScale.bmpで、namespaceは
画像の埋め込みと取得
なのでパスは
"画像の埋め込みと取得.grayScale.bmp"になる
あとはSystem.Reflection.Assemblyクラスでパスを指定するとStreamが得られるので、これをBitmapFrameのCreateに渡せばBitmapSourceが得られる
埋め込んだ画像を取り出して表示したところ
できた
階層(フォルダ)をつけて埋め込む
埋め込む画像は
ファイル名は「HSVRectHue000.png」
これを
この状態にする
- 画像の埋め込みと取得
- Myフォルダー
- HSVRectHue000.png
- Myフォルダー
フォルダの追加
ファイルを追加した時とほとんど同じ、追加の項目から新しいフォルダーってのがある
フォルダの名前は「Myフォルダー」にしたところ
フォルダの右クリックメニューから
で
フォルダの中に入った
これもビルドアクションを、埋め込みリソースに変更したら埋め込み完了
取り出し
MyImageという名前をつけたImage要素に画像を表示する場合
string path = "画像の埋め込みと取得.Myフォルダー.HSVRectHue000.png"; var assembly = System.Reflection.Assembly.GetExecutingAssembly(); using (var stream = assembly.GetManifestResourceStream(path)) { if (stream != null) { MyImage.Source = BitmapFrame.Create(stream); } }
フォルダなしの時と違うのはパスだけ
- 画像の埋め込みと取得
- Myフォルダー
- HSVRectHue000.png
- HSVRectHue000.png
- Myフォルダー
これを順番につなげて、つなげる場所にはピリオドをいれて
画像の埋め込みと取得.Myフォルダー.HSVRectHue000.png
これがパスになる
Button2のクリックイベントで実行してみる
表示された
コード
MainWindow.xaml
<Window x:Class="画像の埋め込みと取得.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:画像の埋め込みと取得" mc:Ignorable="d" Title="MainWindow" Height="300" Width="500"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="150"/> </Grid.ColumnDefinitions> <Grid> <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <Image x:Name="MyImage" Stretch="None" UseLayoutRounding="True"/> </ScrollViewer> </Grid> <StackPanel Grid.Column="1"> <Button x:Name="Button1" Content="button1" Click="Button1_Click"/> <Button x:Name="Button2" Content="button2" Click="Button2_Click"/> <!--<Button x:Name="Button3" Content="button3" Click="Button3_Click"/>--> </StackPanel> </Grid> </Window>
MainWindow.xaml.cs
using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; namespace 画像の埋め込みと取得 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button1_Click(object sender, RoutedEventArgs e) { string path = "画像の埋め込みと取得.grayScale.bmp"; var assembly = System.Reflection.Assembly.GetExecutingAssembly(); using (var stream = assembly.GetManifestResourceStream(path)) { if (stream != null) { MyImage.Source = BitmapFrame.Create(stream); } } } private void Button2_Click(object sender, RoutedEventArgs e) { string path = "画像の埋め込みと取得.Myフォルダー.HSVRectHue000.png"; var assembly = System.Reflection.Assembly.GetExecutingAssembly(); using (var stream = assembly.GetManifestResourceStream(path)) { if (stream != null) { MyImage.Source = BitmapFrame.Create(stream); } } } //未使用 private void Button3_Click(object sender, RoutedEventArgs e) { var bmp = Properties.Resources.HSVRectH90; MyImage.Source = BitmapSource.Create( 256, 256, 96, 96, PixelFormats.Bgra32, null, bmp, 256 * 4); } } }
動作を確認
gogowaten.hatenablog.com
このときの方法でアプリを発行してできたexeファイルだけを、別のフォルダにコピーして実行してみる。アプリに埋め込まれていれば、どこに移動したりコピーしたりしても表示できるはず
Dドライブのブログ用フォルダにコピーして実行
期待通り!
ファイル名:画像の埋め込みと取得.zip
失敗例
埋め込もうとした画像ファイルはこれ
256x256ピクセルのグラデーション画像
アプリのプロパティ画面のリソースの項目、ここで追加した画像ファイルはうまく取得できなかった、その手順
プロパティ画面の表示
ソリューションエクスプローラーのアプリの右クリックメニューからプロパティを選択する
または
メニューのプロジェクト→プロパティを選択
これで
アプリのプロパティ画面になるので、リソースを選択
ここをクリックしてくださいってあるからクリック
こうなって
リソースの追加→既存のファイルの追加
画像ファイルを選択して
画像が追加された
ソリューションエクスプローラーで確認してみると、アプリの下にResourcesというフォルダができていて、その中にファイルが入った状態になっていた
これも同じようにビルドアクションを埋め込みリソースに変更
ここで一旦ビルド
Properties.Resources.まで打つと、入力候補にファイル名が出てくるので、これを選択するんだけど、型がbyte[]になっている。画像ファイルだからBitmapSourceとかになっていればいいんだけどねえ。これでどんなのが得られるのか実行してみたら
なんか違う、要素の数が12360しかない。元の画像サイズは256x256ピクセルのカラー画像だから、24bitカラーだとしても25625624/8=196608byte、32bitカラーなら25625632/8=262144だから全然足りない。中に入っている値も画像の左上は黒色(RGB=0,0,0)だから0が並んだ後に1,2,3...って並ぶはずだけどぜんぜん違う。ってことでうまく取得できない。
でもVisual Studio上では普通に開くことができる?
ソリューションエクスプローラーのファイル名の右クリックメニューに開くってのがあるから開いてみると
普通に開くことができている?よくわからん
関連記事
次回のWPF記事は翌日
gogowaten.hatenablog.com
今回の画像埋め込み使ってみた
前回のWPF記事は4日前