Vykreslení PNG obrázku s víceřádkovým textem v PHP

Vytváření obrázků včetně psaní textu není v PHP žádný problém. Stačí použít funkce začínající prefixem image, konkrétně třeba imagettftext() pro psaní textu pomocí TrueType fontů. Tímto způsobem můžeme vepisovat text do slevových voucherů, na vizitky, samolepky nebo generovat text, který nemá být (jednoduše) strojově čitelný, třeba e-mail. Protože jsme ale líní a nechce se nám moc zkoumat dokumentaci, použijeme nějakou hotovou knihovnu.

intervention/image

První moje volba byla knihovna intervention/image. Na GitHubu vypadá aktivně a podle Packagist má 35.000 stažení za poslední měsíc. Navíc má přímou podporu pro Laravel (popř. OctoberCMS) - jednu fasádu a Service Providera, takže není co řešit, jdu do toho, composer require...

Knihovna je to opravdu povedená, má všechno co by mohl programátor potřebovat. Vytváření obrázku přímo ze souboru, změnit velikost, otáčet, kreslit do něho křivky, vkládat další obrázky (watermarky) a taky psát do něho text. ALE... ne víceřádkový text s automatickým zalomením :-)

// vytvoření čistého obrázku
$img = Image::canvas(800, 600, '#ccc');

// nebo vytvoření ze souboru
$img = Image::make('public/foo.jpg');

// změna velikost
$img->resize(320, 240);

// vložení dalšího překryvného obrázku
$img->insert('public/watermark.png');

// uložení výsledného obrázku
$img->save('public/bar.jpg');

Bohužel termín dodání zakázky mě tlačí a nemám zrovna čas na forkování. Zkusme jinou knihovnu, bude jich určitě milion :-)

stil/gd-text

Další knihovna kterou jsem objevil, má název stil/gd-text a umí sice přímo psaní víceřádkového textu, pomocí funkce imagettfbox(), ALE zase neumí vůbec nic jiného :-) Nicméně psaní textu umí dobře. Knihovně je potřeba dodat již hotový Image Resource, který získáme funkcí imagecreatefrompng(), createimagefromjpeg(), atd. Prostor pro psaní textu definujeme pomocí souřadnic v metodě setBox() a knihovna se do tohoto čtverce pokusí text naplnit.

// $im je Image Resource, Box je GDText\Box a Color je GDText\Color
$box = new Box($im);
$box->setFontFace('Franchise-Bold-hinted.ttf');
$box->setFontColor(new Color(255, 75, 140));
$box->setTextShadow(new Color(0, 0, 0, 50), 2, 2);
$box->setFontSize(40);
$box->setBox(20, 20, 460, 460);
$box->setTextAlign('left', 'top');
$box->draw("Náš super dlouhý text který chceme na více řádků");

Výstupem je opět Image Resource, který je pomocí funkcí imagepng(), nebo třeba imagejpeg() vykreslit.

header("Content-type: image/png");
imagepng($box);

Zachování všech barev u PNG

Pokud chceme do podkladového PNG obrázku psát barevným textem, jehož barva se nepoužívá v samotném obrázku, například červený text na žlutý obrázek, je potřeba uložit PNG s plnou paletou barev (třeba jako 24bit). Pokud PNG uložíme jako 8bit, paleta se omezí pouze na barvy použité v obrázku a barva textu pak bude jiná než požadujeme.

Dole vlevo je vidět žlutá omezená paleta barev, vpravo bez omezení.

Vykreslení PNG i s průhledností

Pro zachování průhlednosti u PNG i při zpracování v PHP, musíme zapnout ukládání alpha kanálu pomocí imageSaveAlpha() a povolit jeho vykreslování pomocí imageAlphaBlending().

// vytvoříme čistý obrázek
$image = ImageCreateTrueColor($width, $height);

// povolení průhlednosti
imageAlphaBlending($image, true);
imageSaveAlpha($image, true);

// vykreslíme
header('Content-Type: image/png');
imagepng($image);

// a uvolníme paměť
imagedestroy($image);