qunitamaのモノづくりブログ

レザークラフトなど、モノづくりのブログです

Goodnotes5 テンプレート生成スクリプト【高速版】

Goodnotesテンプレート生成Perlスクリプトですが課題を抱えていましたので作り直しました。

今までの課題

  • 遅い
  • 描画処理の重複(全てのスクリプトに同じ処理を書いている)

対策

  • ImageMagickはモジュール版を使う
  • 描画処理を外だしする

注意事項

  • 実行は自己責任でお願いします。

Perlスクリプト

共通描画処理(mtdraw.pl)

描画処理の共通ライブラリですので、各スクリプトと同じフォルダ(ディレクトリ)に設置して下さい。
※Noteshelf2のライブラリと同じものです。

# ---------------------------------------------------------------------
# Library for Template Create Script
# File Name mtdraw.pl
# Copyright (c) 2020 qunitama. All rights reserved.
# ---------------------------------------------------------------------
use utf8;
use Image::Magick;
package mtdraw;
# ---------------------------------------------------------------------
# --- 固定値 変更不要
# ---------------------------------------------------------------------
$MM_PER_IN = 25.4; # 1インチは25.4mm

# ---------------------------------------------------------------------
# --- 出力PDFのDPIを指定
# ---------------------------------------------------------------------
$DPI = 300;

# ---------------------------------------------------------------------
# --- 描画ルーチン *基本的には変更不要
# ---------------------------------------------------------------------

# ---------------------------------------------------------------------
# 名前       create_paper_mm
# 処理       用紙を生成
# パラメータ
#   $xmm 用紙サイズ(横)(mm)
#   $ymm 用紙サイズ(縦)(mm)
#   $col 用紙の色
#   $bai 倍率を指定
#        用紙サイズ及びDPIから実寸サイズを計算して用紙を生成すると、
#        書いた時に線が太いので、本倍率で用紙を拡大
# ---------------------------------------------------------------------
sub create_paper_mm {
    my ($xmm,$ymm,$col,$bai) = @_;

    $PDF_X_MM = $xmm;
    $PDF_Y_MM = $ymm;
    $BAIRITSU = $bai;

    $img = Image::Magick->new();

    my $size = sprintf("%dx%d",z($PDF_X_MM),z($PDF_Y_MM));
    $img->Set(size=>"$size");

    my $color = sprintf("xc:%s",$col);
    $img->Read("$color");
}
# ---------------------------------------------------------------------
# 名前       line
# 処理       線を描画
# パラメータ
#   $x1    始点(X)指定(mm)
#   $y1    始点(Y)指定(mm)
#   $x2    終点(X)指定(mm)
#   $y2    終点(Y)指定(mm)
#   $col   線の色
#   $width 線の幅
# ---------------------------------------------------------------------
sub line {
    my ($x1,$y1,$x2,$y2,$col,$width) = @_;

    my $zahyou = sprintf("%d,%d %d,%d",z($x1),z($y1),z($x2),z($y2));

    $img->Draw(
        primitive=>'line',
        points=>"$zahyou",
        stroke=>"$col",
        strokewidth=>$width);
}
# ---------------------------------------------------------------------
# 名前       tatesen
# 処理       縦線をn本等間隔に描画
# パラメータ
#   $x       始点(X)指定(mm)
#   $y       始点(Y)指定(mm)
#   $takasa  高さ指定(mm)
#   $col     線の色
#   $width   線の幅
#   $kankaku 線の間隔
#   $honsuu  本数
# ---------------------------------------------------------------------
sub tatesen {
    my ($x,$y,$takasa,$col,$width,$kankaku,$honsuu) = @_;

    for($i=0;$i<$honsuu;$i++){
        line(
            $x+$kankaku*$i,$y,
            #$x+$kankaku*$i,$y+$takasa-1,
            $x+$kankaku*$i,$y+$takasa,
            $col,$width);
    }
}
# ---------------------------------------------------------------------
# 名前       yokosen
# 処理       横線をn本等間隔に描画
# パラメータ
#   $x       始点(X)指定(mm)
#   $y       始点(Y)指定(mm)
#   $haba    幅指定(mm)
#   $col     線の色
#   $width   線の幅
#   $kankaku 線の間隔
#   $honsuu  本数
# ---------------------------------------------------------------------
sub yokosen {
    my ($x,$y,$haba,$col,$width,$kankaku,$honsuu) = @_;

    for($i=0;$i<$honsuu;$i++){
        line(
            $x,$y+$kankaku*$i,
            #$x+$haba-1,$y+$kankaku*$i,
            $x+$haba,$y+$kankaku*$i,
            $col,$width);
    }
}
# ---------------------------------------------------------------------
# 名前       dot
# 処理       ドットを描画
# パラメータ
#   $x       中心点(X)指定(mm)
#   $y       中心点(Y)指定(mm)
#   $r       半径指定(mm)
#   $col     線の色
# ---------------------------------------------------------------------
sub dot {
    my ($x,$y,$r,$col) = @_;

    my $wkx1=int(z($x));
    my $wkx2=$wkx1+z($r);

    my $zahyou = sprintf("%d,%d %d,%d",$wkx1,z($y),$wkx2,z($y));
    $img->Draw(
        primitive=>'circle',
        points=>"$zahyou",
        fill=>"$col");
}
# ---------------------------------------------------------------------
# 名前       text
# 処理       テキストを描画
# パラメータ
#   $x       指定(X)指定(mm)
#   $y       指定(Y)指定(mm)
#   $font    フォント指定
#   $col     線の色
#   $size    フォントサイズ(≒mm)
#   $text    描画テキスト
# ---------------------------------------------------------------------
sub text {
    my ($x,$y,$font,$col,$size,$text) = @_;

    $geo = sprintf("+%d+%d",z($x),z($y));
    $sz = $size * 14 * $BAIRITSU;

    $img->Annotate(
        text=>$text,
        gravity=>'NorthWest',
        geometry=>"$geo",
        font=>$font,
        fill=>"$col",
        pointsize=>"$sz");
}
# ---------------------------------------------------------------------
# 名前       box
# 処理       箱を描画
# パラメータ
#   $x       始点(X)指定(mm)
#   $y       始点(Y)指定(mm)
#   $haba    幅指定(mm)
#   $takasa  高さ指定(mm)
#   $col     線の色
#   $width   線の幅
# ---------------------------------------------------------------------
sub box {
    my ($x,$y,$haba,$takasa,$col,$width) = @_;

    my $zahyou = sprintf("%d,%d %d,%d",z($x),z($y),z($x+$haba),z($y+$takasa));

    $img->Draw(
        primitive=>'Rectangle',
        points=>"$zahyou",
        fill=>'none',
        stroke=>"$col",
        strokewidth=>$width);
}
# ---------------------------------------------------------------------
# 名前       make_pdf
# 処理       PDFファイルを生成
# パラメータ
#   $fn      ファイル名
# ---------------------------------------------------------------------
sub make_pdf {
    my ($fn) = @_;

    if ( -e $fn ) {
        binmode(STDERR, ":utf8");
        print STDERR "$fn は既に存在します\n";
        undef $img;	
        exit(1);
    }

    binmode(STDOUT);

    my $density = sprintf("%dx%d",$DPI,$DPI);

    $img->Set(density=>"$density");

    $img->Write($fn);

    undef $img;

    exit(0);
}
# ---------------------------------------------------------------------
# 名前       z
# 処理       mm to pixel変換
# パラメータ
#   $mm      座標(mm)
#   戻り値   座標(Pixel)
# ---------------------------------------------------------------------
sub z {
    my ($mm) = @_;
    return $DPI / $MM_PER_IN * $mm * $BAIRITSU;
}

1;

ドット用紙

#!/usr/bin/perl
use utf8;
require("./mtdraw.pl");

# ---------------------------------------------------------------------
# Template Create Script for Note Application
# File Name make_gn_template_dot.pl
# Copyright (c) 2019 qunitama. All rights reserved.
# ---------------------------------------------------------------------

# ---------------------------------------------------------------------
# --- 色,太さ,FONT 指定
# ---------------------------------------------------------------------
$PAPER_COLOR      = "#FAFBFB";

# 色定義
$COL_USU = "#9FA0A0";  # 薄目
$COL_KOI = "#544A47";  # 濃目
$COL_RED = "#d7003a";  # 赤
$COL_BLU = "#007bbb";  # 青

# 線幅定義
$WID_HOS = "1"; # 細
$WID_CHU = "2"; # 中
$WID_FUT = "3"; # 太

# FONTを指定
$FONT =	"/cygdrive/c/Windows/Fonts/BIZ-UDGothicR.ttc";

# 機種:iPad mini アプリ:Goodnotes --> 120x136 倍率 1.6
# 機種:iPad mini アプリ:Noteshelf --> 120x150 倍率 2.4
$PDF_X_MM = 120;
$PDF_Y_MM = 136;
$BAIRITSU = 1.6;
$PDF_FILE = 'GN_dot.pdf';

# ---------------------------------------------------------------------
# --- 用紙生成処理
# ---------------------------------------------------------------------

# 用紙生成

&mtdraw::create_paper_mm(
    $PDF_X_MM,$PDF_Y_MM,$PAPER_COLOR,$BAIRITSU);

# dot 描画

$bs = 5; # 基準間隔 5mm

for($y=$bs;$y<=135;$y+=$bs){
    for($x=$bs;$x<=115;$x+=$bs){
        &mtdraw::dot(
            $x,$y,0.18,
            $COL_USU);
    }
}

# PDFに変換

&mtdraw::make_pdf($PDF_FILE);

5mm方眼用紙

#!/usr/bin/perl
use utf8;
require("./mtdraw.pl");

# ---------------------------------------------------------------------
# Template Create Script for Note Application
# File Name make_gn_template_grid.pl
# Copyright (c) 2019 qunitama. All rights reserved.
# ---------------------------------------------------------------------

# ---------------------------------------------------------------------
# --- 色,太さ,FONT 指定
# ---------------------------------------------------------------------
$PAPER_COLOR      = "#FAFBFB";

# 色定義
$COL_USU = "#9FA0A0";  # 薄目
$COL_KOI = "#544A47";  # 濃目
$COL_RED = "#d7003a";  # 赤
$COL_BLU = "#007bbb";  # 青

# 線幅定義
$WID_HOS = "1"; # 細
$WID_CHU = "2"; # 中
$WID_FUT = "3"; # 太

# FONTを指定
$FONT =	"/cygdrive/c/Windows/Fonts/BIZ-UDGothicR.ttc";

# 機種:iPad mini アプリ:Goodnotes --> 120x136 倍率 1.6
# 機種:iPad mini アプリ:Noteshelf --> 120x150 倍率 2.4
$PDF_X_MM = 120;
$PDF_Y_MM = 136;
$BAIRITSU = 1.6;
$PDF_FILE = 'GN_grid.pdf';

# ---------------------------------------------------------------------
# --- 用紙生成処理
# ---------------------------------------------------------------------

# 用紙生成

&mtdraw::create_paper_mm(
    $PDF_X_MM,$PDF_Y_MM,$PAPER_COLOR,$BAIRITSU);

# grid 描画

$bs = 5; # 基準間隔 5mm

# 罫線描画(縦線)

&mtdraw::tatesen(
    $bs,0,$PDF_Y_MM,$COL_USU,$WID_HOS,$bs,23);

# 罫線描画(横線)

&mtdraw::yokosen(
    0,$bs,$PDF_X_MM,$COL_USU,$WID_HOS,$bs,27);

# PDFに変換

&mtdraw::make_pdf($PDF_FILE);

グラフ用紙

#!/usr/bin/perl
use utf8;
require("./mtdraw.pl");

# ---------------------------------------------------------------------
# Template Create Script for Note Application
# File Name make_gn_template_graph.pl
# Copyright (c) 2019 qunitama. All rights reserved.
# ---------------------------------------------------------------------

# ---------------------------------------------------------------------
# --- 色,太さ,FONT 指定
# ---------------------------------------------------------------------
$PAPER_COLOR      = "#FAFBFB";

# 色定義
$COL_USU = "#9FA0A0";  # 薄目
$COL_KOI = "#544A47";  # 濃目
$COL_RED = "#d7003a";  # 赤
$COL_BLU = "#007bbb";  # 青

# 線幅定義
$WID_HOS = "1"; # 細
$WID_CHU = "2"; # 中
$WID_FUT = "3"; # 太

# FONTを指定
$FONT =	"/cygdrive/c/Windows/Fonts/BIZ-UDGothicR.ttc";

# 機種:iPad mini アプリ:Goodnotes --> 120x136 倍率 1.6
# 機種:iPad mini アプリ:Noteshelf --> 120x150 倍率 2.4
$PDF_X_MM = 120;
$PDF_Y_MM = 136;
$BAIRITSU = 1.6;
$PDF_FILE = 'GN_graph.pdf';

# ---------------------------------------------------------------------
# --- 用紙生成処理
# ---------------------------------------------------------------------

# 用紙生成

&mtdraw::create_paper_mm(
    $PDF_X_MM,$PDF_Y_MM,$PAPER_COLOR,$BAIRITSU);

# graph 描画

$bs  = 1; # 基準間隔 1mm
$bsf = 5; # 太線間隔 5mm

# 罫線描画(細線)

&mtdraw::tatesen(
    $bs,0,$PDF_Y_MM,$COL_USU,$WID_HOS,$bs,119);

&mtdraw::yokosen(
    0,$bs,$PDF_X_MM,$COL_USU,$WID_HOS,$bs,135);

# 罫線描画(横線)

&mtdraw::tatesen(
    $bsf,0,$PDF_Y_MM,$COL_USU,$WID_CHU,$bsf,23);

&mtdraw::yokosen(
    0,$bsf,$PDF_X_MM,$COL_USU,$WID_CHU,$bsf,27);

# PDFに変換

&mtdraw::make_pdf($PDF_FILE);

Weekly Schedule

#!/usr/bin/perl
use utf8;
require("./mtdraw.pl");

# ---------------------------------------------------------------------
# Template Create Script for Note Application
# File Name make_gn_template_weekly.pl
# Copyright (c) 2019 qunitama. All rights reserved.
# ---------------------------------------------------------------------

# ---------------------------------------------------------------------
# --- 色,太さ,FONT 指定
# ---------------------------------------------------------------------
$PAPER_COLOR      = "#FAFBFB";

# 色定義
$COL_USU = "#9FA0A0";  # 薄目
$COL_KOI = "#544A47";  # 濃目
$COL_RED = "#d7003a";  # 赤
$COL_BLU = "#007bbb";  # 青

# 線幅定義
$WID_HOS = "1"; # 細
$WID_CHU = "2"; # 中
$WID_FUT = "3"; # 太

# FONTを指定
$FONT =	"/cygdrive/c/Windows/Fonts/BIZ-UDGothicR.ttc";

# 機種:iPad mini アプリ:Goodnotes --> 120x136 倍率 1.6
# 機種:iPad mini アプリ:Noteshelf --> 120x150 倍率 2.4
$PDF_X_MM = 120;
$PDF_Y_MM = 136;
$BAIRITSU = 1.6;
$PDF_FILE = 'GN_weekly.pdf';

# ---------------------------------------------------------------------
# --- 用紙生成処理
# ---------------------------------------------------------------------

# 用紙生成

&mtdraw::create_paper_mm(
    $PDF_X_MM,$PDF_Y_MM,$PAPER_COLOR,$BAIRITSU);

# grid 描画

$bs = 5; # 基準間隔 5mm

# 罫線描画(縦線)

&mtdraw::tatesen(
    $bs,0,$PDF_Y_MM,$COL_USU,$WID_HOS,$bs,23);

# 罫線描画(横線)

&mtdraw::yokosen(
    0,$bs,$PDF_X_MM,$COL_USU,$WID_HOS,$bs,27);

# 曜日描画
$ywk=20.2;
&mtdraw::text(10.5,$ywk,$FONT,$COL_KOI,3,"月");
$ywk+=15;
&mtdraw::text(10.5,$ywk,$FONT,$COL_KOI,3,"火");
$ywk+=15;
&mtdraw::text(10.5,$ywk,$FONT,$COL_KOI,3,"水");
$ywk+=15;
&mtdraw::text(10.5,$ywk,$FONT,$COL_KOI,3,"木");
$ywk+=15;
&mtdraw::text(10.5,$ywk,$FONT,$COL_KOI,3,"金");
$ywk+=15;
&mtdraw::text(10.5,$ywk,$FONT,$COL_BLU,3,"土");
$ywk+=15;
&mtdraw::text(10.5,$ywk,$FONT,$COL_RED,3,"日");

# 左から15mmの位置に縦線を描画

&mtdraw::tatesen(
    15,10,105,$COL_USU,$WID_FUT,0,1);

# 曜日区切り線描画(横線)

&mtdraw::yokosen(
    0,$bs*2,$PDF_X_MM,$COL_USU,$WID_FUT,$bs*3,8);

# dot 描画

$y = 10;
for($i=0;$i<7;$i++){
    $x = 25;
    for($j=0;$j<10;$j++){
        &mtdraw::dot(
            $x+0.1,$y+1,0.5,$COL_USU);
        $x+=10;
    }
    $y+=15;
}

# 9 10 11 ... 18 描画

$y = 8.5;
for($i=0;$i<7;$i++){
    $x = 20;
    for($j=0;$j<10;$j++){
        if ($j==0){
            $wkx=$x-0.5; # 9は1桁なので少し右に
        }else{
            $wkx=$x-1;
        }
        &mtdraw::text(
            $wkx,$y+2,$FONT,
            $COL_KOI,1.6,$j+9);
        $x+=10;
    }
    $y+=15;
}

$y = 115;
&mtdraw::box(1,$y+1,3,3,$COL_KOI,$WID_FUT);
&mtdraw::box(51,$y+1,3,3,$COL_KOI,$WID_FUT);
$y+=5;
&mtdraw::box(1,$y+1,3,3,$COL_KOI,$WID_FUT);
&mtdraw::box(51,$y+1,3,3,$COL_KOI,$WID_FUT);
$y+=5;
&mtdraw::box(1,$y+1,3,3,$COL_KOI,$WID_FUT);
&mtdraw::box(51,$y+1,3,3,$COL_KOI,$WID_FUT);
$y+=5;
&mtdraw::box(1,$y+1,3,3,$COL_KOI,$WID_FUT);
&mtdraw::box(51,$y+1,3,3,$COL_KOI,$WID_FUT);

# PDFに変換

&mtdraw::make_pdf($PDF_FILE);

完成したPDF

完成したPDFを置いておきますので、ご自由にお使い下さい。

ドット用紙

5mm方眼用紙

グラフ用紙

Weekly Schedule