Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHPでImageMagickとICUを使って画像に縦書きテキストを描画する / Draw vertical text in PHP using ImageMagick and ICU

cc4966
March 28, 2021

PHPでImageMagickとICUを使って画像に縦書きテキストを描画する / Draw vertical text in PHP using ImageMagick and ICU

PDFはこちら: https://drive.google.com/file/d/1frSl5X4296WzFm7V_thsYHcMCIWQt42J/view?usp=sharing

PHPerKaigi 2021 ( https://phperkaigi.jp/2021/ ) での発表「PHPでImageMagickとICUを使って画像に縦書きテキストを描画する」の資料です。

PHPで画像に縦書きテキストを描画する話です。
横書きテキストしか描画できないImageMagickと、ICU (Intl) を使って実現します。
発表では以下の内容を踏まえて縦書きテキストを画像に描画する方法とその要素技術についてお話しします。

- 縦書きテキストとは何か
- テキストを構成する文字について
- 文字を描画するためのフォントファイルについて
- フォントファイルを扱う時に便利なttxというツールについて
- PHPから使えるImageMagickについて
- PHPから使えるICUについて
- 文字列を折り返すということについて

cc4966

March 28, 2021
Tweet

More Decks by cc4966

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ SPLVSPLV w SPLVSPLV 5XJUUFS!@  w ͳΜͰॎॻ͖ʁ w ձࣾͰॎॻ͖ؔ࿈ͷػೳΛ࡞ͬͨͷͰͦͷ͓࿩

    w झຯͰ΋5"5&EJUPSͱ͍͏ॎॻ͖ςΩετΤσΟλΛ࡞ͬͯΔ w J04 "OESPJE 8JOEPXT NBD04 6CVOUV աڈͷൃදΛͲ͏ͧ w J04%$ w %SPJE,BJHJ w J04%$
  2. ॎॻ͖ςΩετͱ͸ จࣈΛදࣔ͢ΔͨΊͷཁૉٕज़ w จࣈίʔυ w ςΩετΛσʔλԽ͢Δϓϩτίϧ w 6OJDPEFͱ͔ w ϑΥϯτϑΝΠϧ

    w จࣈͷܗঢ়͕ऩೲ͞Ε͍ͯΔʢଟ͘ͷ৔߹Ξ΢τϥΠϯ৘ใʣ w ֤จࣈΛ഑ஔ͢Δํ๏͕هड़͞Εͨ΋ͷ
  3. ෳ਺ߦςΩετ w จࣈͣͭඳըͯ͠ંΓฦ͢ $dx = 0; $dy = 0; foreach(preg_split('//u',

    $text, -1, PREG_SPLIT_NO_EMPTY) as $part) { $metrics = $image->queryFontMetrics($draw, $part); $advance = $metrics['originX']; if ($dx + $advance > $width) { $dy += $line_height; $dx = 0; } $image->annotateImage($draw, $x + $dx, $y + $dy, 0, $part); $dx += $advance; if (preg_match("/\n/", $part)) { $dy += $line_height; $dx = 0; } } จࣈྻΛંΓฦ͢ ͜͜Ͱ͸ંΓฦ ͞Εͨ͘ͳ͍
  4. 1)1͔Β࢖͑Δ*$6ʹ͍ͭͯ *OUFSOBUJPOBM$PNQPOFOUGPS6OJDPEF w *$6͸6OJDPEFͷ৘ใ΍ΞϧΰϦζϜΛར༻Ͱ͖ΔϥΠϒϥϦ w 1)1Ҏ߱ಉࠝ͞ΕΔࠃࡍԽ༻֦ுϞδϡʔϧΛ௨ͯ͠ར༻Մೳ w ͜ΕΛ࢖ͬͯվߦՄೳͳҐஔΛऔಘ͢Δ͜ͱ͕Ͱ͖·͢ // Before

    foreach(preg_split('//u', $text, -1, PREG_SPLIT_NO_EMPTY) as $part) {...} // After $it = IntlBreakIterator::createLineInstance('jp'); $it->setText($text); foreach ($it->getPartsIterator() as $part) {...}
  5. ॎॻ͖ͱԣॻ͖ w ॎॻ͖Ͱ͸จࣈΛॎʹฒ΂Δ foreach(preg_split('//u', $part, -1, PREG_SPLIT_NO_EMPTY) as $c) {

    // advance͸ϑΥϯτϑΝΠϧͷvmtx ςʔϒϧ͔Β $advance = $font_size; $image->annotateImage($draw, $x + $dx, $y + $dy, 0, $c); $dy += $advance; } ॎॻ͖ͱจࣈͷ޲͖
  6. ॎॻ͖ͱจࣈͷ޲͖ 6OJDPEFͷॎॻ͖ͷ࢓༷ w 6OJDPEF4UBOEBSE"OOFY 6"9  w 6OJDPEF7FSUJDBM5FYU-BZPVU w 6ͦͷ··දࣔ͢Δ΋ͷʢ೔ຊޠͷจࣈͱ͔ʣ

    w 3ӈ౗͠Ͱදࣔ͢Δ΋ͷʢΞϧϑΝϕοτͱ͔ʣ w 5Vͦͷ··දࣔ͢Δ͕ผͷάϦϑ͕ඞཁʢখจࣈͷฏԾ໊ΧλΧφʣ w 5Sӈ౗͠Ͱදࣔ͢Δ͕ผͷάϦϑ͕ඞཁʢ௕Իه߸ʣ શͯͷจࣈΛ͜ͷͭ Ͱ෼ྨ͍ͯ͠Δ
  7. ॎॻ͖ͱԣॻ͖ w 3ͳΒ౓ճస͢Δ if (!isR($c)) { $image->annotateImage($draw, $x + $dx,

    $y + $dy, 0, $c); } else { $image->annotateImage($draw, $x + $dx, $y + $dy, 90, $c); } w 5S͸ϑΥϯτͷ࢓ࣄͳͷͰ์ஔ ॎॻ͖ͱจࣈͷ޲͖ ͳΜ͔ͣΕͯΔ
  8. ॎॻ͖ͱԣॻ͖ // ӈ্࠲ඪΛࢦఆ͢Δ͜ͱʹ͢Δ if (!isR($c)) { $image->annotateImage($draw, $x - $font_size,

    $y + $font_size * 880 / 1000, 0, $c); } else { $image->annotateImage($draw, $x - $font_size * 880 / 1000, $y, 90, $c); } ॎॻ͖ͱจࣈͷ޲͖ BTDFOEFS VOJUTQFSFN ϑΥϯτ͝ͱͷ஋
  9. ॻهૉΫϥελ 6OJDPEFͷจࣈͷ࢓༷ w 6OJDPEF4UBOEBSE"OOFY 6"9  w 6OJDPEF5FYU4FHNFOUBUJPO w ͜Ε΋*$6Λར༻͢Ε͹ॻهૉΫϥελ΋ղܾ

    // Before foreach(preg_split('//u', $part, -1, PREG_SPLIT_NO_EMPTY) as $c) {...} // After $it = IntlBreakIterator::createCharacterInstance('jp'); $it->setText($part); foreach($it->getPartsIterator() as $c) {...}