かきかたえんぴつ

いつかどこかで何かの役にたつかもしれないメモ

Inkscape SVG の各レイヤを PDF にエクスポートする

Inkscape で作った SVG の各レイヤを個別の PDF ファイルに書き出し、最後にそれらを 1 つの PDF ファイルにまとめる Python スクリプト。

Inkscape と gswin32c に PATH が通っていると仮定。Windows 用なので、他の環境で動かすには修正が要る。

import os, sys
from xml.etree.ElementTree import *

argv = sys.argv
argc = len(argv)
if(argc < 2):
    print 'Usage: svg2pdf.py hoge.svg'
    quit()

path = argv[1]
base, ext = os.path.splitext(path)

tree = parse(path)
pdflist = ""

SVG_NS = "http://www.w3.org/2000/svg"

for layer in tree.findall('.//{%s}g' % SVG_NS):
    lid = layer.get("id")

    if lid.find("layer") < 0:
        continue
    
    cmd = "inkscape -C -f \"%s\" -A %s_%s.pdf -j -i \"%s\"" \
          % (path, base, lid, lid)
    print cmd
    os.system(cmd)
    pdflist += " %s_%s.pdf" % (base, lid)

cmd = "gswin32c -dNOPAUSE -sDEVICE=pdfwrite " \
      + "-dAutoFilterColorImages=false " \
      + "-dColorImageFilter=/FlateEncode " \
      + "-sOUTPUTFILE=%s.pdf -dBATCH %s" \
      % (base, pdflist)
print cmd
os.system(cmd)

個別に書き出した PDF は放ったらかし。非表示のレイヤは真っ白なページとして出力される。

  • 2013.02.06 追記

レイヤでないオブジェクトを PDF に吐き出すことがあるので、

    if lid.find("layer") < 0:
        continue

の2行を加えた。

Windows で Unicode 文字をキーボードから入力する

Unicode 文字を入力する機能を用意しているプログラムもあるが(Microsoft Word や Inkscape など)、そのような機能が無い場合、Windows の機能が使える。

レジストリをいじる。regedit で HKEY_CURRENT_USER\Control Panel\Input Method に EnableHexNumpad という REG_SZ(文字列値)の項目をつくり、値を 1 に設定する。Windows にログインし直してレジストリの変更を反映させる。

設定後、Unicode 文字を入力したいときには以下のようにする。

  1. Alt キーを押しながら
  2. テンキーの「+」を押し
  3. Unicode を 16 進数で入力し
  4. Alt キーを離す。

参考:

Cairo で PDF に埋め込んだビットマップがボケる

Cairo 1.10 以降でビットマップ画像を埋め込んだ PDF を作ると、その画像にデフォルトで /Interpolate true フラグが設定される。画像の解像度が低いとピクセルの境目がボケているのが見えてしまう。これを回避するには、CAIRO_FILTER_NEAREST フィルタを設定する。たとえば、

cairo_surface_t* cs = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
// ...
cr = cairo_create(cs);
// ...
cairo_set_source_surface(cr, img, 0, 0);
cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
cairo_paint(cr);

Inkscape は PDF 出力に Cairo を使っているので、最近の Inkscape が吐いた PDF でも /Interpolate true が設定されてしまう。どうにかならんかなー。

Ghostscript を使って PDF のページサイズを変更する

たとえば in.pdf のページサイズを強制的に A4 にして out.pdf に保存するには、以下のようにする。

gswin32c -q -dNOPAUSE -dBATCH -o out.pdf -sDEVICE=pdfwrite -sPAPERSIZE=a4 -dFIXEDMEDIA -c "<</PageOffset [10 20]>> setpagedevice" -f in.pdf

[10 20] のところで x 方向、y 方向のオフセットを指定する(単位はポイント、負の値も可)。Unix だと gswin32c のかわりに gs か?

ユーザー定義のサイズを指定したいときは、

-sPAPERSIZE=a4

のかわりに

-dDEVICEWIDTHPOINTS=595 -dDEVICEHEIGHTPOINTS=842

のようにする。単位はポイント。

連番でない PNG 画像をとにかく動画に変換

指定されたディレクトリの PNG 画像を連番ファイル名にリネームしたあげく、ffmpeg を使って MP4 動画に変換してしまう Python コード。encode.py とでも名前を付けて

python encode hoge foo

のように使えば、hoge ディレクトリの PNG 画像から foo.mp4 ができる。

連番の桁数や ffmpeg のパラメータは適当に変更すべし。

import glob
import os
import subprocess
import sys

wd  = '.'
out = 'out'

argc = len(sys.argv)
if(argc > 1):
    wd = sys.argv[1]
if(argc > 2):
    out = sys.argv[2]

files = glob.glob(wd + '/*.png')
i = 0
for f in files:
    print f
    os.rename(f, wd + '/%03d.png' % i)
    i += 1

cmd = 'ffmpeg -r 10 -i ' \
      + wd + '/%03d.png -r 10 -vcodec libx264 ' \
      + out + '.mp4'
print cmd
subprocess.call(cmd, shell=True)

Beamer で PDF ファイルに動画を埋め込む

以下の URL から media9 パッケージをダウンロードする。

zip ファイルの中身を C:\w32tex\share\texmf に入れる。ls-R を使っていなければインストール終わり。使っていれば mktexlsr などするのだと思う。

動画の埋込み方は、パッケージを読み込んで

\usepackage[english]{babel}
\usepackage{media9}

以下のように記述する。

\begin{center}
\includemedia[
  activate=pageopen,
  width=160pt,height=160pt,
  addresource=hoge.mp4,
  flashvars={%
     src=hoge.mp4%
     &autoPlay=false%
     &scaleMode=stretch%
     &volume=0%
     &loop=true%
  }  
]{}{StrobeMediaPlayback.swf}
\end{center}

hoge.mp4 には動画ファイルへのパスを指定する。他のパラメータは適宜変更。MP4 の縦横ピクセル数が偶数でないとうまくいかなかったが、理由は不明。とりあえず xelatex ではコンパイルできた。

参考: