Vodotisk

Původní obrázekOsobně nejsem příznivcem znehodnocování obrázků přidáním vodotisku, ale někdy to může být jediná možnost, jak se ubránit jejich rozkradení. V PHP se pro vložení vodotisku dá použít funkce imagecopymerge, ve které lze určit, jak moc má cílový obrázek překrýt obrázek původní. Následující kód např. načte vodotisk ze souboru $watermark a vloží ho do pravého dolního rohu plnobarevného obrázku $img:

<?php
$imagesize_watermark = getimagesize($watermark);
if ($imagesize_watermark && $imagesize_watermark[2] <= 3) {
    $img_watermark = ($imagesize_watermark[2] == 2 ? imagecreatefromjpeg($watermark) : ($imagesize_watermark[2] == 1 ? imagecreatefromgif($watermark) : imagecreatefrompng($watermark)));
    imagecopymerge($img, $img_watermark, imagesx($img) - $imagesize_watermark[0] - 5, imagesy($img) - $imagesize_watermark[1] - 5, 0, 0, $imagesize_watermark[0], $imagesize_watermark[1], 50);
}
?>

Po aplikaci vodotiskuKdyž už obrázky vodotiskem znehodnotíme, je vhodné si v adresáři nedostupném z webu uložit i jejich originál pro případ, že bychom vodotisk chtěli v budoucnu změnit. Pokud na to zapomeneme a máme k dispozici obrázek použitý pro vodotisk, můžeme ho z obrázků zpětně odstranit:

<?php
function orig_color($result, $watermark, $component, $pct = 50) {
    // result = pct * (1 - alpha) * watermark + (1 - pct + alpha * pct) * orig
    return ($result[$component] - $pct / 100 * (1 - $watermark["alpha"] / 127) * $watermark[$component]) / (1 - $pct / 100 + $watermark["alpha"] / 127 * $pct / 100);
}

for ($j=0; $j < imagesy($img_watermark); $j++) {
    for ($i=0; $i < imagesx($img_watermark); $i++) {
        $color = imagecolorsforindex($img, imagecolorat($img, $i, $j));
        $color2 = imagecolorsforindex($img_watermark, imagecolorat($img_watermark, $i, $j));
        imagesetpixel($img, $i, $j, (orig_color($color, $color2, "red") << 16) + (orig_color($color, $color2, "green") << 8) + orig_color($color, $color2, "blue"));
    }
}
?>

Po odstranění vodotiskuPokud byl výsledek uložen ve ztrátovém formátu (obvykle JPG), zůstanou po vodotisku patrné stopy způsobené nepřesným uložením.

Jakub Vrána, Řešení problému, 1.12.2006, on-line

Diskuse

Strom?:

Nevim jestli je to stastne reseni, prece kdyz uz nahravam neaky obrazek na servr napred si nekam zalohuju original a potom teprv z toho udelam vodotisk, nez udelat vodotisk a pak to ho odstranovat.(Pokud autor nechtel nahodou ukazat jak ho zas zpetne odstranit :)
1.12.2006 18:41:30

ikona Jakub Vrána:

Vždyť to přesně takhle je napsané v článku: "Když už obrázky vodotiskem znehodnotíme, je vhodné si v adresáři nedostupném z webu uložit i jejich originál" a "Pokud na to zapomeneme a máme k dispozici obrázek použitý pro vodotisk, můžeme ho z obrázků zpětně odstranit".
1.12.2006 18:59:21

Trupik:

Již před nějakým časem jsem napsal článek, který se právě tímto zabývá. Myslím, že moje funkce je o něco víc připravená k okamžitému nasazení (pomocí parametrů lze snadno ovládat umístění watermarku na obrázku), takže:
http://trupik.aspweb.cz/programovani/php/watermark-v-php.aspx
2.12.2006 00:12:48

Strom?:

Tak v tom pripade se omlouvam moje chyba :)
2.12.2006 18:56:18

pa3k:

Len malá poznámka. Pod pojmom vodotisk (vodotlač) je obvykle chápené niečo malinko iné. Za vodotlač (watermarkt) by som označil skôr niečo takéto: http://kvalitne.sk/sample/DSCF2396m+WM.jpg
Robí sa to použitím vodoznaku vo formáte png s nastaveným alfa kanálom pre priehľadnosť. Možno to niekomu pomôže.

<?php
function image_overlap($background, $foreground) {

    $insertWidth = imagesx($foreground);
    $insertHeight = imagesy($foreground);

    $imageWidth = imagesx($background);
    $imageHeight = imagesy($background);

    imagealphablending($foreground, TRUE);
    imagecopy(
        $background,
        $foreground,
        0,
        $imageHeight-26,
        0,
        0,
        $imageWidth,
        26
   
);

    imagealphablending($foreground,FALSE);
    imagesavealpha($foreground,TRUE);

    return $background;

}
?>

12.6.2007 18:05:13

ikona Jakub Vrána:

Zkus popsat slovy, jaký je rozdíl mezi vodoznakem v mém pojetí a v tvém pojetí. Já žádný rozdíl nevidím.
12.6.2007 19:52:38

pa3k:

Jabub sorry, nepostrehol som, že príklad, ktorý uvádzaš vie aj priehľadnosť. Ani pri detailnom skúmaní toho výsledného obrázku mi to nedošlo. Chcelo by to asi lepší príklad :) Z kódu je to ale jasné, už som si všimol, že je použitý posledný parameter funkcie imagecopymerge pre priehľadnosť. O tejto možnosti som vôbec netušil. Ono bez priehľadnosti by sa vlastne nedal spätne dopočítať ten pôvodný obrázok. Drobný rozdiel tam ale predsalen je. Pri použití png s alfa kanálom, je výhoda v tom, že vodoznak môže mať rôzne stupne priehľadnosti, teda dá sa vytvoriť napríklad postupný prechod a podobné srandičky.

png vodoznak s alfa kanálom:
http://kvalitne.sk/sample/wm.png
výsledok:
http://kvalitne.sk/sample/DSCF2396m+WM2.jpg
13.6.2007 13:30:20

Martin:

Já vidím rozdíl při použití 24bit png. Verze v článku s imagecopymerge nechce pracovat s alfa kanálem, zatímco imagecopy ho použije a tedy průhlednost png se zachová. U gif je to jedno.
29.3.2012 11:25:57

Johnyz:

Ahoj, zkoušel jsem ten skript a z nepochopitelného důvodu (pro mne) mi to hází tuto chybu (u všech imagesx a imagesy):

Warning: imagesx(): supplied argument is not a valid Image resource in ........... on line 86

Obrázky jsem hodil přímo do rootu, kde je skript
<?php
$background
= 'Hell.jpg';
$foreground = 'vodotisk.png';
?>

Nevíte někdo, co s tím?
13.12.2007 11:12:05

ikona Jakub Vrána:

Přesně, jak říká chybová hláška - $foreground a $background musí být Image resource. Tedy:
<?php
$background
= imagecreatefromjpeg('Hell.jpg');
$foreground = imagecreatefromjpeg('vodotisk.png');
?>

13.12.2007 12:13:24

Johnyz:

DÍKY !
13.12.2007 14:17:12

Blizard:

Ahoj, chtěl jsem využít tvůj script. Ale hlásí mi to chyby. A opravdu si nevím rady.

Warning: imagecreatefromjpeg() [function.imagecreatefromjpeg]: '../vodotisk.png' is not a valid JPEG file in ...

Warning: imagesx(): supplied argument is not a valid Image resource in ...

Warning: imagesy(): supplied argument is not a valid Image resource in ...

Warning: imagealphablending(): supplied argument is not a valid Image resource ...

Warning: imagecopy(): supplied argument is not a valid Image resource in ...

Warning: imagealphablending(): supplied argument is not a valid Image resource in ...

Warning: imagesavealpha(): supplied argument is not a valid Image resource in ...
1.2.2010 21:41:22

ikona v6ak:

Ehm, přečti si první chybovou hlášku a může ti to být jasný.
2.2.2010 14:37:12

Blizard:

No už jsem to vyřešil :). Ale Obrázek na kterém by měl být ten vodotisk. Tak je stále stejný.
2.2.2010 15:21:06

Stujky:

Poprosim o radu,

kdyz do promene $watermark vlozim obrazek v .png, vysledek je jen pruhledny obdelnik. GIF mi funguje bez problemu.

Prosim v cem je problem?

dekuji
7.3.2008 01:02:16

MCleaner:

Zdravim,

mam takovy postreh a byl bych rad, pokud mi ho tu nekdo z vas potvrdi.
Trochu jsem s vkladanim vodoznaku do obrazku laboroval a pokud jsem pouzil kombinaci JPG (hlavni obrazek) a GIF (vkladany vodoznak), tak vysledek byl dle ocekavani. Pokud jsem ale pouzil JPG s PNG (ktery mel nastavenou pruhlednost) tak ve vyslednem obrazku byla pruhlednost puvodniho PNG zrejme zrusena, protoze pruhledna mista puvodniho PNG byla na vyslednem obrazku normalne videt. Nakonec jsem prisel na to, ze tato kombinace funguje (JPG, PNG) pokud misto funkce imagecopymerge pouziji pouze funkci imagecopy. Pak je vysledek tak jak bych chtel a puvodni pruhlednost PNG je ve vysledku spravne videt (vlastne nevidet :) ). Je tento zpusob spravny nebo je jina moznost jak spravne spojit JPG a PNG s pruhlednosti pomoci imagecopymerge?
Diky.
31.1.2009 09:49:51

flam:

Přesně s tímto jsem se taky potýkal, akorát místo funkce ImageCopy() jsem použil ImageCopyResized() - také fungovalo. Jakmile jsem použil funkci ImageCopyMerge() na vodotisk ve formátu PNG, tak vložený vodoznak měl s původním obrázkem pramálo společného.
6.2.2009 04:37:27

Juraj Krivda:

Použi funkciu imagecopy miesto ImageCopyMerge
22.3.2009 18:41:00

Miroslav:

Zdravím Tě, Jakube. Díky za Tvůj web, člověk najde, co hledá, když hledá. :-) Zrovna článek http://php.vrana.cz/vodotisk.php mi moc pomohl. Žel jsem puntičkář a z PNG s alfa kanálem chci dostat 100% výsledek, což se mi nedaří stejně jako u http://kvalitne.sk/sample/DSCF2396m+WM2.jpg - jde mi konkrétně o roztřepení okrajů vodotisku. Je to věc PHP knihovny, nebo zdrojového PNG souboru? Předem díky za případnou odpověď.
16.4.2009 07:31:06

dust:

trochu offtopic, ale nemohu si pomoci. SUPER WEB, diky za nej
26.5.2009 02:53:35

Pinqui:

Prosím mám dotaz. Jak vložím do obrázku, který budu uploadovat přez formulář šikmě pod sebou třeba 3 texty přez obrázek??? Jde třebas o to když budu dělat i miniatury, tak aby byl ten text taky vidět. Děkuji
28.6.2009 10:14:58

Francek Vosmrádlo:

V PHP, za pomoci funkcí knihovny GD si můžeš:
* vytvořit pomocný obrázek (v tomto případě může/měl by být s indexovanými barvami),
* vložit do něj tvůj text,
* obrázek s tímto textem natočit o požadovaný úhel,
* určit si barvu pozadí jako průhlednou,
* obrázek použít jako vodoznak.
Pokud víš, co v těch řádkách bude (a je to konstantní), pak by mi přišlo lepší udělat si tento natočený text v nějakým grafickým editoru a pak ho jako obrázek též používat. Výše popsané řešení je vhodné, pokud by se onen text měl měnit.
4.8.2010 05:29:59

ikona Ghostshape:

Taky díky, netušil jsem, že je to až takhle jednoduché..
10.8.2010 10:24:23

Šimon:

Ahoj. Zajímalo by mě jestli můžu zadat umístění do obrázku třeba procenty, nebo tam dát nějaký výpočet kdyby byl obrázek třeba na výšku, vodotisk by se schoval pryč, jde mi o to že mám fotky různých velikostí a nechce se mi to předělávat na 140 dalších fotek... možná bych to mohl i zautomatizovat nějakým cyklem - mám fotky 1.jpg, 2.jpg, 3.jpg...
24.12.2011 09:05:03
avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.