Perl
Perl 5Day 18

PerlでPDFにQRコード(画像)を埋め込む

More than 1 year has passed since last update.

記事を書いたことをないので経験がてら書いてみる。
初めての投稿なのでこうした方が等あれば教えてください。


環境

Perl 5.16.3
モジュール
GD http://search.cpan.org/~lds/GD-2.56/lib/GD.pm
Imager::QRCode http://search.cpan.org/~kurihara/Imager-QRCode-0.034/lib/Imager/QRCode.pm
PDF::API2 http://search.cpan.org/~ssimms/PDF-API2-2.030/lib/PDF/API2.pm
全部CPANでインストールできる。
CPANってやっぱいいよね!
cpan install ****でインストールできちゃう!

その他日本語フォントがない場合はIPAから以下をインストール
http://ipafont.ipa.go.jp/

PDFを作る

とりあえず、埋め込むPDFを作成する。

pdf.perl
# #!/usr/local/bin/perl
use strict;
use warnings;
use utf8;
use Encode;
use PDF::API2;
# PDFのモジュール
my $pdf = PDF::API2->new();
my $page = $pdf->page(); # ページ取得
my $txt = $page->text();

$txt->font( $pdf->ttfont("../.fonts/ipaexg.ttf") , 14 ); # フォントの設定
$txt->translate( "150","600"); # 座標が左下X0,Y0
$txt->text( "Perl 5 Advent Calendar 2016 12 18" );
$txt->translate( "150","580");
# 内部文字列じゃないとばける
$txt->text( "日本語フォントを指定してるので日本語もOK" );
$txt->translate( "150","560");
# お約束だけど注意
$txt->text( encode_utf8("日本語フォントを指定してるので日本語もOK") );
$pdf->saveas("/tmp/perl.pdf");

無題.jpg
内容のないPDFのできあがり

QRコードの作成

Imager::QRCodeを使えば日本語を使える
URLだけとかならGD::Barcodeでも大丈夫

qr.perl
use strict;
use warnings;
use utf8;
use feature qw/say/;
use Imager::QRCode;

eval {
    my $qrcode = Imager::QRCode->new(
        size          => 3,
        version       => 6,
        level         => 'M',
        casesensitive => 1,
        mode          => '8-bit',
        lightcolor    => Imager::Color->new( 255, 255, 255 ),
        darkcolor     => Imager::Color->new( 0, 0, 0 )
    );
    $qrcode->plot("パールでQRコードを生成")->write( file => "/tmp/qr1.jpg", type => "jpeg" );

};

作成した画像がこちら
qr1.jpg

やったね!

QRコードをPDFに埋め込む

merge.pl
#!/usr/local/bin/perl
use strict;
use warnings;
use utf8;
use feature qw/say/;
#use GD;
#use Imager::QRCode;
use Encode;
use PDF::API2;
# PDFのモジュール
my $pdf = PDF::API2->open("/tmp/perl.pdf");
my $page = $pdf->openpage(0); # ページ取得
my $txt = $page->text();

my $gd_img = $pdf->image_jpeg("/tmp/qr1.jpg");
my $gfx = $page->gfx();
# 画像の開始座標を左下から指定なので注意
$gfx->image( $gd_img, 250,540,100,100 );
$pdf->saveas("/tmp/perl.pdf");

image

くっつけるとこんな感じになる
面白みもナニもない感じ・・・?

ディスクを使わないでやってみる

qr_pdf.pl
#!/usr/local/bin/perl
use strict;
use warnings;
use utf8;
use feature qw/say/;
use GD;
use Imager::QRCode;
use Encode;
use PDF::API2;
# PDFのモジュール
my $pdf = PDF::API2->new();
my $page = $pdf->page(); # ページ取得
my $txt = $page->text();

$txt->font( $pdf->ttfont("../.fonts/ipaexg.ttf") , 14 ); # フォントの設定
$txt->translate( "150","700");
$txt->text( "Perl 5 Advent Calendar 2016 12 18" );

# お約束だけど注意
$txt->translate( "150","680");
$txt->text( "日本語フォントを指定してるので日本語もOK" );
$txt->translate( "150","660");
$txt->text( encode_utf8("日本語フォントを指定してるので日本語もOK") );


eval {
    my $qrcode = Imager::QRCode->new(
        size          => 3,
        version       => 6,
        level         => 'M',
        casesensitive => 1,
        mode          => '8-bit',
        lightcolor    => Imager::Color->new( 255, 255, 255 ),
        darkcolor     => Imager::Color->new( 0, 0, 0 )
    );
    my $qr_img;
    $qrcode->plot("http://yapcjapan.org/2017kansai/")->write( data => \$qr_img, type => "jpeg" );

   my $gd_img = $pdf->image_gd(GD::Image->new($qr_img));
   my $gfx = $page->gfx();
   $gfx->image( $gd_img, 250,540,100,100 );
};

$pdf->saveas("/tmp/perl.pdf");

出力結果

image

PDF::API2にはGD用のオブジェクトが用意されているのでメモリ上の展開のみで処理ができます。
これでインフラにディスク使っちゃだめ!って言われても対応できるよ!やったね!(涙)


今時Perlで帳票なんてやんねーよ!とかあるかもしれませんが
Perlでも出来ますよ!ってことを主張したかった。

むしゃくしゃしてやった、公開してやる!