WPFヘルパー:ImageHelper.cs – BitmapSource関連「画像ファイル読み込み・DPI96化・拡張子判定」

コンピュータ

Helpers/ImageHelper.cs

using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Maywork.WPF.Helpers;

public static partial class ImageHelper
{
    // 画像ファイルを読み込むメソッド
    public static BitmapSource Load(string path)
    {
        using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);

        var decoder = BitmapDecoder.Create(
            stream,
            BitmapCreateOptions.PreservePixelFormat,
            BitmapCacheOption.OnLoad);

        var frame = decoder.Frames[0];
        frame.Freeze();

        return frame;
    }

    // 96DPIに変換する
    public static BitmapSource To96Dpi(BitmapSource source)
    {
        if (Math.Abs(source.DpiX - 96) < 0.01 &&
            Math.Abs(source.DpiY - 96) < 0.01)
        {
            return ConvertToBgra32(source);
        }

        var rtb = new RenderTargetBitmap(
            source.PixelWidth,
            source.PixelHeight,
            96,
            96,
            PixelFormats.Pbgra32);   // ← ここはPbgra32固定

        var dv = new DrawingVisual();
        using (var dc = dv.RenderOpen())
        {
            dc.DrawImage(source,
                new Rect(0, 0, source.PixelWidth, source.PixelHeight));
        }

        rtb.Render(dv);
        rtb.Freeze();

        return ConvertToBgra32(rtb);   // ← 後からBgra32へ変換
    }
    private static BitmapSource ConvertToBgra32(BitmapSource source)
    {
        if (source.Format == PixelFormats.Bgra32)
            return source;

        var converted = new FormatConvertedBitmap(
            source,
            PixelFormats.Bgra32,
            null,
            0);

        converted.Freeze();
        return converted;
    }

    // Imageコントロール対応拡張子判定
    private static readonly HashSet<string> _supportedExtensions =
        new(StringComparer.OrdinalIgnoreCase)
        {
            ".jpg",
            ".jpeg",
            ".png",
            ".bmp",
            ".gif",
            ".tif",
            ".tiff",
            ".webp"
        };

    /// <summary>
    /// 画像として扱う拡張子か判定する
    /// </summary>
    public static bool IsSupportedImage(string path)
    {
        if (string.IsNullOrWhiteSpace(path))
            return false;

        var ext = Path.GetExtension(path);

        if (string.IsNullOrEmpty(ext))
            return false;

        return _supportedExtensions.Contains(ext);
    }
    // ヒストグラム生成
    public static BitmapSource CreateHistogram(BitmapSource source)
    {
		int width = source.PixelWidth;
		int height = source.PixelHeight;

		int stride = width * 4;
		byte[] pixels = new byte[stride * height];
		source.CopyPixels(pixels, stride, 0);

		int[] hist = new int[256];

		for (int i = 0; i < pixels.Length; i += 4)
		{
			byte b = pixels[i];
			byte g = pixels[i + 1];
			byte r = pixels[i + 2];

			// Rec.709 輝度
			int y = (int)(0.2126 * r + 0.7152 * g + 0.0722 * b);

			hist[y]++;
		}

		int max = hist.Max();

		int histHeight = 200;
		int histWidth = 512;
		int barWidth = 2;

		var wb = new WriteableBitmap(
			histWidth, histHeight, 96, 96,
			PixelFormats.Bgra32, null);

		byte[] histPixels = new byte[histWidth * histHeight * 4];

		// 背景黒
		for (int i = 0; i < histPixels.Length; i += 4)
			histPixels[i + 3] = 255;

		for (int level = 0; level < 256; level++)
		{
			int xStart = level * barWidth;

			int value = hist[level] * histHeight / max;

			for (int y = 0; y < value; y++)
			{
				for (int w = 0; w < barWidth; w++)
				{
					int index =
						((histHeight - 1 - y) * histWidth + xStart + w) * 4;

					// 白で描画
					histPixels[index + 0] = 255; // B
					histPixels[index + 1] = 255; // G
					histPixels[index + 2] = 255; // R
					histPixels[index + 3] = 255;
				}
			}
		}

		wb.WritePixels(
			new Int32Rect(0, 0, histWidth, histHeight),
			histPixels,
			histWidth * 4,
			0);

		return wb;
    }
}

/*
 // 使用例

LoadCommand = new RelayCommand(async _ =>
{
    var path = @"C:\temp\test.jpg";

    if (!ImageHelper.IsSupportedImage(path))
        return;

    var bmp = await Task.Run(() =>
    {
        var img = ImageHelper.Load(path);
        return ImageHelper.To96Dpi(img);
    });

    Image = bmp;
});
 */
Download

コメント