2013年7月12日金曜日

TIFFからPDFへ変換するには・・・

ファイル変換はよくある話で、画像ファイルからPDFともなるとほぼ王道。
有償ソフトは別として、フリーソフトでも多種多様なものが提供されているのだが、決められたルールに従って大量にPDF化する様なソフトは見当たらないようだ。(見つけられないだけかも・・・)
いつもの通り、「なければ作ればいい」という精神で試みる。
さすがにPDF変換を1から構築するのは大変なので、ツールかライブラリを探してみると以下のようなものがあった。
Zipを解凍すると itextsharp.dll が現れるので、後ほど作成するプロジェクトフォルダにコピーしておけばいい。リファレンスヘルプは・・・まぁ、適当に。
itextsharp を使うには参照設定に登録する必要がある。
「ソリューションエクスプローラ」窓から「参照設定」を右クリックし、「参照の追加」を選択する。
「参照」タブから、iTextSharp.dll を選択することで、前準備が完了する。
 コーディングの基本形は以下の通り。
01.using iTextSharp.text;
02.using iTextSharp.text.pdf;
03. 
04.// itextsharp::ドキュメントを作成
05.Document doc = new Document();
06. 
07.// itextsharp::PDF保存先を指定
08.PdfWriter.GetInstance(doc, new FileStream(@"c:\hoge\test.pdf", FileMode.Create));
09. 
10.// itextsharp::PDFを開く
11.doc.Open();
12. 
13.// itextsharp::画像データ取得
14.iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(new Uri(@"c:\hoge\image.tif"));
15. 
16.// itextsharp::書込み
17.doc.Add(image);
18. 
19.// itextsharp::PDFを閉じる
20.doc.Close();
これだとA4サイズのTIFFファイルを上記のプログラムで作成すると、TIFF画像の一部しかPDF化されないことが分かる。
ちなみにA4サイズは、インチでいうと 8.3x11.5、mmで言うと 210x297 である。
で、TIFFファイルはあくまでも画像なので、用紙サイズなどの情報は保持せず、あくまで画像サイズなのだ。そのため、上記のプログラムでは端的に言うと解像度に比例して巨大化されてしまうのだ。
最終的には次のようになった。
01.using iTextSharp.text;
02.using iTextSharp.text.pdf;
03. 
04. 
05.{
06.    // ドキュメントを作成
07.    Document doc = new Document();
08. 
09.    // PDF保存先を指定
10.    PdfWriter.GetInstance(doc, new FileStream(@"c:\hoge\test.pdf", FileMode.Create));
11. 
12.    // PDFを開く
13.    doc.Open();
14. 
15.    // 画像データ取得
16.    iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(new Uri(@"c:\hoge\image.tif"));
17. 
18.    // サイズを算出
19.    // itextsharpのサイズ定義の数値が合わないので2.834の差分を補正
20.    float y = (image.PlainHeight / image.DpiY) * 25.4f * 2.834f;
21.    float x = (image.PlainWidth / image.DpiX) * 25.4f * 2.834f;
22. 
23.    // 用紙サイズを判定
24.    iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(myPaperSize(x, y));
25.                         
26.    // 縮尺率を判定
27.    // ※これでフィットするのだが理由は不明
28.    image.ScalePercent(35f);
29. 
30.    // 配置個所指定(左下が起点)
31.    image.SetAbsolutePosition(0f, 0f);
32. 
33.    // 用紙サイズを設定
34.    doc.SetPageSize(rect);
35. 
36.    // 書込み
37.    //doc.NewPage(); ←サイズが異なる複数頁のときにこの位置で頁変更をする
38.    doc.Add(image);
39. 
40.    // PDFを開く
41.    doc.Close();
42.}
43. 
44.private iTextSharp.text.Rectangle myPaperSize(float x, float y)
45.{
46.    // 誤差範囲10%とする
47.    // ※スキャン状態によって多少の誤差があるため
48.    float gosa = 0.9f;
49. 
50.    if (PageSize.A0.Height < (y * gosa)) return PageSize.B0;
51.    if (PageSize.B1.Height < (y * gosa)) return PageSize.A0;
52.    if (PageSize.A1.Height < (y * gosa)) return PageSize.B1;
53.    if (PageSize.B2.Height < (y * gosa)) return PageSize.A1;
54.    if (PageSize.A2.Height < (y * gosa)) return PageSize.B2;
55.    if (PageSize.B3.Height < (y * gosa)) return PageSize.A2;
56.    if (PageSize.A3.Height < (y * gosa)) return PageSize.B3;
57.    if (PageSize.B4.Height < (y * gosa)) return PageSize.A3;
58.    if (PageSize.A4.Height < (y * gosa)) return PageSize.B4;
59.    if (PageSize.B5.Height < (y * gosa)) return PageSize.A4;
60.    if (PageSize.A5.Height < (y * gosa)) return PageSize.B5;
61.    if (PageSize.B6.Height < (y * gosa)) return PageSize.A5;
62.    if (PageSize.A6.Height < (y * gosa)) return PageSize.B6;
63.    if (PageSize.B7.Height < (y * gosa)) return PageSize.A6;
64.    if (PageSize.A7.Height < (y * gosa)) return PageSize.B7;
65.    if (PageSize.B8.Height < (y * gosa)) return PageSize.A7;
66.    if (PageSize.A8.Height < (y * gosa)) return PageSize.B8;
67.     
68.    return PageSize.A8;
69.}
腑に落ちない部分も多々あるのだが、これでスキャンした用紙サイズのTIFFファイルを同用紙サイズのPDFファイルに変換することができる。

元ネタ
http://yonaizumi.dip.jp/weblog/cappe/2010/11/ctiffpdf.html

2 件のコメント:

  1. はじめまして。TIFからPDFへの変換で調べている中でこちらのページに辿り着きました。
    サイズ算出の箇所でサイズ定義に対する補正をかけていますが、TIFのDIPで割った後、PDFで標準的に使われている解像度の72をかけることで適正値になりました。
    float y = (image.PlainHeight / image.DpiY) * 72.0f
    また、縮尺率判定においても、上記倍率から算出することで適正縮尺になりました。
    image.ScalePercent(1.0f / image.DpiX * 72.0f * 100.0f)
    参考になれば幸いです。

    返信削除
  2. 指摘ありがとうございます。

    返信削除