差分表示
#freeze
*&date(Y-n-j[lL],2016/2/28); libharu を使ってjpg画像を右綴じpdfに変換
本の自炊で右綴じ化のために Acrobat を立ち上げるのは面倒で、他のフリーのpdfツールもたいていGUIで面倒そうで手頃なのが見つからないのでコマンドラインツールを作ってみることにした。
pdf作成で手頃そうなライブラリとして libharu(libhpdf.lib)というのがあったのでそれを採用... なんだけど、pdf 読込がよくわからず(出来ないのか出来ても面倒なのか...)。
もっとも jpg画像からpdf化に imagemagick を使ってるのだからその工程も自作ツールでやればよい話、と気づけばわりと簡単だった。(imagemagick では空白や日本語のあるファイル名の扱いに難ありだったし)
まず複数のjpgから1つのpdf生成するのは jpeg_demo.c あたりをいじって以下
#include <stdio.h>
#include <setjmp.h>
#include <hpdf.h>
static jmp_buf s_jmp_buf_env;
static void errorHandlerForHaru(HPDF_STATUS err, HPDF_STATUS detNo, void *udat) {
printf ("ERROR: err=%04X, detNo=%u\n", (HPDF_UINT)err, (HPDF_UINT)detNo);
longjmp(s_jmp_buf_env, 1);
}
int main (int argc, char *argv[]) {
if (argc < 2) {
printf("usage> jpg2pdf jpgfile(s).jpg ...\n");
return 1;
}
HPDF_Doc pdf = HPDF_New (&errorHandlerForHaru, NULL);
if (!pdf) {
printf ("error: cannot create PdfDoc object\n");
return 1;
}
if (setjmp(s_jmp_buf_env)) {
HPDF_Free (pdf);
return 1;
}
HPDF_SetCompressionMode (pdf, HPDF_COMP_ALL);
/*☆*/
for (size_t i = 1; i < argc; ++i) {
HPDF_Page page = HPDF_AddPage (pdf);
if (!page)
return 1;
HPDF_Image image = HPDF_LoadJpegImageFromFile(pdf, argv[i]);
if (!image) {
printf("load error %s\n", argv[i]);
return 1;
}
HPDF_REAL img_w = HPDF_REAL(HPDF_Image_GetWidth(image));
HPDF_REAL img_h = HPDF_REAL(HPDF_Image_GetHeight(image));
HPDF_Page_SetWidth (page, img_w);
HPDF_Page_SetHeight(page, img_h);
HPDF_Page_DrawImage (page, image, 0, 0, img_w, img_h);
}
HPDF_SaveToFile (pdf, "a.pdf");
HPDF_Free (pdf);
return 0;
}
コマンドライン引数で渡された jpgファイル(名) を順に突っ込んでるだけ。(コマンドライン引数なんで1オリジンだったり、出力ファイル名無精して a.pdf だったりするけれど)。
これだけで画像複数頁のpdfができちゃうので... ライブラリ、ありがたいです。
次に頁の開き方を設定。/*☆*/あたりに
HPDF_SetPageLayout(pdf, HPDF_PAGE_LAYOUT_TWO_PAGE_RIGHT);
を挿入。ここでは見開き奇数ページ始まりにしてみた。
で、右綴じ。これについては[[ここら>http://kb2.adobe.com/jp/cps/511/511204.html]]あたりをみて "ViewerPreferences" の Direction"に"R2L"を設定すりゃいいとのこと、libharuの HPDF_Catalog_SetViewerPreference が用途的にはそれなのだけど残念ながら"Direction"には未対応だったので見よう見まねで改造。
HPDF_STATUS addR2L(HPDF_Doc pdf) {
HPDF_Catalog catalog = pdf->catalog;
HPDF_Dict preferences = HPDF_Dict_New(catalog->mmgr);
if (!preferences)
return catalog->error->error_no;
HPDF_STATUS ret = HPDF_Dict_Add(catalog, "ViewerPreferences", preferences);
if (ret != HPDF_OK)
return ret;
ret = HPDF_Dict_AddName(preferences, "Direction", "R2L");
if (ret != HPDF_OK)
return ret;
return HPDF_OK;
}
というのを用意、/*☆*/ の位置に呼び出しの addR2L(pdf); を挿入でok。
タイトルと著者名は (これも /*☆*/付近)
HPDF_SetInfoAttr(pdf, HPDF_INFO_TITLE , "本のタイトル");
HPDF_SetInfoAttr(pdf, HPDF_INFO_AUTHOR, "著者名");
と用意されたもので楽ちん... なんだが日本語が化けてしまう。
日本語関係の設定が必要のようだ。jfont_demo.c 等いろいろみて
HPDF_UseJPEncodings(pdf);
HPDF_UseJPFonts(pdf);
HPDF_SetCurrentEncoder(pdf, "90msp-RKSJ-H");
を タイトルや著者を設定する前に記述しとく。~
(3行目の"90msp-RKSJ-H"指定は、HPDF_UseJPEncodings(pdf);内で設定されているモノからプロポーショナルなゴシック体を選んだ)~
これでacrobatのプロパティでタイトル&著者がちゃんと日本語で見れたので、めでたしめでたし、としておく。
※ ''HPDF_SetCurrentEncoder'' が肝、というか気づけずにここが一番苦労した。他のツールで生成したpdfとバイナリ見比べて、TitleやAuthorは7bit範囲はasciiだけどそれ以上だとUTF16(big endian)ベースになってるとか、utf8で別のxmlな記述スタイルになってるものとか... 結局utf16扱ってる処理から遡ってSetCurrentEncoderに行き着いた、と.
~
ということで、上記をもとに作ってみたコマンドラインツールは[[こちら>http://www.6809.net/tenk/html/lib/cnvToPdf-0.1b.zip]]。~
ということで、上記をもとに作ってみたコマンドラインツールは[[こちら>http://www.6809.net/tenk/html/lib/cnvToPdf-0.1c.zip]]。~
(※2/29追記: libharuビルド・バッチの不具合修正. exeは前と同じ)