LoginSignup
31
29

More than 5 years have passed since last update.

PowerShellスクリプトでPowerPointファイルPNG化+まとめて画像操作

Posted at

Windows上で軽くスクリプトでまとめて何かしたい、みたいなときにPowerShellさんが変態チックで面白かったのでそのメモ。

やりたいこと

PowerPointで作った資料をまとめて画像化したい。画像化したものは余白でトリミングして適当なマージンつけてとかしたい。

はじめっからPowerPointで作らず別のツールで作れよ、という感じかもしれませんが、ストーリーを考えながらえいやでべたべた貼りつけていくのにはPowerPointが一番慣れてしまっている・・・

以前もJavaでCOMオブジェクトのラッパーとか使ってPowerPoint.Applicationオブジェクトにアクセスして自動化とかしてたわけですが、Java実行環境は入ってなさそうな人の環境上でも実行する可能性があったので、Windows標準みたいな部分だけでなんとかならないかなあと。

PowerShell

で、PowerShellさんのことを思い出しました。
以前はcygwin環境だったのでまったくさわってなかったのですが、インフラ管理系のことをはじめてから、できるだけ、すでにインストールされているソフトウェアだけでなんとかするような感じで適応してしまったりで、ちょこちょこさわるようになってきたというのもあり。

この辺の、他のシェルと一線を画す感じの変態仕様がグッときます。

パイプを使ってコマンド間でオブジェクトを流せる

パイプで Get-Process | where {$_.ProcessName -eq "chrome"} | select CPU とか書けるのが素敵です。
コマンド(コマンドレット)間でパイプを通じて.NETオブジェクトが流れていきます。型がついている分、テキストベースのパイプのカジュアルさが失われている感もありますが、パイプを介してオブジェクトがあれこれされていくさまを見るのは嫌いじゃないです。

.NET FrameworkだけでなくCOMのオブジェクトも生成できる

コマンドラインで $ppApp = New-Object -com PowerPoint.Applicationとかして、$pptPres = $ppApp.Presentations.Open("hogehoge.pptx") とかできるのが素敵です。オブジェクトの後始末はそれなりに面倒ではありますが。

やってみた

PowerPointをPNGにする / 画像の余白を削り取る / マージンを追加する / 一定サイズに収まるようにリサイズする みたいな個々の機能をPowerShellスクリプト(.ps1)にして必要に応じて組み合わせる形を考えています。
各スクリプトをできるだけ独立して作りたかったのと、既存の ls (実体は Get-ChildItem)とかとうまくつなげたかったので、同じタイプのオブジェクトをパイプに流す格好に。

pipe.jpg

作ってみたのはこんな感じのスクリプト:https://gist.github.com/yacchin1205/925851027b84240b512f
自分の作業に必要な範囲内なので色々適当。

ファイル 機能
Export-PPT2PNG.ps1 パイプから入力されたファイルパスで示されたファイルを PowerPoint.Application で開き、-Outオプションで示されたディレクトリに全スライドをPNG画像として保存し、そのパスを出力する
Trim-Image.ps1 パイプから入力されたファイルパスで示される画像ファイルの余白(ARGB 0xffffffff)部分を切り抜き、-Outオプションで示されたディレクトリに保存し、そのパスを出力する
Resize-Image.ps1 パイプから入力されたファイルパスで示される画像ファイルを-Width, -Heightオプションで示されるサイズ(pixel)にしたがって縮小し、-Outオプションで示されたディレクトリに保存し、そのパスを出力する
Add-Image-Margin.ps1 パイプから入力されたファイルパスで示される画像ファイルを-Marginオプションで示されるサイズ(pixel)にしたがって縮小し、-Outオプションで示されたディレクトリに保存し、そのパスを出力する。-MarginTop, -MarginBottom, -MarginLeft, -MarginRightでマージンを細かく指定することもできる。

使い方としては、これらのファイルを適当なところにおいて、PowerShellのコンソールから、

> ls hogehoge.pptx | .\Export-PPT2PNG.ps1 -Out .\work | .\Trim-Image.ps1 -Out .\work | .\Resize-Image.ps1 -Out .\work -Width 700 | .\Add-Image-Margin.ps1 -Out .\out

とかするとhogehoge.pptxの内容が画像で保存されて色々加工されてoutディレクトリに加工された画像が作られます。作業用のworkディレクトリにはもろもろ途中状況の画像が保存される。(各ディレクトリは事前に作成してある必要あり)

あと、PowerShellスクリプトを実行するにはSet-ExecutionPolicyを変更しておく必要があります。
参考:Set-ExecutionPolicy コマンドレットの使用

もろもろ感想

パラメータの設定が楽ちん

param() を使ってスクリプトに与えるパラメータが簡単に定義できてよいです。

Export-PPT2PNG.ps1
param(
    [Parameter(Mandatory=$True)]
    [string]$out,
    [Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
    [Alias('FullName')]
    [String[]]$filePaths
)

...

みたいにしてあげると、-Outオプションで指定された内容が簡単に変数で参照できるように。

あと、パイプから与えるファイルパスについても、同じくここで宣言していますが、ここではFileSystemInfoオブジェクトの場合はFullNameプロパティが受け取りたいし一方で単純な文字列も受け取りたいしで Alias('FullName') とか書いています。この辺はちと煩雑な気もする・・・

作業ディレクトリの扱いが.NET FrameworkとPowerShellで別々なのが謎

PowerShellで cd とかして設定した作業ディレクトリと、.NET FrameworkのCurrent Directoryは別ものという謎仕様。

PS C:\Users\Test\hogehoge> [IO.Directory]::GetCurrentDirectory()
C:\Users\Test
PS C:\Users\Test\hogehoge> Get-Location

Path
----
C:\Users\Test\hogehoge

そのせいで、.NETのオブジェクトに気軽に相対パスとかを渡してしまうと「ファイルが作成されないー」みたいに悩んでしまいます。

この回避方法はいくつかあるようですが、今回は Resolve-Path を利用して必ずパス表現オブジェクトを取得して.NETオブジェクトに渡すようにしています。

Export-PPT2PNG.ps1
...
begin {
    ...
    $outPath = Resolve-Path $out
}
...

エラーでの終了

一見.NETのコードを書いている気になってしまい忘れがちですが、PowerShellスクリプトはデフォルトではエラーが発生しても終了せず、次の行の実行を継続します。
エラーで終了したい場合は、$ErrorActionPreference を使ってエラー時の挙動を定義してあげる必要があります。

Export-PPT2PNG.ps1
...
begin {
    $ErrorActionPreference = "Stop"
    ...
}
...

こんな感じで、OfficeとかCOM経由で機能をさわれたりするアプリケーションに関しては、PowerShellでお気軽に自動化できそうな感じがします。

画像の処理とかは.NETの標準的なオブジェクトの範囲内でスクリプトでロジックを組んでやってみたけれど、やっぱりNuGetとかで画像処理系のライブラリを拾ってきて、それに食わせてあげるのが楽ちんかなと。今回は、あんまり人の環境にインストールされているものを気にしたくなかった(汚したくなかった)のでこんな格好なわけですが・・・

31
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
29