Áttetsző képek kezelése PHP alatt
Aki már dolgozott PHP alatt áttetsző képekkel (azaz olyan képekkel, amelyek részben átlátszóak), az tudhatja, hogy a beépített GD rendszer nem igazán segíti munkáját. A GD2 bevezetésével ugyan javultak a dolgok, de messze van még a rendszer attól, hogy igazán jól használható legyen áttetsző képek kezelésében.
Az odáig rendben van, hogy nagyszerűen kezelhetünk benne nem áttetsző képeket, erre minden lehetőségünk megvan. Ugyanakkor áttetsző képek esetén a következő problémákba ütközünk:
- Ha a képünk áttetsző, akkor a rendszer hajlamos eldobni az átlátszóságot a pixelekről, azaz pixelenként csak 24 bitet használ.
- Nincs támogatás arra, hogy egy már áttetsző képnek módosítsuk az átlátszóságát.
Áttetsző képek esetén a legfontosabb, hogy egy olyan üres vászonnal (képpel) kezdjünk a munkát, ami true color, és csak átlátszó pixeleket tartalmaz. Ehhez írtam egy egyszerű, de nagyszerű függvényt, ami ezt szépen megvalósítja:
/**
* Create a new true color image with solid color background.
*
* @param $width
* The image's width.
* @param $height
* The image's height.
* @param $color
* 24 bit color of the background.
* @param $opacity
* Opacity of the background from 0 to 100 where 100 means totally opaque
* and 0 is transparent.
* @return
* An image link resource.
*/
function image_generate($width, $height, $color = 0, $opacity = 100) {
$im = imagecreatetruecolor($width, $height);
// Handle transparency.
imagealphablending($im, true);
imagesavealpha($im, true);
// Generate RGBA components for the color.
$r = ($color >> 16) & 0xFF;
$g = ($color >> 8) & 0xFF;
$b = $color & 0xFF;
// $a is between 0 - 127 where 0 is totally opaque and 127 is transparent.
$a = 127 - round(127 * $opacity / 100);
if ($a) {
$fill = imagecolorallocatealpha($im, $r, $g, $b, $a);
} else {
$fill = imagecolorallocate($im, $r, $g, $b);
}
// Fill the background, and prepare for drawing.
imagefill($im, 0, 0, $fill);
imageantialias($im, true);
return $im;
}
Az image_generate()
függvény az imagecreatetruecolor()
függvény segítségével létrehoz egy true color képet, majd azt kiszínezi a megfelelő színűre. Amennyiben az $opacity
értéknek 0-t adunk meg, akkor teljesen átlátszó képet kapunk, ekkor a szín mellékessé válik. Vagyis csak válna, ugyanis például az imagecopymerge()
függvény, ha megadunk neki 0 és 127 közötti $ptc
értéket (azaz átlátszóságot), akkor, mivel ez a függvény eldobja a kép eredeti áttetszőségre vonatkozó információit, ezzel a teljesen átlátszatlan színnel fogja másolni a képet. Azaz, ha az áttetsző színünk, amivel a vásznat kiszíneztük fekete volt, akkor az átlátszatlan feketévé, ha fehér, akkor fehérré válik.
A függvény még beállít pár lényeges információt a képpel kapcsolatban. Ezek pedig a következők:
- A kép tartalmazzon áttetszőséget.
- Tartsa meg az áttetszőségre vonatkozó információt mentéskor.
- A rajta végzett műveletekkor az anti-alias függvényeket is használja (átméretezéskor és áttetsző képek egymásra másolásakor van jelentősége).
Ahhoz, hogy egy egy képnek megváltoztassuk az átlátszóságát, két dolgot kell tennünk. Mivel az imagecopymerge()
, amivel elméletileg az áttetszőséget is tudjuk módosítani (a $ptc
paraméter megadásával), nem működik már korábban is áttetsző képeken, ezért létre kell hozni egy átlátszó vásznat (például az image_generate()
függvény segítségével), majd erre kell pixelenként átmásolni az képünk adatait, miközben azoknak megváltoztatjuk az átlátszóságát. Erre jött létre az imagecopy_opacity()
függvény:
/**
* Copy an image to destination with changing it's opacity.
*
* @param $dst_im
* Destination image link resource.
* @param $src_im
* Source image link resource.
* @param $dst_x
* x-coordinate of destination point.
* @param $dst_y
* y-coordinate of destination point.
* @param $src_x
* x-coordinate of source point.
* @param $src_y
* y-coordinate of source point.
* @param $src_w
* Source width.
* @param $src_h
* Source height.
* @param $opacity
* Opacity from 0 to 100 where 100 means totally opaque 0 is transparent.
*/
function imagecopy_opacity($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $opacity) {
// Calculate the width/height to be copied based on the source width/height,
// the destination width/height, and the specified width/height, to only copy
// available pixels to available destinations.
$width = min($src_w, imagesx($src_im), imagesx($dst_im) - $dst_x);
$height = min($src_h, imagesy($src_im), imagesy($dst_im) - $dst_y);
$alpha = $opacity / 100;
for ($x = 0; $x < $width; $x++) {
for ($y = 0; $y < $height; $y++) {
// Get color at (x, y) pixel on the source, and change it's opacity.
$color = imagecolorat($src_im, $x + $src_x, $y + $src_y);
$r = ($color >> 16) & 0xFF;
$g = ($color >> 8) & 0xFF;
$b = $color & 0xFF;
// $a is between 0 - 127 where 0 is totally opaque and 127 is transparent.
$a = 127 - round((127 - (($color >> 24) & 0x7F)) * $alpha);
$newcolor = imagecolorexactalpha($dst_im, $r, $g, $b, $a);
// Set the color at the same pixel on destination.
imagesetpixel($dst_im, $x + $dst_x, $y + $dst_y, $newcolor);
}
}
}
A függvénynek meg kell adni a cél és a forrás képet, valamint az eltolást ezeken a képeken, a forrás kép másolandó darabját, valamint természetesen az átlátszóságot. A PHP átlátszóságkezelése egy kicsit fura ezen a téren. Ugyanis a dokumentáció nem írja, de az imagecolorat()
függvény a színen kívül visszaadja az átlátszóságot is a 24. bit feletti információban 7 bites pontossággal, azaz 0–127-es skálán, ahol a 0 átlátszatlant, 127 pedig teljesen átlátszót jelent.
Azaz a függvényünk nem tesz mást, mint a megadott régióban végighalad a forráskép összes pixelén, azoknak kiszedi a színinformációját (az átlátszósággal egyetemben), majd az átlátszóságot módosítva felülírja a célképen a megadott pixeleket. Ekkor ugye a régióba eső összes pixel felülírásra kerül, de az eredeti imagecopy()
esetében is pontosan ugyanezt a működést kapjuk. Ezek után, ha ezt a módosított képet használni akarjuk, nem kell mást tennünk, mint az imagecopymerge()
használatával (a $ptc
értéket mellőzve) rámásoljuk arra a képre, amit szeretnénk.
Ahhoz, hogy PHP-ban áttetsző képpel tudjunk dolgozni a következőket kell tennünk tehát:
- Betöltjük a használni kívánt forrás képet az
imagecreatefrom*()
segítségével. - Létrehozunk egy teljesen átlátszó képet (például az
image_generate()
függvény segítségével). - Rámásoljuk forrás képet az átlátszó képre (
imagecopy()
,imagecopymerge()
,imagecopyresampled()
, illetveimagecopy_opacity()
). - Elkezdünk vele dolgozni, mint bármilyen más képpel.
Miért imagecopymerge?
Összefoglaló
Thx
Köszönjük
exec('/usr/local/php/bin/php /home/user/script.php &');
(linuxon/unixon, kulcs az &
If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.
Köszönöm a kiegészítést
exec('/usr/local/php/bin/php /home/user/script.php > /home/user/akarmi.txt &');
Nem csak processzor, hanem
Szerintem erről a témáról