WPFのXAMLでImageコントロールで画像を表示する。

コンピュータ
WPFではXAMLでImageコントロールを使うと簡単に画像を表示することが出来ます。

ローカルファイルを表示

<Window x:Class="WPFImageSample.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:WPFImageSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Image 
            Source = "C:\Users\karet\Pictures\20230614\202304301753.jpg"
        >
        </Image>
    </Grid>
</Window>


Stretchを指定しない場合の規定値はUniformとなり、縦横比が保持された状態で拡大縮小されます。

画像をオリジナルサイズで表示

<Image 
            Source = "C:\Users\karet\Pictures\20230614\202304301753.jpg"
            Stretch = "None"
        >



StretchNoneをセットすると画像のオリジナルサイズで表示されます。

スクロール

画像をオリジナルサイズで表示した例では画像のサイズがImageコントロールのサイズより大きいため画像の一部のみが表示されています。
ScrollViewerを使って画像をスクロールすることではみ出した部分を表示することが出来ます。

        <ScrollViewer
            HorizontalScrollBarVisibility="Auto"
            VerticalScrollBarVisibility="Auto">
            <Image
                Source = "C:\Users\karet\Pictures\20230614\202304301753.jpg"
                Stretch = "None"
            >
            </Image>
        </ScrollViewer>


HorizontalScrollBarVisibilityの規定値はHidden
VerticalScrollBarVisibilityの規定値はVisibleですので、デフォルトでは縦方向のみスクロールになります。
autoに設定することで自動的にスクロールバーが表示されるようしています。

ドラッグアンドドロップで画像表示

ファイル名:MainWindow.xaml

<Window x:Class="ImgDropView.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:ImgDropView"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel
            x:Name = "StackPanel1"
            Background = "Black"
            AllowDrop = "True">
            <Image
                x:Name="Image1"
                Stretch="Uniform" />
        </StackPanel>
    </Grid>
</Window>


ファイル名:MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;

namespace ImgDropView
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            StackPanel1.SizeChanged += (s, e) =>
            {
                Image1.Height = (int)e.NewSize.Height;
                Image1.Width = (int)e.NewSize.Width;
            };

            StackPanel1.Drop += async (s, e) =>
            {
                if (e.Data is null) return;
                var files = e.Data.GetData(DataFormats.FileDrop) as string[] ?? new string[]{};
                if (!files.Any()) return;
                string file = files[0];

                var bi = await Task.Run(()=>
                {
                    using var fs = new FileStream(file, FileMode.Open, FileAccess.Read);
                    BitmapImage bi = new();
                    bi.BeginInit();
                    bi.StreamSource = fs;
                    bi.CacheOption = BitmapCacheOption.OnLoad;
                    bi.CreateOptions = BitmapCreateOptions.None;
                    bi.EndInit();
                    bi.Freeze();
                    return bi;
                });
                Image1.Source = bi;

            };

        }
    }
}

ドラッグアンドドロップとコピーアンドペーストと拡大縮小

ファイル名:MainWindow.xaml

<Window x:Class="WPFImageSample.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:WPFImageSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ScrollViewer
            x:Name = "ScrollViewer1"
            HorizontalScrollBarVisibility="Auto"
            VerticalScrollBarVisibility="Auto">
            <Canvas
                x:Name = "Canvas1"
                Background = "LightGray"
                AllowDrop = "True">
                <Image
                    x:Name = "Image1"
                    Stretch = "UniformToFill">
                </Image>
            </Canvas>
        </ScrollViewer>
    </Grid>
</Window>

ファイル名:MainWindow.xaml.cs

using System.Windows;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using System.Windows.Input;

namespace WPFImageSample;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Image1.SizeChanged += (s, e) =>
        {
            // Canvas.SizeをImage.Sizeに合わせる
            Canvas1.Width = e.NewSize.Width;
            Canvas1.Height = e.NewSize.Height;
        };

        Canvas1.Drop += async (s, e) =>
        {
            // ドラッグアンドドロップ
            if (e.Data == null) return;
            var files = e.Data.GetData(DataFormats.FileDrop) as string[];
            if (files is null) return;
            await using var fs = new FileStream(files[0], FileMode.Open, FileAccess.Read);
            BitmapImage bi = await Task.Run(()=>
            {
                BitmapImage bi = new();
                bi.BeginInit();
                bi.StreamSource = fs;
                bi.CacheOption = BitmapCacheOption.OnLoad;
                bi.CreateOptions = BitmapCreateOptions.None;
                bi.EndInit();
                bi.Freeze();
                return bi;
            });
            Image1.Source = bi;
            Image1.Height = bi.PixelHeight;
            Image1.Width = bi.PixelWidth;
        };

        Canvas1.PreviewMouseWheel += (s, e) =>
        {
            // 拡大・縮小
            e.Handled = true;

            double h = double.IsNaN(Image1.Height) ? Image1.ActualHeight : Image1.Height;

            double scale = h / Image1.ActualHeight;

            scale = (0 < e.Delta) ? scale + 0.2 : scale - 0.2;
            if (scale < 0.4) scale = 0.4;
            if (scale > 4.0) scale = 4.0;

            Image1.Height = Image1.ActualHeight * scale;
            Image1.Width = Image1.ActualWidth * scale;

            Point sp = e.GetPosition(ScrollViewer1);

            double xOffset = ScrollViewer1.HorizontalOffset;
            double yOffset = ScrollViewer1.VerticalOffset ;

            xOffset = (xOffset + sp.X) * scale - sp.X;
            yOffset = (yOffset + sp.Y) * scale - sp.Y;

            ScrollViewer1.ScrollToHorizontalOffset(xOffset);
            ScrollViewer1.ScrollToVerticalOffset(yOffset);
        };
        this.KeyDown += (s, e) =>
        {
            if (e.Key == Key.C && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                // "Ctrl+C" コピー
                var encoder = new PngBitmapEncoder();
                var bitmapSource = Image1.Source as BitmapImage;
                if (bitmapSource is null) return;
                var frame = BitmapFrame.Create(bitmapSource);
                encoder.Frames.Add(frame);
                using var mem = new MemoryStream();
                encoder.Save(mem);
                Clipboard.SetData("PNG", mem);
            }
            else if (e.Key == Key.V && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                // "Ctrl+V" 貼り付け
                using var ms = Clipboard.GetData("PNG") as System.IO.MemoryStream;
                if (ms is null) return;
                
                var bi = new BitmapImage();
                bi.BeginInit();
                bi.StreamSource = ms;
                bi.CacheOption = BitmapCacheOption.OnLoad;
                bi.CreateOptions = BitmapCreateOptions.None;
                bi.EndInit();
                bi.Freeze();

                Image1.Source = bi;
                Image1.Height = bi.PixelHeight;
                Image1.Width = bi.PixelWidth;
            }
        };
    }
} // MainWindow

コメント