C#リストビューで画像ファイルのサムネイル表示2

コンピュータ

実行環境構築

プロジェクトの作成

mkdir プロジェクト名
cd プロジェクト名
dotnet new winforms

ソースプログラム

namespace TaskWithThumbnail;

public partial class Form1 : Form
{
    MenuStrip menubar = new MenuStrip();    // メニューバー
    ToolStripMenuItem menuItem_Exec = new ToolStripMenuItem
    {
        Text = "実行",
    };    // 実行

    ListView listView = new ListView
    {
        Dock = DockStyle.Fill,   // クライアント領域全体に広げる
    };    // リストビュー
    ImageList imgList = new ImageList
    {
        ImageSize = new Size(256, 256),    // 画像サイズ256x256
    };    // イメージリスト

    // コンストラクタ
    public Form1()
    {
        InitializeComponent();
        InitControls();
    }

    // コントロールの初期化
    void InitControls()
    {
        // メニュー関連

        menuItem_Exec.Click += menuItem_Exec_Click;
        menubar.Items.Add(menuItem_Exec);
        Controls.Add(menubar);

        // リストビュー関連

        listView.Columns.Add("NAME");    // // カラムの追加
        listView.LargeImageList = imgList;
        Controls.Add(listView);    // フォームにリストビューを登録
    }

    // 正方形画像で読み込み
    static Bitmap LoadSquareImage(string path)
    {
        using var fs = new FileStream(path, FileMode.Open);
        var bmp = new Bitmap(fs);

        // 縦横同じ場合を最初に処理
        if (bmp.Width == bmp.Height)
        {
            return bmp;
        }

        if (bmp.Width > bmp.Height)
        {
            // 幅基準
            var result = new Bitmap(bmp.Width, bmp.Width);

            using (var g = Graphics.FromImage(result))
            {
                int y = (int)((result.Height - bmp.Height) / 2);
                Rectangle dstRect = new Rectangle(0, y, bmp.Width, bmp.Height);
                Rectangle srcRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                g.DrawImage(bmp, dstRect, srcRect, GraphicsUnit.Pixel);
            }
            bmp.Dispose();
            return result;
        }
        else
        {
            // 高さ基準
            var result = new Bitmap(bmp.Height, bmp.Height);

            using (var g = Graphics.FromImage(result))
            {
                int x = (int)((result.Width - bmp.Width) / 2);
                Rectangle dstRect = new Rectangle(x, 0, bmp.Width, bmp.Height);
                Rectangle srcRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                g.DrawImage(bmp, dstRect, srcRect, GraphicsUnit.Pixel);
            }
            bmp.Dispose();
            return result;
        }

    }
    // 実行ボタンのクリック処理
    async void menuItem_Exec_Click(object? s, EventArgs e)
    {
        string path = @"c:\users\karet\OneDrive\Pictures";    // 画像ファイルが保存されたディレクトリ

        // リストビューをクリア
        listView.Items.Clear();
        imgList.Images.Clear();

        Image[] b = {};
        ListViewItem[] a = {};

        Task<int> task = Task.Run(() =>
        {

            var dirInfo =  new DirectoryInfo(path);
            var i = 0;

            // LINQで書き直し
            var d = dirInfo.EnumerateFiles("*.png");
            b = d.Select(x => LoadSquareImage(x.FullName))
                .ToArray();
            a = d.Select(x => new ListViewItem(x.Name, i++))
                .ToArray();
            
            return i;
        });
        int result = await task;
        if (result > 0)
        {
            imgList.Images.AddRange(b);
            listView.Items.AddRange(a);
        }
    }
}

ビルド

dotnet build -c Release

使い方

PS>プロジェクト名.exe

メニュー→実行

縦横の比率が維持されています。

前回の記事の画像

縦横比を無視して引き延ばされています。

問題点

ファイル数・サイズが少ない場合は一瞬で表示されますが、多くなってくると待ちが発生します。

コメント