Skip to content

Instantly share code, notes, and snippets.

@Yarakashi-Kikohshi
Last active May 17, 2021 05:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Yarakashi-Kikohshi/3cb8d19bc6a5c75826ec667912bf4f3a to your computer and use it in GitHub Desktop.
Save Yarakashi-Kikohshi/3cb8d19bc6a5c75826ec667912bf4f3a to your computer and use it in GitHub Desktop.
Convert multi page PDF to SVG with BAT file

Convert multi page PDF to SVG with BAT file

VSCode +LaTeX Workshop を利用してpdftocairo をrecipes から実行することが出来ることを紹介した.

しかし,この中で,SVG の変換に関しては単数ページPDF またはPDF 内の特定の1ページの変換しか対応していない. そのために,いちいちPDF を単数ページで作成したり,単数ページのPDF に分割するのは面倒である.

上手く1つのコマンドから複数ページのPDF を一気にSVG に変換したい. これを実現するために,BAT (バッチ) ファイルを利用してスクリプトを組みたい.Windows であれば誰でも利用することが可能なためBAT ファイルを採用している.

BAT ファイルとは,コマンドプロンプトから実行することのできるコマンドをまとめたファイルです.一連のコマンドをまとめておくことで1回の操作で実現できるようになります.

もしも他の言語が好みであれば作成してみると良いだろう.Bash とか? Batch の他ではrecipe から実行できるかは検証していません.

BAT file and settings.json

LaTeX Workshop を利用している際にrecipes からBAT ファイルを実行させることでpdftocairo-svg オプション付きで利用したい.

settings.json を見れば明らかだが,サブフォルダに成果物を出力するようにしている.これは大量の画像をTeX ファイルと同じディレクトリに出力してごちゃごちゃになることを避けるためである.

BAT file

TeX ファイルのあるフォルダにmppdf2svg.bat (Multi Page PDF to SVG) ファイルを設置する.

BAT ファイルの設計目標は以下の通りになる.

  1. pdfinfo からPDF の諸情報を取得
  2. findstr で"Pages:" の行からPDF のページ数を取得
  3. pdftocairo をページ数分だけ繰り返し実行し,1ページずつSVG に変換

また,該当するPDF ファイルが存在しない場合には停止する(SVG への変換をスキップする) ようにしている.

実際に作成すると次のファイルで示すBatch ファイルのようになった.

mppdf2svg.bat

Usage

基本的な使い方は以下を想定している.

$ mppdf2svg.bat <PDF-file-name-without-extension> <[option] SVG-folder-name>

Option

オプションのデフォルトはimage フォルダが作成されSVG がその中に生成される.任意のフォルダ名を入力すればそのフォルダ内にSVG が生成される.

PDF と同じディレクトリに出力したい場合には.\ をオプションで付与すれば良い.

option subfolder
no type (default) image folder
hoge hoge folder
.\ same PDF folder

オプションは2つ目に課すようにする.また,スペースを含みたい場合はダブルクオーテーション" で囲んでいても良い.

Example

3ページのtest.pdf に対して以下を実行したとする.

$ mppdf2svg.bat test svg-image

test.pdf のフォルダ内にsvg-image フォルダが作成され,その中にSVG ファイルが生成される.

Result folder and files structure

  . (x:\path\to\PDF\file\test)
  ├── mppdf2svg.bat
  ├── test.pdf
  └── svg-image
      ├── test-image-1.svg
      ├── test-image-2.svg
      └── test-image-3.svg

OUTPUT: (LaTeX Compiler)

Running mppdf2svg.bat (`pdftocairo`)...
Search "test.pdf"...
... ... Found it

----- ----- BEGIN TO CONVERT ----- -----
Get PDF information...
+++: x:\path\to\PDF\file\test\pdfinfo.txt
Make SVG output "image-svg" folder
Convert 4 page PDF to SVG...
+++: x:\path\to\PDF\file\test\svg-image\test-image-1.svg
+++: x:\path\to\PDF\file\test\svg-image\test-image-2.svg
+++: x:\path\to\PDF\file\test\svg-image\test-image-3.svg

----- ----- END TO CONVERT ----- -----
`mppdf2svg.bat` ERRORLEVEL: 0

PDF やSVG が出力されているサブフォルダ内にpdfinfo.txt ファイルが出力されているが,これはpdfinfo によって得たPDF の諸情報が記載されている.

もしもこれを自動的に削除したい場合は,次のスクリプトをecho COMPLETED!! の前に加えておけば良いだろう.(下のコードではコメントアウトにしている)

echo Delete "pdfinfo.txt" ...
for /f %%d in ('dir /s/b "pdfinfo.txt"') do (
    del /q %%d
    echo ---: %%d
)

Known issues

少しだけ問題点がある.

カレントディレクトリ以下に含まれる同一名PDF が複数ある場合,これらを区別することは出来ない.(存在しない場合のみははじくことが出来る)

LaTeX Workshop でLaTeX を編集している際に利用することを想定しているので,カレントディレクトリ以下に同一名のPDF が複数ある可能性はほとんどないものと考えている.

その他問題があれば...

settings.json for LaTeX Workshop

recipes とtools に以下を加える.

settings.json

  "latex-workshop.latex.recipes": [
    // another recipes ...
    {
      "name": "Convert multi page PDF to SVG",
      "tools": ["mppdf2svg_batch"]
    },
  ],
  "latex-workshop.latex.tools": [
    // another tools ...
    {
      "name": "mppdf2svg_batch",
      "command": "./mppdf2svg.bat",
      "args": [
        "%DOCFILE%",
        // "OUTDIR_NAME",// OPTION SVG DIRECTORY
      ]
    },
  ],

カレントディレクトリにBAT ファイルを設置しているが,任意のディレクトリに設置することも可能である.(ホームディレクトリとか?) これは,"command" を絶対パスで指定すれば良い.

ちなみに,~ を利用したホームディレクトリの指定は出来ないようだ.絶対パスで指定しよう.

FAQ - # You cannot use a tilde ~ in PATH LaTeX -Workshop Wiki - GitHub

まとめ

これでpdftocairo を利用して複数ページのPDF をSVG に変換することが出来るようになった. 他に良い方法があれば教えてほしい.

LaTeX Workshop を利用してBAT ファイルを実行することが出来るという知見を得ることが出来ました.これからさまざまなことを出来るようになりそうですね.

調子乗って作成していたら初めに作成したものから比べると倍ほど長いコードとなった.処理の各セクションにはコメントアウトで注釈を挿入しているので,もしも利用したい人がいれば確認しておいてほしい. 変なコードにはなっていないはずです.

これに加えて,pdftocairo ではPNG の変換なども可能だが,サブフォルダ内に生成することは出来ない.したがって,このBAT ファイルをいじっても良いだろうと思われる.(ほとんどいらない部分が多い気がする)

Modified mppdf2svg

旧ドキュメント

これまで示していたmppdf2svg.bat では以下のようなの不自由さがあったように思われる.

  • 複数の引数を使用してBAT ファイルを利用していた
  • PDF のあるフォルダ名を限定していた
  • SVG を出力するフォルダをPDF と同一のフォルダに指定していた

これらの点から,少し改修を試みた.この結果として以下のように自由度を持たせることが出来た.

  • 変換したいPDF を探して自動的に作業ディレクトリを移動
  • SVG を出力するフォルダを簡易的に変更可能

また,基本的な引数をPDF のファイル名のみに限定した.

@echo off
@REM ARGS DESCRIPTION
@REM %~1: PDF file name
@REM %~2: SVG output subfolder name
echo ----- ----- ----- ----- -----
if "%1"=="" (
goto ARGS_ERROR
) else (
goto RUN_START
)
:ARGS_ERROR
echo NO ARGUMENTS
pause
exit /b 33
:RUN_START
echo Running mppdf2svg.bat (`pdftocairo`)...
@REM SEARCH PDF FILE SEQUENCE
set PDF_FILE=
echo Search "%~1.pdf"...
for /f %%F in ('dir /s/b "%~1.pdf" 2^> nul') do (
set PDF_FILE=%%~nxF
)
setlocal enabledelayedexpansion
if "%~1.pdf"=="%PDF_FILE%" (
echo ... ... Found it
goto RUN_BEGIN
) else (
echo CAUTION: NO EXIST PDF FILE !!!
goto RUN_STOP
)
endlocal
:RUN_STOP
popd
echo.
echo ----- ----- EMARGENCY STOP ----- -----
echo `mppdf2svg.bat` ERRORLEVEL: %errorlevel%
exit /b 4
:RUN_CAIRO_STOP
popd
echo.
echo ----- ----- EMARGENCY STOP ----- -----
echo `pdftocairo` ERRORLEVEL: %errorlevel%
exit /b
:RUN_BEGIN
echo.
echo ----- ----- BEGIN TO CONVERT ----- -----
@REM MOVE THE WORKING DIRECTORY TO THE FOLDER CONTAINING "PDF YOU WANT TO CONVERT TO SVG"
set WDIR=
for /f %%W in ('dir /s/b "%PDF_FILE%"') do (
pushd %%~dpW
set WDIR=%%~dpW
)
@REM GET PDF INFORMATION WITH `pdfinfo`
echo Get PDF information...
call pdfinfo %PDF_FILE% > pdfinfo.txt
for /f %%I in ('dir /s/b "%WDIR%pdfinfo.txt"') do (
echo +++: %%~I
)
@REM GET PDF PAGES INFORMATION WITH `findstr` FROM "pdfinfo.txt"
set CONVERT_FILES=
for /f "tokens=2" %%N in ('findstr "Pages:" pdfinfo.txt') do (
set CONVERT_FILES=%%N
)
@REM MAKE A FOLDER TO PUT SVG FILES
set OUTPUT_SVG=
if "%~2"=="" (
set OUTPUT_SVG=.\image\
mkdir image > nul 2>&1
echo Make SVG output "image" folder
) else if "%~2"==".\" (
set OUTPUT_SVG=
echo Output same PDF folder
) else (
set OUTPUT_SVG=.\%~2\
mkdir %~2 > nul 2>&1
echo Make SVG output "%~2" folder
)
@REM CONVERT PDF TO SVG USING `pdftocairo`, REPEATEDLY PAGE BY PAGE
echo Convert %CONVERT_FILES% page PDF to SVG...
for /l %%i in (1,1,%CONVERT_FILES%) do (
call pdftocairo -svg -f %%i -l %%i %PDF_FILE% %OUTPUT_SVG%%~1-image-%%i.svg 2> nul
if errorlevel 1 (
echo %errorlevel%
goto RUN_CAIRO_STOP
) else (
for /f %%C in ('dir /s/b "%OUTPUT_SVG%%~1-image-%%i.svg"') do (
echo +++: %%C
)
)
)
@REM DELETE "pdfinfo.txt"
@REM echo Delete "pdfinfo.txt" ...
@REM for /f %%d in ('dir /s/b "pdfinfo.txt"') do (
@REM del /q %%d
@REM echo ---: %%d
@REM )
@REM RETURN TO THE ORIGINAL DIRECTORY
popd
echo.
echo ----- ----- END TO CONVERT ----- -----
echo `pdf2svg.bat` ERRORLEVEL: %errorlevel%
exit /b 0

Convert multi page PDF to SVG with BAT file

VSCode +LaTeX Workshop を利用してpdftocairo をrecipes から実行することが出来ることを紹介した.

しかし,この中で,SVG の変換に関しては単数ページPDF またはPDF 内の特定の1ページの変換しか対応していない. そのために,いちいちPDF を単数ページで作成したり,単数ページのPDF に分割するのは面倒である.

上手く1つのコマンドから複数ページのPDF を一気にSVG に変換したい. これを実現するために,BAT (バッチ) ファイルを利用してスクリプトを組みたい.Windows であれば誰でも利用することが可能なためBAT ファイルを採用している.

BAT ファイルとは,コマンドプロンプトから実行することのできるコマンドをまとめたファイルです.一連のコマンドをまとめておくことで1回の操作で実現できるようになります.

もしも他の言語が好みであれば作成してみると良いだろう.Bash とか?

What is Shell in VSCode ?

LaTeX Workshop でLaTeX Workshop: Build with Recipe からタイプセットを実行する際に,内部では以下のような実行コマンドを命令しているはずだ.(tools を見れば明らか)

$ platex -u test.tex

これはコマンドプロンプトを叩いているのだろうか,それともPowerShell を叩いているのだろうか.

結論から言えば,どうやらPowerShell を叩いているようだ.これに関して公式のドキュメントを探し出すことは出来なかった.

settings and bat file

LaTeX Workshop を利用している際にrecipes からBAT ファイルを実行させることでpdftocairo を-svg オプション付きで利用したい.

今回,2パターンのBAT ファイルを作成してみた.settings.json に関しては統一して利用することが出来る.

settings.json を見れば明らかだが,サブファイルに成果物を出力するようにしている.これは大量の画像をTeX ファイルと同じディレクトリに出力してごちゃごちゃになることを避けるためである.

これを嫌う場合は,~.latex.outDir"OUTDIR" を削除,BAT ファイルでは%~2. に変更すれば良いだろう.(動作未確認)

settings.json

recipes とtools に以下を加える.

settings.json

  "latex-workshop.latex.outDir": "%DIR%\\%DOCFILE%",
  "latex-workshop.latex.clean.subfolder.enabled": true,
  "latex-workshop.latex.recipes": [
    // another recipes ...
    {
      "name": "Convert multi page PDF to SVG",
      "tools": ["mppdf2svg"]
    },
  ],
  "latex-workshop.latex.tools": [
    // another tools ...
      {
        "name": "mppdf2svg",
        "command": "./mppdf2svg.bat",
        "args": [
          "%DOCFILE%",
          "%OUTDIR%",
        ]
      },
  ]

1つ目の引数にしている%DOCFILE% はBAT ファイル内のコマンドの引数に使用している. 2つ目の引数にしている%OUTDIR% はOutput に出力される文言のみに使用している.

BAT file

TeX ファイルのあるフォルダにmppdf2svg.bat (Multi Page PDF to SVG) ファイルを設置する.

BAT ファイルの設計目標は以下の通りになる.FILENAME.pdf を変換することを想定したい.

Pattern 1

  1. pdfseparate でN ページのPDF を分割 (FILENAME-n.pdf)
  2. 分割されたPDF ファイルの数をカウント
  3. pdftocairo をファイル数分だけ繰り返し実行し,PDF をSVG に変換 (FILENAME-n-image.svg)
  4. 分割したPDF ファイルをすべて削除

Pattern 2

  1. pdfinfo からPDF の諸情報を取得
  2. findstr で"Pages:" の行からPDF のページ数を取得
  3. pdftocairo をページ数分だけ繰り返し実行し,PDF をSVG に変換 (FILENAME-n-image.svg)

実際に作成すると以下のようになった.

Pattern 1

mppdf2svg.bat

@echo off

echo Separate PDF...
call pdfseparate .\%~1\%~1.pdf .\%~1\%~1-%%%%d.pdf

@REM COUNT SEPALETED PDF FILES
set a=0
for /f %%i in ('2^>nul dir .\%1 /a-d/b/-o/-p/s^|find /c ".pdf"') do (
    set n=%%i
)
set /a CONVERT_FILES=%n%-1

echo Convert %CONVERT_FILES% PDF to SVG...
for /l %%j in (1,1,%CONVERT_FILES%) do (
    call pdftocairo -svg .\%~1\%~1-%%j.pdf .\%~1\%~1-%%j-image.svg
    echo +++: %~2\%~1-%%j-image.svg
)

echo Delete separated PDF files...
for /l %%k in (1,1,%CONVERT_FILES%) do (
    del /q .\%~1\%~1-%%k.pdf
    echo ---: .\%~1\%~1-%%k.pdf
)

echo COMPLETED!!

Output example: LaTeX Compiler

例えば,3ページのPDF ファイルを分割してSVG に変換した際には,以下のような文言をOutput に得る.

Separate PDF...
Convert 3 PDF to SVG...
+++: X:/path/to/separated/PDF/FILENAME\FILENAME-1-image.svg
+++: X:/path/to/separated/PDF/FILENAME\FILENAME-2-image.svg
+++: X:/path/to/separated/PDF/FILENAME\FILENAME-3-image.svg
Delete separated PDF files...
---: .\FILENAME\FILENAME-1.pdf
---: .\FILENAME\FILENAME-2.pdf
---: .\FILENAME\FILENAME-3.pdf
COMPLETED!!

Pattern 2

mppdf2svg.bat

@echo off

echo Get PDF information...
call pdfinfo .\%~1\%~1.pdf > .\%~1\pdfinfo.txt
echo +++: %~2\pdfinfo.txt

@REM GET PDF PAGE INFORMATION
for /f "tokens=2" %%N in ('findstr "Pages:" .\%~1\pdfinfo.txt') do (
    set CONVERT_PAGES=%%N
)

echo Convert %CONVERT_PAGES% pages PDF to SVG...
for /l %%i in (1,1,%CONVERT_PAGES%) do (
    call pdftocairo -svg -f %%i -l %%i .\%~1\%~1.pdf .\%~1\%~1-%%i-image.svg
    echo +++: %~2\%~1-%%i-image.svg
)

echo COMPLETED!!

Output example: LaTeX Compiler

例えば,3ページのPDF ファイルを分割してSVG に変換した際には,以下のような文言をOutput に得る.

Get PDF information
+++: X:/path/to/separated/PDF/FILENAME\pdfinfo.txt
Convert 3 pages PDF to SVG...
+++: X:/path/to/separated/PDF/FILENAME\FILENAME-1-image.svg
+++: X:/path/to/separated/PDF/FILENAME\FILENAME-2-image.svg
+++: X:/path/to/separated/PDF/FILENAME\FILENAME-3-image.svg
COMPLETED!!

PDF やSVG が出力されているサブファイル内にpdfinfo.txt ファイルが出力されているが,これはpdfinfo によって得たPDF の諸情報が記載されている. もしもこれを自動的に削除したい場合は,次のスクリプトをecho COMPLETED!! の前に加えておけば良いだろう.

echo Delete pdfinfo.txt...
del /q .\%~1\pdfinfo.txt
echo ---: %~2\%~1\pdfinfo.txt

まとめ

これでpdftocairo を利用して複数ページのPDF をSVG に変換することが出来るようになった.

本記事ではpdfseparate で1ページごとに分割してそれぞれをSVG に変換する方法とpdfinfo でPDF のページ数を取得して各ページを変換する方法の2つを作成した. 他に良い方法があれば教えてほしい.

個人的には2つ目の方法を用いる方が余分なPDF を大量に作成しないで済むので良いだろうと思われる.

LaTeX Workshop を利用してBAT ファイルを実行することが出来るという知見を得ることが出来ました.これからさまざまなことを出来るようになりそうですね.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment