2012年11月27日火曜日

Java帳票 iTextで高解像度の画像を印刷する

  • Javaの標準の印刷 (JPS) で画像を印刷する手段は一長一短
    利点 欠点
    java.awt.print.PrinterJob? どんなプリンタでも使える 解像度が72dpi
    javax.print.DocPrinterJob? 高解像度の印刷可能 プリンタドライバによっては、直接、画像を印刷できない
  • iTextで、高解像度の画像をPDFに貼り付けて印刷すれば上手くといいな

ソースコード 

  • 1000px x 1000px の画像を PDF に貼り付けた
  • 画像の解像度は img.scalePercent(float); で指定できる。 画像を縮小するとその分解像度が上がる
    縮尺(%) 解像度(dpi)
    100f 72dpi
    50f 144dpi
    25f 288dpi
    10f 720dpi
    5f 1440dpi
  • 無指定時は 72 dpi
  • 画像の大きさ(縦横の長さ)が小さくなっても画素情報は失われない。たとえば、 (1inch x 1inch) の (1000px x 1000px) の画像になる。



package com.snail.exam.printexam;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfWriter;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;

public class ITextExam3 {

    public static void main(String[] args) {
        try {

            OutputStream out = new FileOutputStream("/tmp/iTextExample3.pdf");
            //ByteArrayOutputStream out = new ByteArrayOutputStream();
           
            Document doc = new Document(PageSize.A4, 50, 50, 50, 50);
            PdfWriter pdfwriter = PdfWriter.getInstance(doc, out);

            Image img = createImage();

            doc.open();
           
            doc.add(new Phrase("72dpi\n\n"));
            doc.add(img);
           
            doc.newPage();
            img.scalePercent(50f);
            doc.add(new Phrase("144dpi\n\n"));
            doc.add(img);
           
            doc.newPage();
            img.scalePercent(25f);
            doc.add(new Phrase("288dpi\n\n"));
            doc.add(img);
           
            doc.newPage();
            img.scalePercent(10f);
            doc.add(new Phrase("720dpi\n\n"));
            doc.add(img);
           
            doc.newPage();
            img.scalePercent(5f);
            doc.add(new Phrase("1440dpi\n\n"));
            doc.add(img);
           
            // Document End
            doc.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
   
    private static Image createImage() throws IOException, BadElementException{
            BufferedImage image = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);

            Graphics2D g = image.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                    RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            g.setColor(Color.WHITE);
            g.fillRect(0, 0, image.getWidth(), image.getHeight());

            g.setColor(Color.GRAY);
            for (int x = 0; x < image.getWidth(); x += 5) {
                g.drawLine(x, 0, x, image.getHeight());
            }
            for (int y = 0; y < image.getHeight(); y += 5) {
                g.drawLine(0, y, image.getWidth(), y);
            }

            g.setColor(Color.BLACK);
            g.setFont(new java.awt.Font(java.awt.Font.SANS_SERIF, java.awt.Font.PLAIN, 24));
            g.drawString("20pt 123 ABC あいう アイウ", 0, 20);

            g.setFont(new java.awt.Font(java.awt.Font.SANS_SERIF, java.awt.Font.PLAIN, 10));
            g.drawString("10pt 123 ABC あいう アイウ", 0, 40);

            g.setFont(new java.awt.Font(java.awt.Font.SANS_SERIF, java.awt.Font.PLAIN, 8));
            g.drawString("8pt 123 ABC あいう アイウ", 0, 60);
           
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(image, "png", out);
           
            return com.itextpdf.text.Image.getInstance(out.getBytes()); 
    }
}

IText Image オブジェクト

iText は、さまざまなイメージフォーマット(いくつかのフォーマットはイメージに限定されていません)をサポートしています。
  • JPEG: Joint Photographic Experts Group. 非可逆な圧縮法として一般的に使われており、96%程度サイズを圧縮する。Web に写真を掲載するためにはもっとも優れている。
  • GIF: Graphic Interchange Format. イメージファイルの共通フォーマット、特にイメージの多くの部分が同じ色の場合に使われる。単純なイメージの GIF フォーマットファイルは、JPEG フォーマットのものよりも小さくなることが多いですが、写真は JPEG のようには保存されません。
  • PNG: Portable Network Graphics. GIFの後継フォーマットとしてデザインされた。GIF のように、圧縮、透過、プログレッシブローディングをサポートしており、特許の制約からフリーです。
  • TIFF: Tagged Image File Format. デジタルスキャナで取り込まれたイメージのための共通フォーマットとして使われている。
  • BMP: Windows bitmap. Microsoft Windows においてビットマップファイルの共通フォーマット。他のオペレーティングシステムでは、色に関する事項は十分にはサポートされていない。
  • WMF:  Windows Metafile Format. Windows コンパチブルコンピュータのベクタグラフィックスフォーマットであり、ワードプロセッサのクリップアートとしてよく使われる。
  • EPS の基本的な機能:  Encapsulated PostScript. PostScript 言語においてイメージを記述するためのフォーマット。
  • java.awt.Image: JAVA オブジェクト。SUNのJDKに含まれている。
  • com.lowagie.text.pdf.PdfTemplate: PdfTemplate で定義された PDF 文は、Image のなかにラップすることができます。
  • com.lowagie.text.pdf.Barcode: 抽象クラスです。どのようなバーコードがサポートされているかは、実装クラスを参照してください。
Image インスタンスは、getInstance メソッドのうちのひとつを使って作成されます。Image は抽象クラスなので、getInstance メソッドは、与えられたイメージの型 (Jpeg、WMFなど) を判断し、それに従ったオブジェクト (JpegImgWMFなど) を返します。多くのPDFライブラリは、イメージを復号してPDFにする前に、ビットマップのようなフォーマットに変換してしまいます。このアプローチは、生成されるPDFが非常に大きくなってまうので、iText ではこのような方法をとっていません。ほかのライブラリでは、もとのファイルサイズの 10倍 にもなってしまうこともありますが、iText ではそんなことにはなりません。同一の Image は、再利用されます (Image XObject はひとつしかありません) 。
Example: java com.lowagie.examples.objects.images.Images
Adds different formats of images to a document.: see Images.pdf
External resources for this example: otsoe.jpg iText.bmp pngnow.png iText.tif getacro.gifiText.wmf

Image インスタンスを得るもっとも普通の方法は、ファイルのパス (getInstance(java.lang.String)) か URL (getInstance(java.net.URL)) を使う方法ですが、Raw イメージデータ (例えば、データベースにイメージデータが格納されている場合など) から作成することもできます。

Example: java com.lowagie.examples.objects.images.RawData
Using raw image data to construct an Image object.: see rawdata.pdf
External resources for this example: otsoe.jpg
iText は、JAVA のライブラリなので、java.awt.Image オブジェクトもサポートしています。しかし、この機能を UNIX/Linux システムで使うときには気をつけてください。java.awt.Image をインスタンス化するための、java.awt.Toolkit を使うときには、特別な X Window が必要です。com.lowagie.text.Image に固執すれば、ほかに必要なものはなくなります。com.lowagie.text.Image は、どのプラットフォームでも利用できます。
Example: java com.lowagie.examples.objects.images.AwtImage
Using a java.awt.Image object to construct an Image object.: see awt_image.pdf
External resources for this example: H.gif
先頭に戻る
イメージの配置
イメージの配置は、setAlignment(int) によって設定できます。パラメータとして、意味が自明な定数 LEFTRIGHT あるいは MIDDLE をとることができます。
Example: java com.lowagie.examples.objects.images.Alignment
Alignment of images.: see alignment.pdf
External resources for this example: vonnegut.gif otsoe.jpg hitchcock.png
これらの定数とともに、 TEXTWRAP  UNDERLYING 定数も組み合わせることができます。最初の定数は、テキストをイメージの周りに配置し、二番目の定数は、テキストはイメージの上に配置されます。どちらの定数も、次の例で、示されています。
Example: java com.lowagie.examples.objects.images.ImagesAlignment
Alignment and wrapping of images.: see imagesAlignment.pdf
External resources for this example: vonnegut.gif otsoe.jpg hitchcock.png
イメージの絶対位置が指定されていないときには、iText は、現在のポインタに配置しようとします。しかし、イメージを加えるために必要な空間がない場合もあります。そのような場合、iText はイメージを加えることを延期し、ほかのコンテンツを先に加えます。イメージを add メソッドを呼び出したそのときに加えたいときには、Writer に正確な順序でイメージを配置することを設定しなければなりません。
writer.setStrictImageSequence(true);
例で、iTextの既定の振る舞いと、正確な順序でイメージを配置することを設定した場合の違いを見てください。
Example: java com.lowagie.examples.objects.images.ImageSequence
Adds images to a document, once respecting the order in which they were added, once in the default order.: see inSequence.pdf NotInSequence.pdf
External resources for this example: otsoe.jpg getacro.gif
先頭に戻る
イメージの変換
ほかのコンテンツにかかわりなく、イメージをページ上の絶対位置に加えることができます。座標系座標系の章において、変換行列の仕組みについて詳しく説明しますが、それは詳しすぎるものでしょう。通常使われる、拡大、縮小、単純な回転などの単純な操作には、そのような計算が必要になることはほとんどありません。

変換
座標系について知っておかなければならないことは、原点が左下にあるということです。etAbsolutePosition(float, float) メソッドのパラメータは、イメージの左下を定義します。
Example: java com.lowagie.examples.objects.images.AbsolutePositions
Adding an Image at absolute positions.: see absolutepositions.pdf
External resources for this example: hitchcock.png
スケーリング(拡大・縮小)
イメージの大きさを指定してスケーリングをするときには、scaleAbsolute[Width|Height] メソッドを使います。ある割合 (パーセント) でスケーリングするときは、scalePercent メソッドを使います。
既定では、スケーリングされていないイメージは、解像度が 72dpi と扱われることに注意。50% でスケーリングされたイメージでは、144 になります。小さくスケーリングされたイメージは、ピクセルの大きさが小さくなるので、解像度は大きくなりますを、300dpi で出力したいときには、72/300=24% のスケーリングを使います。例えば、24% (72/300 = 0.24) のスケーリングで 1500X1500 ピクセル (5X300 = 1500) のイメージを PDF へ配置すると、PDF 中では、1500X1500 ピクセル が 5X5 inch となり解像度が 300dpi のイメージとなります。サイズがどうあろうとも、そのイメージはいつでも 1500X1500 ピクセルです。
Example: java com.lowagie.examples.objects.images.Scaling
Scaling images.: see scaling.pdf
External resources for this example: otsoe.jpg
ほかに、使いでのあるメソッドとして、scaleToFit があります。このメソッドは、イメージを四角形に合うようにスケーリングしますが、XY の比は保持します。次の例の権利は、私自身が所有しているものではありません。www.bigfoto.com に感謝。
Example: java com.lowagie.examples.objects.images.DvdCover dvdcover.pdf My Sunflower Movie 808080 sunflower-front.jpg sunflower-back.jpg
Make a DVD Cover.: see dvdcover.pdf
External resources for this example: sunflower-front.jpg sunflower-back.jpg
回転
イメージは、 setRotation(float) (角度はラジアン) あるいは setRotationDegrees(float) (角度は度) メソッドのうちのひとつで回転ができます。
Example: java com.lowagie.examples.objects.images.Rotating
Rotating images.: see rotating.pdf
External resources for this example: otsoe.jpg
先頭に戻る
特別な機能
クリック可能なイメージ
クリック可能なイメージやイメージに注釈を加えたいときは、Annotation オブジェクトを構築し、それをイメージに加えなければならない。位置は、必ずしも指定する必要はない (0, 0, 0, 0 でもよい)。位置は、内部でイメージに合うように変換される。setAnnotation(com.lowagie.text.Annotation) メソッドと注釈の章を参照ください。
Example: java com.lowagie.examples.objects.images.AnnotatedImage
images and annotations.: see annotated_images.pdf
External resources for this example: otsoe.jpg iText.wmf
Chunk 中のイメージ
In some cases it can be handy to wrap an image inside a . Just create a Chunk with an image and an offset with one of the Chunk constructors that take an Image as parameter. 場合によっては、イメージをChunk 中に入れることによってそれをラップすることもできます。Image をパラメータとしてとる Chunk のコンストラクタによってイメージとそのオフセットを保持する Chunk を作成するだけです。
Example: java com.lowagie.examples.objects.images.ImageChunks
Images wrapped in a Chunk.: see imageChunks.pdf
External resources for this example: pngnow.png
イメージマスク
ほかのイメージの透過性を指定するマスクとして使われる Image を作成することができます。
3C
7E
E7
C3
C3
E7
7E
3C
このイメージは、たて8ピクセル、横8ピクセル、1コンポーネントで、コンポーネントあたり1バイトです。makeMask() メソッドを使うことにより、このイメージはマスクになります。
byte maskr[] =     {(byte)0x3c,      (byte)0x7e,      (byte)0xe7,      (byte)0xc3,      (byte)0xc3,      (byte)0xe7,      (byte)0x7e,      (byte)0x3c};  Image mask = Image.getInstance(8, 8, 1, 1, maskr);  mask.makeMask();  mask.setInvertMask(true);
このマスクを、イメージの一部をクリップするための明示的なマスクとして利用できます。
PdfContentByte cb = writer.getDirectContent();  Image image = Image.getInstance("vonnegut.gif");  image.setImageMask(mask);
色とパタンの章では、ステンシルマスクの概念について論じます。Image から作成したマスクは、このようにステンシルマスクにも使えます。
PdfContentByte cb = writer.getDirectContent();  cb.setRGBColorFill(255, 0, 0);  cb.addImage(mask, mask.scaledWidth() * 8, 0, 0, mask.scaledHeight() * 8, 100, 400);
 (addImage メソッドについては、座標系などについての知識も必要です。。)
Example: java com.lowagie.examples.objects.images.ImageMasks
Applying a mask to an image.: see maskedImages.pdf
External resources for this example: otsoe.jpg