基本的にMagick.NETを呼んでいけばOK(気づいたPowerShell固有の罠は以下に書いておく)。本格的に処理するのであればC#でコード書いたほうがいいと思うけど、そこまででもないワンタイムバッチ処理にどうぞ。ただし「Verb-Noun -Arg abc」styleでない、.NETクラス直呼び出しの「なんちゃってPowerShell」なので、がっかりされる前に宣言しておく。コンソールで打って問題ない量だと思うけど。
なお動かしてる環境は、PowerShell v4 / x64。
準備
インストール
適当なフォルダを作り、NuGetでMagick.NETのx64 or x86を環境にあわせてもってくる。PS C:\> mkdir c:\opt\magick PS C:\> cd c:\opt\magick PS C:\opt\magick> Invoke-WebRequest https://nuget.org/nuget.exe -OutFile nuget.exe PS C:\opt\magick> .\nuget install Magick.NET-Q16-x64NuGet的にはAnyCPUがあるので、何も考えずにAnyCPUを選びたくなるところではあるが、それはNG。というのも、AnyCPU版はx86とx64のDLLをEmbedded Resourceでかかえる形になっていて、必要に応じてロードしているっぽいのだが、これがAdd-Typeでうまくロードできない。x64やx86はプラットフォーム依存DLLがそのまま置いてあるのでOK。
アセンブリのロード
Add-Typeするだけ。これはさすがにスクリプト化しておいたほうが便利かもね。PS C:\opt\magick> Add-Type -Path .\Magick.NET-*\lib\net40-client\Magick.NET-x64.dll
イメージの読み書き
イメージの読み込み
とにかくここから始まる。これはMagickImageインスタンスを作ればOK。PS c:\temp> $image = New-Object ImageMagick.MagickImage c:\temp\sample.jpgただし、ワーキングディレクトリはPowerShellのものではないので、フルパスで指定するのが無難。クラス名はNew-O[TAB] MagickI[TAB]で補完できるのでおすすめ。
イメージの書き込み
後述の加工作業を行ってから、.Write(path)で書く。PS C:\temp> $image.Write('c:\temp\sample-out.jpg')
基本的に「New-Object」「何かして」「Write」の組み合わせ。
フォーマット指示が必要な場合、Writeの前に入れる。
PS C:\temp> $image.Format = 'png' PS C:\temp> $image.Write('c:\temp\sample-out.png')とか、
PS C:\temp> $image.Format = 'jpeg' PS C:\temp> $image.Quality = 99 PS C:\temp> $image.Write('c:\temp\sample-out-q99.jpg')とか。
あとは
PS c:\temp> $image.Dispose()で後片付け。インタラクティブ操作時はpowershellごと消してもいいと思うけど、ループ時とかは注意。
情報の表示
属性の表示
$imageと打てば、それだけで情報がでてくる。Width, Heightなど。これだけでもわりと便利。ただ、計算するプロパティが含まれているせいか、全部出すと重いのでループするのはおすすめしない。表示はこんな感じ(全部ではない):EXIF情報の表示
$image.GetExifProfile().Values でOK。PS C:\temp> $image.GetExifProfile().Values DataType IsArray Tag Value -------- ------- --- ----- Ascii False ImageDescription Ascii False Make SONY Ascii False Model NEX-6 Short False Orientation 1 Rational False XResolution 350 Rational False YResolution 350 Short False ResolutionUnit 2 Ascii False Software NEX-6 v1.01 Ascii False DateTime 2015:05:24 10:46:23 Short False YCbCrPositioning 2 Undefined True Unknown {80, 114, 105, 110...} Rational False ExposureTime 0.01 Rational False FNumber 13 Short False ExposureProgram 2 Short False ISOSpeedRatings 100 (以下略) PS C:\temp> $image.GetExifProfile().Values.Where({$_.Tag -eq 'FocalLengthIn35mmFilm'}).Value 24
1ファイル系の処理
1ファイルに対する処理をこの画像を使って行っていく。回転(変換と保存)
回転はRotate()。PS c:\temp> $image = New-Object ImageMagick.MagickImage c:\temp\sample.jpg PS C:\temp> $image.Rotate(90) PS C:\temp> $image.Write('c:\temp\sample-out.jpg')
(多分)EXIFにしたがって回転してくれるAutoOrient()ってのもある。便利ね。
切り出し
切り出しはCrop()。Gravityはどこからひっぱってくるかの指示。PS c:\temp> $image = New-Object ImageMagick.MagickImage c:\temp\sample.jpg PS c:\temp> $image.Crop(200, 200, [ImageMagick.Gravity]::Center) PS C:\temp> $image.Write('c:\temp\sample-out.jpg')
リサイズ
Resize()かResample()かScale()かThumbnail()。この使い分けは難しいのだけど、とりあえず無難そうなResizeだけ説明。そのResize()もパラメータをいくつか選べる。
PS C:\temp> $image.Resize OverloadDefinitions ------------------- void Resize(int width, int height) void Resize(ImageMagick.MagickGeometry geometry) void Resize(ImageMagick.Percentage percentage) void Resize(ImageMagick.Percentage percentageWidth, ImageMagick.Percentage percentageHeight)
一番簡単なやつがwidth, heightを指定するやつ(New-ObjectとWriteはここの説明では省略)
PS C:\temp> $image.Resize(200, 100)ただし、アスペクト比を維持するので、(200, 100)にはならない。ここに入る大きさになる。
パーセンテージ指定が次に簡単(書き方がイマイチ...)
PS C:\temp> image.Resize((New-Object ImageMagick.Percentage 50))
で、もっともいろいろできるのが、MagickGeometry指定パターン。ImageMagickをコマンドで使っている人ならおなじみの、例の記法が使える。例えば、アスペクト比を無視する!を付与したスタイル。
PS C:\temp> $image.Resize((New-Object ImageMagick.MagickGeometry '200x200!'))
このあたりの挙動はImageMagickそのものの話なので、詳しくは公式ドキュメント(ImageMagick v6 Examples --
Resize or Scaling (General Techniques))を参照。なお、日本語でまとめてくれてる人もいる(ImageMagickでリサイズする方法)
複数ファイル系の処理
ここからはこの2つの画像を例に説明。結合
結合は、MagickImageCollectionを作ってimageを追加し、AppendHorizontally()かAppendVertically()を呼ぶ。PS C:\temp> $image1 = New-Object ImageMagick.MagickImage c:\temp\sample.jpg PS C:\temp> $image2 = New-Object ImageMagick.MagickImage c:\temp\sample2.jpg PS C:\temp> $col = New-Object ImageMagick.MagickImageCollection PS C:\temp> $col.Add($image1) PS C:\temp> $col.Add($image2) PS C:\temp> $image = $col.AppendVertically() # あるいは $col.AppendHorizontally() PS C:\temp> $image.Write('c:\temp\sample-out.jpg')
重ねる
結合とだいたい同じノリだけども、重ねることも可能。PS C:\temp> $image1 = New-Object ImageMagick.MagickImage c:\temp\sample.jpg PS C:\temp> $image2 = New-Object ImageMagick.MagickImage c:\temp\sample2.jpg PS C:\temp> $col = New-Object ImageMagick.MagickImageCollection PS C:\temp> $col.Add($image1) PS C:\temp> $col.Add($image2) PS C:\temp> $image = $col.Evaluate([ImageMagick.EvaluateOperator]::Add) PS C:\temp> $image.Write('c:\temp\sample-out.jpg')
ここまで書いておいて例が悪いな。
etc, etc...
あとはBlurとか、さまざまなフィルタがあるのだけど、きりないからこのへんでやめ。ImageMagickは加工は得意なので、できることはたくさんある。他のものを知りたかったら、$image.で[TAB]してみたり、MagickNetのドキュメントとか、ImageMagickのコマンドラインオプション(ImageMagick: Command-line Options)を参照。
おまけ: 統計情報の表示
最後に一応、需要はなさそうだけど、これをやるために使い始めたので説明。平均とかの取り方。Statistics()を呼んで、Composite()あるいはGetChannel(チャンネル)を呼ぶ。
先に
$image.Grayscale([ImageMagick.PixelIntensityMethod]::Lightness)を呼んでおくのも便利かも。
PS C:\temp> $stat = $image.Statistics() PS C:\temp> $stat.Composite() Channel : Composite Depth : 1 Entropy : 0.966856332282486 Kurtosis : -1.25816857805541 Maximum : 65535 Mean : 27115.482213115 Minimum : 0 Skewness : 0.0779930273889325 StandardDeviation : 17685.6919467067 Sum : 27115.482213115 SumCubed : 45922010656938.6 SumFourthPower : 2.14361048522477E+18 SumSquared : 1049386363.99743 Variance : 312783699.633806 PS C:\temp> $stat.GetChannel([ImageMagick.PixelChannel]::Blue) Channel : Blue Depth : 8 Entropy : 0.967346949241304 Kurtosis : -1.26933689965117 Maximum : 65535 Mean : 28404.2418122061 Minimum : 0 Skewness : 0.0995661483530123 StandardDeviation : 18559.3929293196 Sum : 28404.2418122061 SumCubed : 52904690206274 SumFourthPower : 2.59600361552516E+18 SumSquared : 1151252018.83115 Variance : 1151252018.83115
0 件のコメント:
コメントを投稿