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); を挿入。ここでは見開き奇数ページ始まりにしてみた。 で、右綴じ。これについてはここらあたりをみて "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");
を タイトルや著者を設定する前に記述しとく。 ※ HPDF_SetCurrentEncoder が肝、というか気づけずにここが一番苦労した。他のツールで生成したpdfとバイナリ見比べて、TitleやAuthorは7bit範囲はasciiだけどそれ以上だとUTF16(big endian)ベースになってるとか、utf8で別のxmlな記述スタイルになってるものとか... 結局utf16扱ってる処理から遡ってSetCurrentEncoderに行き着いた、と.
ということで、上記をもとに作ってみたコマンドラインツールはこちら。 |