【Wpf】画像ファイルの読み込み方法を何パターンか紹介(ビルドアクションについても少し解説)

.Net FrameWork

この記事は、WPF(C#)で画像ファイルを読み込む方法です。

WPFの場合は、以下の方法があります。
・xamlから読み込む方法
・C#ソースコードから読み込む方法


今回はそれぞれの方法を確認していきます。

さっぞく画像を読み込む方法を順番に確認していきます。

絶対パスから画像を読み込む

まずは絶対パスで画像を読み込む方法からです。

絶対パスとは - IT用語辞典
絶対パスとは、ファイルなどの所在を書き表すパス(path)の表記法の一つで、階層構造の頂点(最上位階層)からの位置関係を記述する方式。現在位置とは無関係に、ドライブやシステムの最上位ディレクトリ(ルートディレクトリ、ルートフォルダ)から目的のディレクトリ(フォルダ)やファイルまでの道筋を省略なくすべて記述する方法で、途...

最初に利用する画像はどれでも良いので、その画像を任意の場所にセットします。

$C:\Sample\image1.png

ここではCドライブのSampleフォルダにimage1.pngをセットします。

今からこの画像を読み込んでいきます。
各々Wpfのプロジェクトファイルを作成してください。

XAMLから画像ファイルを読み込む方法

xamlファイル

<Window x:Class="SetImageSample.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:SetImageSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <!--ここから-->
        <Image Margin="100" x:Name="setImage">
            <Image.Source>
                <!--読み込みたい画像のパス情報をセット-->
                <BitmapImage UriSource="C:\Sample\image1.png"/>
            </Image.Source>
        </Image>
        <!--ここまで-->
    </Grid>
</Window>
Point

※主観的な意見ですが、プログラムを書かなくても良いので、
 後述するC#で記述する方法よりおすすめです。

C#から画像ファイルを読み込む方法

<Window x:Class="SetImageSample.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:SetImageSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <!--この後、ここにC#から画像を読み込んでセット予定-->
        <Image Margin="100" x:Name="setImage"/>
    </Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Media.Imaging;

namespace SetImageSample
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // 画像ファイルパス情報
            string imgFilePath = @"C:\Sample\image1.png";
            //画像ファイルを読み込んでセットする.
            setImage.Source = new BitmapImage(new Uri(imgFilePath));           
        }
    }
}

相対パスから画像を読み込む

次は、相対ファイルパスで画像を読み込む方法です。

相対パスとは - IT用語辞典
相対パスとは、ファイルなどの所在を書き表すパス(path)の表記法の一つで、現在位置からの相対的な位置関係を記述する方式。起点となる位置から目的の位置までの道筋にある要素を順に並べて記述する。システムが現在操作対象としているカレントディレクトリ(カレントフォルダ)を起点に、指し示したいディレクトリやファイルの相対位置を...

ここでも同様に画像ファイルを用意するところから。
今回は以下の画像のようにプロジェクト内に「Image」フォルダを作成してその中に任意の画像をセット。

次も同じようにそれぞれXAMLから読み込む方法とC#から読み込む方法それぞれ確認します。

xamlから画像ファイルを読み込む方法

基本的には先程確認した絶対パスの場合と同じです。
ファイルのパス情報を変更するだけ

「C:\sample\image1.png」-> 「.\Image\image1.png

<Window x:Class="SetImageSample.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:SetImageSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <!--ここから-->
        <Image Margin="100" x:Name="setImage">
            <Image.Source>
                <!--変更点:ファイルパスの先頭に「.」がついてる-->
                <BitmapImage UriSource=".\Image\image1.png"/>
            </Image.Source>
        </Image>
        <!--ここまで-->
    </Grid>
</Window>

※注意:ファイルパスの先頭「.\」がカレントディレクトリを指してます。
だからあとは続きに、xamlファイルから見て画像ファイルはどこにあるのかいうのを記述してあげれば解決です。

C#から画像ファイルを読み込む方法

こちらも基本的には絶対パスの画像を読み込む場合と同じです。
new Uri(“○○○.png”)の中身を絶対パスから相対パスへ変更してやればOK

<Window x:Class="SetImageSample.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:SetImageSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <!--この後、ここにC#から画像を読み込んでセット予定-->
        <Image Margin="100" x:Name="setImage"/>
    </Grid>
</Window>
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // 画像ファイルパス情報
            string imgFilePath = @".\Image\image1.png";
            // 画像ファイルを読み込んでセットする.
            setImage.Source = new BitmapImage(new Uri(imgFilePath));
        }
    }

例外発生!?

上記のプログラムを実行すると以下の例外が発生します。

例外が発生した原因は、new Uri()内のファイルパス情報が正しくないからです。
xamlで同様のファイルパス利用した時は正常に動作したのに、今回は動作しませんでした。
違いは何でしょう?

重要Point①

原因は、画像のファイルパスを参照するときの基準位置(カレントディレクトリ)が違います
C#で記述したファイルパスを参照するときは、ビルド後に生成される「XXX.exe」実行ファイルが基準となります。

そのため、実行ファイルから上記の画像ファイルパスを参照しようとしても画像ファイルが見つけられないので例外が発生します。
解決方法は次項です。

解決方法は「ビルドアクション」をチェック

次は解決方法です。
例外が発生した原因は文字列で指定したファイルパスに画像ファイルが存在しないのが原因でした。
解決するためには、指定するファイルパスに画像ファイルを用意してやれば解決できます。
そのために画像ファイルのプロパティを変更します。

変更箇所①

ビルドアクションの「リソース」⇒「コンテンツ」に変更

変更箇所②

出力ディレクトリにコピーの「コピーしない
⇒「常にコピーする」か「新しい場合にコピーする」に変更

これでビルドして実行してあげると実行ファイルと同階層にプロパティを変更した画像ファイルをコピーしてくれるので実行ファイルからファイルパスを参照しても問題なく画像ファイルを読み込むことが可能です。

画像ファイルのプロパティについてもう少し

先ほど変更したプロパティのビルドアクションについてもう少し確認。
これを「リソース」から「コンテンツ」に変更しました。
それにより何が変わったのかについてです。

リソースの場合は、画像ファイルはビルド時に生成されるobjフォルダ内にあるxxx.g.resourceファイルに直接埋め込まれます

ファイルのビルド ファイル - Visual Studio (Windows)
Visual Studio プロジェクトのすべてのファイルにビルド アクションが含まれ、そのビルド アクションによって、プロジェクトのコンパイル時にファイルに行われる処理が制御されることについて説明します。

コンテンツの場合は、実行ファイルが生成されるのと同じ階層に画像ファイルをコピーしてくれます。
「出力ディレクトリ」を「常にコピー」か「変更時のみコピー」に変更する必要があります。
 実行ファイルが生成された階層と同じ階層を確認すれば、今回の場合だと「Image」フォルダが生成されて画像ファイルもその中にあるはずです。

ビルドアクション変更によるメリット

メリットは、画像ファイルの変更をファイルを置換することで変更可能です。
方法は、上記のように変更後にコピーされた画像ファイルを置換するだけです。

以上のことからビルドアクションを「コンテンツ」に変更することによってxxx.g.resourceファイルに埋め込まれずに実行ファイル生成される階層に画像ファイルとして生成されるのでそちらを差し替えてあげることで後々、リビルドなどしなくても差し替えが可能になります。

以上のように、後々画像を利用する場合に差し替え可能しておくことで便利な場合もあります。
例えば、日本語表示と英語表記で変更したい場合なども有効的に利用できそうです。
\(^o^)/

コメント

タイトルとURLをコピーしました