LaTeX→DVI→PDF→(複数枚の)画像→結合した画像という順番で処理します。
LaTeXをDVIに変換するには
platex -guess-input-enc -interaction=nonstopmode xxx.tex
とします。
DVIをPDFに変換するには
dvipdfmx -f ptex-ipaex.map xxx.dvi
とします(ptex-ipaex.map
はフォント埋め込みの設定ファイルです)。
PDFをPNG画像に変換するにはImageMagickのコマンドであるconvert
を使用します。
convert -density 800 xxx.pdf -quality 100 -resize 800 xxx.png
とします(-density
は解像度、-quality
は品質、-resize
はサイズです)。PDFが複数ページの場合は複数枚の画像が生成されます。複数枚の画像が生成される場合、それぞれの画像のファイル名はxxx-1.png
、xxx-2.png
、・・・、xxx-9.png
、xxx-10.png
、・・・となります。
画像を結合するには
montage +frame +shadow +label -tile 2x -geometry 800x600+0+0 xxx-*.png xxx.png
とします(+frame +shadow +label
はmontage
に画像の結合以外の余計なことをさせないための設定、-tile
は縦横何枚ずつ画像を並べるか、-geometry
は画像を並べる場所(タイル)のサイズです。-tile 2x
で横2枚ずつ並べるという設定です。-geometry 800x600+0+0
でタイルのサイズが横800px
、縦600px
となります。+0+0
は余白なしということです)。
このような処理をNode.jsを使って行うプログラムを書きました。
ただし、PDFから生成された画像が10枚以上の場合、ファイルの名の所為で、montage
で結合を行うと10枚目~19枚目の画像が2枚目の画像の前に結合されてしまいます。
これでは不味いのでPDFから生成された画像が10枚以上ある場合には1枚目から9枚目までの画像のファイル名の連番部分の冒頭に0
を挿入するようにしました。
これで画像が10枚以上100枚未満の場合には対応できていますが、100枚以上の場合には対応できていないので注意してください(スライドの枚数が100枚以上になることは稀だと思うので100枚以上の場合には対応していません)。
あと、このプログラムを実行する前には同じフォルダにある画像ファイルは全て削除するか、どこか別の場所に移動してください。そうしないと、無関係の画像が結合されてしまうかもしれません(プログラムの最初に自動で削除するようにしても良いかもしれません)。
var childProcess = require('child_process');
var fs = require('fs');
if (process.argv.length < 3) {
console.error('lack argument.');
process.exit(1);
}
var tex = process.argv[2] + '.tex';
var dvi = process.argv[2] + '.dvi';
var pdf = process.argv[2] + '.pdf';
var pngs = process.argv[2] + '-*.png';
var png = process.argv[2] + '.png';
function pngn(n) {
return process.argv[2] + '-' + + n + '.png';
}
function pngn2(n) {
return process.argv[2] + '-0' + + n + '.png';
}
processPlatex(0);
function processPlatex(i) {
var platex = childProcess.spawn('platex', ['-guess-input-enc', '-interaction=nonstopmode', tex], { stdio: 'inherit' });
platex.on('close', function (code) {
if (i == 0) {
processPlatex(1)
}
else if (i == 1) {
processDvipdfmx();
}
else {
console.error('coding error.');
process.exit(1);
}
});
platex.on('error', function (err) {
console.error(err);
process.exit(1);
});
}
function processDvipdfmx() {
var dvipdfmx = childProcess.spawn('dvipdfmx', ['-f', 'ptex-ipaex.map', dvi], { stdio: 'inherit' });
dvipdfmx.on('close', function (code) {
processConvert();
});
dvipdfmx.on('error', function (err) {
console.error(err);
process.exit(1);
});
}
function processConvert() {
var convert = childProcess.spawn('convert', ['-density', '800', pdf, '-quality', '100', '-resize', '800', png], { stdio: 'inherit' });
convert.on('close', function (code) {
fs.stat(pngn(10), function (err, stats) {
if (!err) {
processRename(1);
}
else {
processMontage();
}
});
});
convert.on('error', function (err) {
console.error(err);
process.exit(1);
});
}
function processRename(i) {
if (i == 10) {
processMontage();
}
else {
fs.rename(pngn(i), pngn2(i), function (err) {
if (err) {
console.error(err);
process.exit(1);
}
else {
processRename(++i);
}
});
}
}
function processMontage() {
var montage = childProcess.spawn('montage', ['+frame', '+shadow', '+label', '-tile', '2x', '-geometry', '800x600+0+0', pngs, png], { stdio: 'inherit' });
montage.on('close', function (code) {
console.log('finished!!');
});
montage.on('error', function (err) {
console.error(err);
process.exit(1);
});
}