WebP形式画像へ変換して保存する (ImageSharp を利用) - C#

C#でWebP形式画像へ変換して保存するコードを紹介します。
ImageSharp を利用します。

概要

C#で画像をWebP形式に変換して保存します。
画像変換ライブラリとして、SixLabors の ImageSharp を利用します。
メモ
ImageProcessorを利用するコードはこちらの記事を参照してください。

プログラム

Windows Formアプリケーションを作成します。

事前準備:SixLabors.ImageSharp のインストール

NuGetでSixLabors.ImageSharpパッケージをインストールします。
NuGetのWebサイトで、SixLabors.ImageSharpのインストールコマンドを確認し、NuGetパッケージマネージャーコンソールでインストールします。


または、ソリューションエクスプローラーで右クリックし、ポップアップの[ソリューションのNuGetパッケージの管理]をクリックし、 GUIでSixLabors.ImageSharpパッケージをインストールします。



インストールできると、ソリューションエクスプローラーのプロジェクトのノードの[依存関係]の[パッケージ]の子ノードに "SizLabors.ImageSharp"のノードが追加されます。

UI

下図のフォームを作成します。フォームに[Button]を1つ配置します。加えて、OpenFileDialogとSaveFileDialogも配置します。


フォーム編集時にエラーが発生する場合
フォームデザイナフォームを開く際にエラーが発生する場合があります。これは、 Size クラスが System.Drawing.SizeSixLabors.ImageSharp.Size のどちらを指定しているのかあいまいなために発生します。
FormMain.Designer.csのコードでエラーの発生している部分を以下のコードに変更します。
SizeSystem.Drawing.Sizeに変更します。
FormMain.Designer.cs
    private void InitializeComponent()
    {
      SuspendLayout();
      // 
      // Form1
      // 
      AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
      AutoScaleMode = AutoScaleMode.Font;
      ClientSize = new System.Drawing.Size(512, 227);
      Name = "Form1";
      Text = "Form1";
      ResumeLayout(false);
    }

コード

以下のコードを記述します。
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Webp;

namespace WebPConvWindowsForm
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      if (openFileDialog1.ShowDialog() == DialogResult.OK) {
        if (saveFileDialog1.ShowDialog() == DialogResult.OK) {
          SixLabors.ImageSharp.Image img = SixLabors.ImageSharp.Image.Load(openFileDialog1.FileName);
          WebpEncoder we = new WebpEncoder() { FileFormat = WebpFileFormatType.Lossy, Quality = 80 };
          img.SaveAsWebp(saveFileDialog1.FileName, we);
        }
      }
    }
  }
}

解説

ボタンがクリックされると、OpenFileDialogを表示します。変換元の画像ファイルを選択します。 続いてSaveFileDialogが表示されます。WebP形式で保存するファイル名を指定します。
SixLabors.ImageSharp.Image.Load()メソッドを呼び出し、元の画像をSixLabors.ImageSharp.Image オブジェクトに読み込みます。 WebpEncoder を作成し、WebPの保存フォーマットに関する設定をします。今回のコードでは、非可逆圧縮で、品質を80で保存する設定とします。
品質の値は0~100の範囲で指定できます。値が小さいほどサイズは小さくなりますが画質は劣化します。
SixLabors.ImageSharp.Image オブジェクトの SaveAsWebp() メソッドでWebP形式で保存します。第一引数に保存先のファイルパスを与えます。 第二引数には先のコードで作成した、WebpEncoder オブジェクトを与えます。
 if (openFileDialog1.ShowDialog() == DialogResult.OK) {
   if (saveFileDialog1.ShowDialog() == DialogResult.OK) {
     SixLabors.ImageSharp.Image img = SixLabors.ImageSharp.Image.Load(openFileDialog1.FileName);
     WebpEncoder we = new WebpEncoder() { FileFormat = WebpFileFormatType.Lossy, Quality = 80 };
     img.SaveAsWebp(saveFileDialog1.FileName, we);
   }
 }

実行結果

今回、元画像として下図の画像を用意しました。PNG形式の画像です。


プロジェクトを実行します。下図のウィンドウが表示されます。[button1]をクリックします。

開くダイアログが表示されます。用意した画像を選択します。


変換したWebP画像を保存するディレクトリ、画像のファイル名を設定します。


WebP形式で保存できました。


左が元の画像、右側がWebP形式に変換して保存した画像です。元の画像よりサイズが小さくなっていることが確認できます。


WebPに変換した画像です。Webブラウザで表示した状態です。見てわかるほどの品質の劣化はありませんでした。

プログラム:Lossless WebPの変換

可逆圧縮のWebPに変換する場合のコードです。

UI

下図のフォームを作成します。先ほどのプログラムのフォームにボタンを1つ追加しています。

コード

以下のコードを記述します。追加したボタン(button2)のClickイベントを実装します。
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Webp;

namespace WebPConvWindowsForm
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void button2_Click(object sender, EventArgs e)
    {
      if (openFileDialog1.ShowDialog() == DialogResult.OK) {
        if (saveFileDialog1.ShowDialog() == DialogResult.OK) {
          SixLabors.ImageSharp.Image img = SixLabors.ImageSharp.Image.Load(openFileDialog1.FileName);
          WebpEncoder we = new WebpEncoder() { FileFormat = WebpFileFormatType.Lossless, Quality = 80 };
          img.SaveAsWebp(saveFileDialog1.FileName, we);
        }
      }
    }
  }
}

解説

ボタンがクリックされると、OpenFileDialogを表示し、変換元の画像ファイルを選択します。 続いてSaveFileDialogが表示され、WebP形式で保存するファイル名を指定します。
先の例のコードと同様のロジックです。
可逆圧縮(Lossless)の場合は、WebpEncoderオブジェクトのFileFormatプロパティにWebpFileFormatType.Losslessを設定します。 この設定により、非可逆でのWebPファイルの保存となります。 Qualityの値は0~100の範囲で指定できます。値が大きいほど、圧縮処理が最適化されファイルサイズは小さくなりますが、処理時間はかかります。
  WebpEncoder we = new WebpEncoder() { FileFormat = WebpFileFormatType.Lossless, Quality = 80 };

ファイル保存も先の例と同様です。第一引数に保存先のファイルパスを与えます。 第二引数には先のコードで作成した、WebpEncoder オブジェクトを与えます。
  img.SaveAsWebp(saveFileDialog1.FileName, we);

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。[button2]をクリックします。


ファイルを開くダイアログが表示されます。変換元のファイルを選択します。


続いてファイルを名前を付けて保存ダイア路が表示されます。保存ファイル名を設定します。


ファイルが保存されました。


ファイルサイズを比較します。WebPのLosslessファイルがPNG形式のファイルよりもサイズが小さくなっていることが確認できます。


C#のプログラムでWebP形式に変換できました。

プログラム:WebP画像をレスポンスするWebハンドラ

WebP画像をレスポンスするWebハンドラの例です。
ASP.NET Core アプリケーションのプロジェクトを作成します。

事前準備:SixLabors.ImageSharp のインストール

先の例と同様にNuGetでSixLabors.ImageSharpパッケージをインストールします。

コード

以下のコードを記述します。
Program.cs
using Microsoft.AspNetCore.WebUtilities;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Webp;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
  endpoints.MapGet("/", async context =>
  {
    MemoryStream ms = new MemoryStream();
   
    SixLabors.ImageSharp.Image img = SixLabors.ImageSharp.Image.Load("image.png");
    WebpEncoder we = new WebpEncoder() { FileFormat = WebpFileFormatType.Lossy, Quality = 80 };
    img.SaveAsWebp(ms, we);

    ms.Seek(0, SeekOrigin.Begin);
    byte[] imageBytes = ms.ToArray();
    ms.Close();
    await context.Response.Body.WriteAsync(imageBytes);
  });
});

app.Run();

解説

WebP画像を書き出すためのMemoryStreamオブジェクトを作成します。
MemoryStream ms = new MemoryStream();
レスポンスヘッダのContentTypeを指定します。WebP画像を返しますので image/webp を設定します。
    context.Response.ContentType = "image/webp";

SixLabors.ImageSharp.Imageオブジェクトを作成し、PNG形式の画像を読み込みます。 WebpEncoder を作成し、WebP形式でMemoryStreamに保存します。
    SixLabors.ImageSharp.Image img = SixLabors.ImageSharp.Image.Load("image.png");
    WebpEncoder we = new WebpEncoder() { FileFormat = WebpFileFormatType.Lossy, Quality = 80 };
    img.SaveAsWebp(ms, we);

WebP画像のデータをMemoryStreamからbyte配列に変換し、レスポンスとして返します。
    ms.Seek(0, SeekOrigin.Begin);
    byte[] imageBytes = ms.ToArray();
    ms.Close();
    await context.Response.Body.WriteAsync(imageBytes);

画像の準備

画像をプロジェクトのルートディレクトリに追加します。

画像のプロパティの[出力ディレクトリにコピー]の値を"常にコピーする"に変更します。

実行結果

プロジェクトを実行します。Webブラウザが開き、下図の画面が表示されます。 WebP形式の画像が表示できています。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2023-07-30
iPentec all rights reserverd.