rosスクリプト練習: PDFをPNG画像で出力
元々の動機:impressで作ったスライドを1920x1080ピクセルでまとめて画像保存したい。
impressからPDFに出力して、xpdfに付属するコマンドpdftoppmで画像のセットに変換した後、image-magickのconvertでppmからpngに変換する。
#!/bin/sh #|-*- mode:lisp -*-|# #| exec ros -Q -- $0 "$@" |# (ql:quickload :uiop :silent t) (ql:quickload :cl-ppcre :silent t) (defun catstr (&rest args) (apply #'concatenate 'string args)) (defun format-directory (p) (assert (eq (car (pathname-directory p)) :absolute)) (reduce (lambda (a b) (catstr a b "/")) (cons "/" (cdr (pathname-directory p))))) (defun format-pathname (p &optional type) (format nil "~A~A.~A" (format-directory p) (pathname-name p) (if type type (pathname-type p)))) (defun pwd () (truename "./")) (defun ls (&optional dir) (uiop:directory-files (if dir dir (pwd)))) (defun main (&rest argv) (declare (ignorable argv)) (assert (= (length argv) 2)) (assert (uiop:file-exists-p (first argv))) ;; create ppm images (1920x1020px) (uiop:run-program (list "pdftoppm" "-rx" "174.02" "-ry" "174.2" (first argv) (second argv))) ;; select ppm images (let ((ppm-files (remove-if-not (lambda (p) (and (equal (pathname-type p) "ppm") (ppcre:scan (catstr "^" (second argv) ".*") (pathname-name p)))) (ls)))) (dolist (ppm-file ppm-files) ;; convert ppm image to png (uiop:run-program (list "convert" (format-pathname ppm-file) (format-pathname ppm-file "png"))) ;; remove ppm image (uiop:run-program (list "rm" (format-pathname ppm-file))))))
$ pdftopng input.pdf output $ ls input.pdf output-1.png output-2.png output-3.png
カレントディレクトリを取得する方法:逆引きCommon Lisp: 処理系を起動したディレクトリのパスネームを返す
カレントディレクトリは (uiop:getcwd) でも取れるらしい。
merge-pathnameがあればcdは別にいらないかな。
単にsbcl --scriptだとquicklispが読み込まれなかったりして、ライブラリ読み込み済のコアイメージをダンプしなければいけなかったりと色々と面倒(sbclでscriptオプションを利用したさいにquicklispが利用できなくなってしまう)。roswellを使うと引数の取り扱いや処理系の終了など何も考えなくていいので楽。
shebangに色々書くという方法もあるらしいけど(あなたの知らないShebang)、eshellだと動かなかった。やはりroswellか。