C#のMagick.Net (ImageMagick)の使い方

C# C#

C#のMagick.Net (ImageMagick)の使い方

C#(Azure Function)でImageMagickを使ったので、使い方や発生したエラー・サンプルコードを記載しています。
「画像を縮小した後に拡大して、画像の容量を減らす」といった実装を今回行いました。

環境はmacのVisual Stadio for Macを利用しています。
(.Net Core3.0を使っています)

今回の実装サンプルはgithubのこちらに置いています。

Magick.Netのインストール

NugetからMagick.Netを検索して、インストールします。
Q16とQ8の違いは公式ドキュメントにあるように、Q16は16bitのことで、こちらの方が高画質な画像を扱えるようです。

Q8の方が推奨になっているみたいです。今回はQ16を入れてみました。
環境に合わせてx64またはx86を選ぶ必要があるようです。

画像を縮小する

MemoryStream(ms)に画像を読み込んだら下記のように処理できます。

var settings = new MagickReadSettings();

ms.Position = 0;
var image = new MagickImage(ms, settings);

// オリジナル画像の幅を保持
int originalImageWith = image.Width;

// 画像を縮小する
var reducedImageMemory = new MemoryStream();
image.Resize(originalImageWith / 2, 0);
image.Write(reducedImageMemory);

コードの説明

MagickReadSettingsクラスを使用して読み込み時の設定するためのインスタンスを作成します。
次にMemoryStream(ms)のPositionに0を設定します。

MagickImageクラスを使用してMagick.Netで処理するための画像のインスタンス(image)を作成します。
1番目の引数が画像のMemoryStreamで2番目の引数がMagickReadSettingsです。

reducedImageMemoryという名前で新しくMemoryStreamを作成しています。
そして、MagickImageのResizeメソッドを使って、画像のリサイズをしています。

image.Resize(originalImageWith / 2, 0);

上記の記述でオリジナルの画像の半分に設定しています。(ここの数値をいじると画像のサイズを調整できます。)
その後に新しく作ったMemoryStream(reducedImageMemory)にイメージを書き込んでいます。

この状態で出力すると、半分になった画像が取得できます。

画像を縮小したあとに拡大する

画像の容量を減らしたかったので、「画像を縮小したあとに拡大する」と言うことを行いました。
解像度のプロパティ(Density)を触ってみましたが変わらず…

// 元のサイズに戻す
reducedImageMemory.Position = 0;
var outputImageMemory = new MemoryStream();

settings.Width = originalImageWith;
var resizeImageMemory = new MagickImage(reducedImageMemory, settings);
resizeImageMemory.Strip();
resizeImageMemory.Resize(originalImageWith, 0);
resizeImageMemory.Write(outputImageMemory);

var bytes = Convert.FromBase64String(Convert.ToBase64String(outputImageMemory.ToArray()));
return new FileContentResult(bytes, "image/png");

コードの説明

上記のコードの続きになります。
MemoryStream(reducedImageMemory)には半分になった画像が格納されています。

最初にPositionを0にして、出力用のMemoryStream(outputImageMemory)を用意します。
reducedImageMemory(半分にした画像情報)を使って、MagickImageクラスをインスタンス化します。

Stripメソッドを使って、画像情報を削除しています。
その後にResizeメソッドで元のサイズに戻す設定をしています。

設定後、outputImageMemoryに書き込んでいます。
最後に画像をレスポンスとして返して、処理終了です。

動作確認

対象の画像はこれです。サイズが3.5Mあります。

Postmanでリクエストに画像を選んで送信します。

画像を返すようにしているので、レスポンスはこんな感じで表示されます。
返ってきたレスポンスの画像はサイズが減っていますね。
(※サイズの減りを増やすために10分の1に設定しました。)

レスポンスを保存すると、こんな感じで減っていることが確認できます。

OK… 👌
サイズが減って、同じ大きさの画像が取得できました。
縮小して拡大しているので、もちろん画質は荒くなります。

dylibを移動しないとエラーになる

.NET Core2.2でライブラリを使った処理を書いて、普通に実行すると下記のエラーになりました。

System.Private.CoreLib: Exception while executing function: ImageResize. Magick.NET-Q16-AnyCPU: The type initializer for 'NativeMagickSettings' threw an exception. Magick.NET-Q16-AnyCPU: Unable to load shared library 'Magick.Native-Q16-x64.dll' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: dlopen(libMagick.Native-Q16-x64.dll, 1): image not found.

回避策としては下記になります。
dylibファイルがbin/Debug/netcoreappX.X/bin/runtimes配下のosxという、いかにもmacで使用するライブラリだと思われるディレクトリできています。
Magick.Native-Q8-x64.dll.dylibというdylibファイルがあるので、それをbin/Debug/netcoreappX.X/配下に移動します。

同じ操作を行って、windows端末で確認するとエラーになりませんでした。
なぜ…🤔

コメント

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