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に行き着いた、と.
ということで、上記をもとに作ってみたコマンドラインツールはこちら。
2016-3-27[日] 2TBオーバーのHDDへのWindows10インストールSATAが2ポートしかないN3150Bのdisk容量アップのためSSD512GB(Win8.1)を6TB(弱)のHDDにクローン、ついでにWin10へアップグレード。まずまず良好、と思いきや Cドライブのパーティションの直後に450MBほどの回復パーティションが作られていた。HDDのクローンで時短のためCドライブサイズ減らしたままだったので非常に困ってしまう。
しかたないので更地インストールし直すことに。
(win10は良くも悪くもハード構成一度認証してしまえば再インストールでproductキーの入力必要ないとのことなので多少 気が楽) usbメモリからboot、概ね今までのwindows同様の手順で、HDDの選択にて全部のパーティションを一旦全部削除したところ、あれれ、未使用領域が2TBと4TB弱に分かれてる……2TBのほうは新規でフォーマット可能だけれど4TB弱のほうはエラー。ヘンに思いつつとりあえず2TBのほうにインストール。難なくOSインストールは済んだけれど、「ディスクの管理」で4TB弱の未使用パーティションは見えるけれど使用可能にすることが出来ない。 ググるとMBRでフォーマットした時の挙動のようだ。ここ数年bootドライブはSSDにして2TBオーバーなディスクにインストールしたことなかったので この手の事情 すっかり失念していた。GPTでインストールするには64bitOSでUEFIなBIOS必須、といっても今時のMBなら満たしてる。N3150Bも満たしてる……何か設定忘れてるんだろうな。 結論としては、DVDなりUSBメモリなりのwindowsインストールメディアを装着した状態でPCのBIOS画面にて最初にbootするドライブとして"UEFI:"が付いたモノを設定すればよい模様。
うち(N3150B)の場合、BIOSの"起動"の頁で、 起動装置 #1 に "UEFI: (USBメモリ名)" を設定、念の為 "USB:(USBメモリ名)" は無効にした。この状態でusbメモリからbootしてインストール開始すると、ちゃんと 6TB HDDを好きなようにパーティション分けできて osインストールも無事終了。 (わかれば他愛ないことだけど、手間取ったし、数年後にまたハマるかもしれないので、メモ書き)
2016-8-3[水] windows10 でスクリーンキーボードが勝手に出て鬱陶しいwindows10 にアップグレードしたマシンによってスクリーンキーボードが勝手に出るものがあった。出ないものもある。「設定」の「キーボード」ではどれも「スクリーンキーボード」offになってるのに... 結論からいえば、コントロールパネル側の簡単設定でもスクリーンキーボードのon/offが別途あり有効になっていた模様。 どうも古い仕組みと新しい仕組みが統合されてなかったのね。 と、いうことで覚書。
2016-9-3[土] opencvのコンパイルopencvを使ってみたいけれど、公式配布のwin用バイナリは vs12,vs14 用 dll 版だけのようで個人的に好みでないのでソースをビルドしてみることに。
CMake を使う模様。てことで、慣れてない CMake 使用のメモ書き。
CMakeでソース環境外でビルドするには、まずビルド用フォルダ用意して そこをカレントにする必要があるらしい。 cd \opencv-3.1.0 md build cd build そして CMake -G "Visual Studio 12 2013 Win64" -DBUILD_SHARED_LIBS=0 ..\ とすれば vs12 x64用 staticライブラリ(/Mt)版の sln 環境が生成され、生成された OpenCV.sln でビルドすれば .lib 群の出来上がり、と。
引数の ..\ は、ソース環境の基準となるディレクトリ位置の指定。ソース外ビルドするときは必須。 オプション -G は生成するビルドシステム(コンパイラ) の指定。どういう指定があるかは CMake --helpで確認。vs9 x86用なら "Visual Studio 9 2008" な具合。(CMake の運用では x86用と x64用とで sln(vc(x)proj) を別々に生成するのが普通ってことのよう) オプション -D でopencv固有の BUILD_SHARED_LIBS を off にすることで dll(shared)ライブラリを止める指定になる。(つまりデフォルトはshared) opencvビルドオプションはイッパイあり、opencv-3.1.0/直下の CMakeLists.txt の中を覗けば 説明付きでずらっと並んでるのでそれらを確認。
CMake -G "Visual Studio 12 2013 Win64" -DBUILD_SHARED_LIBS=0 -DBUILD_WITH_STATIC_CRT=0 ..\ ※ .lib .exeごとに vcxproj があって数が多いので、とても手作業で コンパイルオプションを設定し直す気になれないで、CMakeで生成し直しとなる。
-DWITH_CUDA=0 -DWITH_CUFFT=0 -DBUILD_CUDA_STUBS=0
を加えたりもした。 -DWITH_OPENCL=0 -DWITH_OPENCL_SVM=0 -DWITH_OPENCLAMDFFT=0 -DWITH_OPENCLAMDBLAS=0 を付ければよい、のだけど、こちらについては付けなくても問題なさそうだった。 その他 sample\をビルドしたければ -DBUILD_EXAMPLES=1 付けたり、逆にテスト関係不要ならば -DBUILD_TESTS=0 -DBUILD_PERF_TESTS=0 を付けたり、このへんはお好みで。
vc9(vc8) については、コンパイルできる.libも多いけれど、ソースで stdint.h が使われているライブラリもあってそれらがアウトだったり、OpenCL関係やvideoio関係がアウトなので、公式には未対応コンパイラの模様。
2016-11-19[土] C++TemplateのつもりでC#Generics使ってハマる(初歩)
人様のソース改修でロクに知らないC#をここ1,2ヶ月さわってた。 C++だと
#include <stdio.h> class Foo { public: void Run() { printf("Foo!"); } }; template<class T> class FooMgr { public: void Run() { T().Run(); } }; class Bar : public Foo { public: void Run() { printf("Bar!"); } }; class BarMgr : public FooMgr<Bar> { }; int main() { BarMgr barMgr; barMgr.Run(); } で "Bar!!" と出力されるようなつもりで
class Foo { public void Run() { System.Console.Write("Foo!"); } } class FooMgr<T> where T : Foo, new() { public void Run() { (new T()).Run(); } } class Bar : Foo { public new void Run() { System.Console.Write("Bar!!"); } } class BarMgr : FooMgr<Bar> { } class Test { public static void Main() { BarMgr barMgr = new BarMgr(); barMgr.Run(); } } のように書いてみたところ、実行したら "Foo!" が出力される、と。
初歩的な勘違いバグの類で、C# Generics って C++ Template ほど Macro的な強力さはなくて、この場合 継承class のラッパー的なモノでしかないのね。
where T : Foo で継承的な記述からとっとと気づけよなんだけど、ググって見よう見まね、要求を書いてるだけのつもりになってた。
class Foo { public virtual void Run() { System.Console.Write("Foo!"); } } class FooMgr<T> where T : Foo, new() { public void Run() { (new T()).Run(); } } class Bar : Foo { public override void Run() { System.Console.Write("Bar!!"); } } class BarMgr : FooMgr<Bar> { } class Test { public static void Main() { BarMgr barMgr = new BarMgr(); barMgr.Run(); } } どうせbase側からアクセスしないのだからと無精してTemplate使いたかったわけで多少本末転倒な気分もあるのだけれど、実作業では結局virtualすべき多態な事案になってしまったのでコレはコレでよしとしとく。 ※も1つアホだったのは、new で継承元メソッド上書きしてたものだから、後から根本を virtual に変えても orverrideすべきものがnewのままでコンパイル通っちゃってハマるワナ
|