Vodoznak pomocou PHP. Pridajte dynamický vodoznak do obrázka pomocou vodoznaku PHP PHP za chodu

  • 20.06.2020

Jednou zo zaujímavých vecí, ktoré môžete robiť s grafickou knižnicou GD PHP, je trieda, ktorá označí obrázok vodoznakom. Stručne povedané, vodoznak je technológia na ochranu digitálnych obrázkov pred neoprávneným použitím pomocou vodoznaku alebo titulkov. V dôsledku toho môže byť použitý (a väčšinou je) na určenie vlastníka autorských práv k obrázku. Poďme teda ďalej.

Úvod

PHP v tejto fáze svojho vývoja ponúka programátorom široké spektrum funkcií na dynamické generovanie obrázkov a prácu s nimi. V tomto článku vám ukážem, ako vytvoriť triedu, ktorá bude vodoznakom tie isté obrázky. Táto trieda bude pracovať s dvoma obrázkami: originál a vodotlač. Ako doplnok bol zavedený tretí parameter - naša trieda bude obsahovať premennú alfa. To nám umožní použiť alfa kanál pre náš vodoznak.

Pre referenciu

alfa kanál (alfa kanál):časť obrazu, ktorá uchováva informácie o priehľadnosti jednotlivých častí obrazu, zatiaľ čo farebné kanály ukladajú informácie o farbe obrazu. V grafických editoroch sa používa na maskovanie (ochranu pred úpravou) určitej oblasti obrázka. V niektorých aplikáciách sa nazývajú priehľadná maska.

Informácie nachádzajúce sa v alfa kanáli najčastejšie predstavujú zvýraznenia - nejaký tvar alebo usporiadanie farebných plôch. Ponechaním alfa kanála v obraze sa veľkosť súboru zväčší o 1/3. Obrázky RGB môžu mať až 24 alfa kanálov. Bitmapy a indexované obrázky nemôžu obsahovať alfa kanály.

Prvá časť – základy

Skôr ako začneme písať triedu samotnú, pozrime sa na funkcie, ktoré v nej budú použité. Tu je ich zoznam:

# vráti šírku a výšku obrázka imagesx() imagesy() # vytvorí nový obrázok v skutočnej farbe imagecreatetruecolor # vráti asociatívne pole s kľúčmi červeným, zeleným a modrým (+alfa kanál), ktoré obsahuje zodpovedajúce hodnoty pre zadaný index farieb imagecolorsforindex() # vráti index farby pixelu na zadanom mieste v obrázku imagecolorat() # vykreslí jeden pixel danej farby imagesetpixel() # vráti index paletového indexu farieb obrázka, ID farby (zložené z komponentov RGB) a paletový index farieb obrázka, ktorý je „najbližšie“ hodnote RGB (tieto údaje sú potrebné pre funkciu imagesetpixel()) imagecolorexact() imagecolorallocate() imagecolorclosest()

Ako vidíte, php má dostatok funkcií na prácu s grafikou. Hoci účel niektorých z nich nie je teoreticky úplne jasný, v praxi je všetko oveľa jednoduchšie. Preto, aby sme prišli na to, ako s nimi pracovať, ich použijeme v našej triede.

Výber cesty k cieľu

Teraz, keď sme sa už rozhodli pre cieľ nášho „miniprojektu“, vráťme sa trochu späť a povedzme si spôsoby jeho realizácie.

Najprv naša aplikácia dostane dva obrázky – pôvodný obrázok a samotný vodoznak. Ďalej musíme určiť rozmery týchto obrázkov (šírka-šírka a výška-výška). Tieto údaje potrebujeme na umiestnenie vodoznaku do stredu obrázka (za predpokladu, že veľkosť vodoznaku bude menšia ako samotný obrázok).

Potom budeme musieť prekryť náš vodoznak na pôvodný obrázok. Aby sme to dosiahli, musíme pridať farby (matematicky) prekryvných obrázkov, aby sme získali tretí.

A na záver budeme musieť výsledný obrázok zobraziť v prehliadači. V tomto prípade sa obrázok otvorí priamo zo zdroja uvedeného v " "

Myslím si, že teórie je už dosť – kľúčové body v nej sú dostatočne podrobne opísané. Teraz prejdime k písaniu scenára.

Druhá časť - písanie scenára

Začnime tým najjednoduchším – napíšme triedu, ktorá vytvorí súbor s vodotlačou. Nazvime ho „vodoznak“ a jeho kód napíšme do súboru „api.watermark.php“. "Kostru" triedy budú mať tri funkcie:

Ďalším krokom je napísanie kódu pre funkcie triedy „vodoznak“. Súbor "api.watermark.php" dopĺňame nasledujúcimi riadkami kódu:

# funkcia, ktorá spája dva zdrojové obrázky do jednej funkcie create_watermark($main_img_obj, $watermark_img_obj, $alpha_level = 100) ( # previesť hodnotu priehľadnosti alfa kanála z % na desiatky $alpha_level/= 100; # vypočítať rozmery obrázka (šírka a výška ) $main_img_obj_w = imagesx($main_img_obj); $main_img_obj_h = imagesy($main_img_obj); $watermark_img_obj_w = imagesx($watermark_img_obj); $watermark_img_obj_h = imagesy($watermark_img_img_img_obj); #j$ming_img_img_obj); /2)-($watermark_img_obj_w/2)); $main_img_obj_max_x=ceil(($main_img_obj_w/2)+($watermark_img_obj_w/2)); $main_img_obj_min_y=floor(($main_img_-(obj_h_im/2) ); $main_img_obj_max_y=ceil(($main_img_obj_h/2)+($watermark_img_obj_h/2)); # vytvorte nový obrázok $return_img = imagecreatetruecolor($main_img_obj_w, $main_img_obj_h); # nejaký kód“ pôvodný obrázok # zobraziť obrázok s vodoznakom podpísať return $return_img; ) # koniec funkcie create_watermark().

Teraz sa pozrime bližšie na funkciu create_watermark().

Najprv mu odovzdáme tri parametre:

# zdrojový obrázok, ktorý má byť označený vodoznakom $main_img_obj # samotný vodoznak musí obsahovať alfa kanál $watermark_img_obj # vodoznak hodnota priehľadnosti alfa kanála, (0-100, predvolená hodnota = 100) $alpha_level

(Je dôležité poznamenať, že naša funkcia prijíma obrázky ako objekty, nielen ako cesty k nim – ale o tom neskôr)

Ďalším krokom je vytvorenie nového obrázka v skutočných farbách s rovnakými rozmermi ako pôvodný obrázok. Tento obrázok (premenná $return_img) sa použije na spojenie informácií z pôvodných obrázkov (obrázok a vodotlač).

Predtým sa však ešte treba „prejsť“ cez každý z dvoch pôvodných obrázkov a „zlúčiť“ ich do jedného. Na to je ešte priskoro – ešte na to nie sme pripravení. Namiesto toho umiestnime komentár „nejaký kód“ a potom do tohto priestoru pridáme kúsok kódu.

Posledným krokom je zobrazenie nášho upraveného obrázka na webovej stránke, ktorá si to vyžaduje. Ďalej zvážte zostávajúce dve pomocné funkcie.

Tretia časť - Pomocné funkcie

Okrem funkcie create_watermark má naša trieda vodoznaku ďalšie dve funkcie. Pokračujme v zdrojovom kóde triedy nasledujúcimi riadkami:

# priemerné dve farby, berúc do úvahy priehľadnosť funkcie alfa kanála _get_ave_color($color_a, $color_b, $alpha_level) ( return round((($color_a*(1-$alpha_level))+($color_b*$alpha_level) )); ) # vráti hodnoty najbližších RGB komponentov novej funkcie obrázka _get_image_color($im, $r, $g, $b) ( $c=imagecolorexact($im, $r, $g, $ b); if ($c!=- 1) vráťte $c; $c=imagecolorallocate($im, $r, $g, $b); if ($c!=-1) vráťte $c; vráťte imagecolorclosest( $im, $r, $g, $ b); )

A teraz podrobnejšie. Naša prvá funkcia „_get_ave_color“ preberá číselné hodnoty dvoch farieb a alfa kanála. Vráti ich priemernú hodnotu. Túto funkciu potrebujeme na určenie farby, ktorá sa získa, keď sa prekrývajú pixely dvoch kresieb.

Druhá funkcia „_get_image_color“ rozdelí obrázok na červenú (červenú), zelenú (zelenú) a modrú (modrú) zložku (paleta rgb). Pomocou vstavaných php funkcií pre prácu s grafikou (ich popis bol na začiatku článku) získame najbližšiu hodnotu farby pre nový obrázok.

Okrem toho sa kontroluje niekoľko ďalších bodov. Po prvé, ak bolo možné získať presnú hodnotu (premenná $c), potom sa vráti z funkcie (návrat $c). V opačnom prípade sa vykoná pokus o zhodu farby pomocou funkcie imagecolorallocate(). Ak to nepomôže dosiahnuť výsledok, potom pomocou funkcie imagecolorclosest () sa jednoducho vráti najbližšia hodnota farby (najpresnejšia).

Naša trieda je takmer pripravená. Zostáva len nahradiť komentár „nejaký kód“ vo funkcii „create_watermark“ nasledujúcimi riadkami:

# prechádzajte obrázkom pre ($y = 0; $y< $main_img_obj_h; $y++) { for ($x = 0; $x < $main_img_obj_w; $x++) { $return_color = NULL; # определение истинного расположения пикселя в пределах # нашего водяного знака $watermark_x = $x - $main_img_obj_min_x; $watermark_y = $y - $main_img_obj_min_y; # выбор информации о цвете для наших изображений $main_rgb = imagecolorsforindex($main_img_obj, imagecolorat($main_img_obj, $x, $y)); # если наш пиксель водяного знака непрозрачный if ($watermark_x >= 0 && $watermark_x< $watermark_img_obj_w && $watermark_y >= 0 && $watermark_y< $watermark_img_obj_h) { $watermark_rbg = imagecolorsforindex($watermark_img_obj, imagecolorat($watermark_img_obj, $watermark_x, $watermark_y)); # использование значения прозрачности альфа-канала $watermark_alpha = round(((127-$watermark_rbg["alpha"])/127),2); $watermark_alpha = $watermark_alpha * $alpha_level; # расчет цвета в месте наложения картинок $avg_red = $this->_get_ave_color($main_rgb["red"], $watermark_rbg["red"], $watermark_alpha); $avg_green = $this->_get_ave_color($main_rgb["zelená"], $watermark_rbg["zelená"], $watermark_alpha); $avg_blue = $this->_get_ave_color($main_rgb["modrá"], $vodoznak_rbg["modrá"], $vodoznak_alpha); # pomocou prijatých údajov vypočítajte index farieb $return_color = $this->_get_image_color($return_img, $avg_red, $avg_green, $avg_blue); # ak si nemôžete vybrať farbu, zoberte # kópiu pôvodného pixelu ) else ( $return_color = imagecolorat($main_img_obj, $x, $y); ) # nakreslite nový obrázok z prijatých pixelov imagesetpixel( $return_img, $x, $ y, $return_color); ))

Po napísaní takej významnej časti kódu sa môžete pozastaviť a podrobnejšie sa venovať jeho analýze.

Náš skript najprv prechádza obrazom pomocou dvoch slučiek „for“. Paralelne sa vypočítavajú aj súradnice každého pixelu vodoznaku.

Ďalej sa pre každý pixel vyhľadajú informácie RGB. Ak sa aktuálny pixel nenachádza v oblasti, kde sa pretína pôvodný obrázok a vodotlač, potom naša trieda iba duplikuje pixel pre nový obrázok. Ak sa pixel nachádza v oblasti priesečníka, musíme určiť jeho farbu ako výsledok prekrytia pôvodného obrázka a vodoznaku.

Na určenie farby oblasti priesečníka musíme najprv získať hodnotu premennej RGB vodoznaku pomocou informácií, ktoré sme získali v slučkách „for“. Potom sa pomocou funkcie „_get_ave_color“ určí priemerná hodnota farby pre nový obrázok. Ďalej nasleduje funkcia „_get_image_color“ na určenie farebnej schémy, ktorú použije funkcia „return_img“.

Výsledkom je, že po dokončení slučiek "pre" máme hotový obrázok s vodoznakom.

A teraz sa pozrime na našu triedu v akcii.

Štvrtá časť - skúšobná jazda

Na začiatok potrebujeme dva súbory. Prvú pomenme „watermark_test.php“ a umiestnime do nej nasledujúci kód:



Účel tohto súboru je veľmi jednoduchý: zobrazuje pôvodné (main.jpg) a výsledné (watermark.png, vodotlač) obrázky v prehliadači.

Ako môžete vidieť, náš druhý obrázok (watermark.png) odkazuje na súbor php image.php, nie na súbor s obrázkom. Tento odkaz vyzerá ako požiadavka GET, kde sa do php súboru prenesú hodnoty dvoch premenných: $main a $watermark.

Pomenujeme druhý súbor „image.php“ a umiestnime doň nasledujúci kód:

create_watermark($main_img_obj, $watermark_img_obj, 66); # zobrazte náš výsledný obrázok v prehliadači - # ale najprv mu dajte vedieť, že ide o hlavičku súboru jpeg("Content-Type: image/jpeg"); header("Content-Disposition: inline; filename=" . $_GET["src"]); imagejpeg($return_img_obj, "", 50); ?>

No a tu sa dostávame do finále. (ZIP, 47,6 kB)

Ak chcete pridať vodoznak na fotografiu bez toho, aby ste sa museli obťažovať editormi obrázkov alebo ho pridávať počas nahrávania fotografií na server, potom je táto lekcia určená práve vám.

V tomto návode vám ukážem, ako pridať vodoznak do obrázka za behu bez toho, aby ste skutočne zmenili pôvodný obrázok. Najprv budete potrebovať obrázok, ktorý použijete ako vodoznak.

Potom vytvoríme hlavičku súboru:

// tento riadok oznámi prehliadaču, že odovzdávame hlavičku obrázka jpg("typ-obsahu: obrázok/jpeg");

Potom vytvoríme obrázok png a získame jeho rozmery:

// vytvorenie vodoznaku png $vodoznak = imagecreatefrompng("vodoznak.png"); // získame šírku a výšku $watermark_width = imagesx($watermark); $watermark_height = imagey($watermark);

To isté urobíme s pôvodným obrázkom, ale len vo formáte jpg. Je to bežné pre fotografie, ktoré sa nahrávajú prostredníctvom formulára. Postupujeme nasledovne:

// vytvorenie obrázku jpg $image_path = "original.jpg"; $obrazok = imagecreatefromjpeg($cesta_obrázku); // získanie rozmeru obrázku $veľkosť = getimagesize($cesta k obrázku);

Teraz musíme na obrázok umiestniť vodoznak:

// umiestnite vodoznak vpravo dole. 5px výplň $dest_x = $veľkosť - $šírka_vodoznaku - 5; $dest_y = $veľkosť - $Výška_vodoznaku - 5;

Potom nastavíme možnosti prelínania pre oba obrázky:

imagealphablending($obrazok, pravda); imagealphablending($watermark, true);

Nakoniec vytvoríme nový obrázok pomocou parametrov:

// vytvorenie nového obrázku imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height); imagejpeg($obrazok);

Je dôležité odobrať:

// uvoľnenie pamäte imagedestroy($image); imagedestroy($watermark);

Na úpravu priehľadnosti vodoznaku môžete použiť Photoshop.

To je všetko s teóriou. Teraz uplatníme naše znalosti v reálnom projekte. Toto všetko je potrebné uložiť do súboru. Napríklad s názvom watermark.php

Hlavička("typ-obsahu: obrázok/jpeg"); // získajte názov obrázku cez GET $image = $_GET["image"]; // vytvorenie vodoznaku $watermark = imagecreatefrompng("watermark.png"); // získanie výšky a šírky vodoznaku $watermark_width = imagesx($watermark); $watermark_height = imagey($watermark); // vytvorenie jpg z pôvodného obrázku $image_path = "/cesta/k/obrázku/priečinku/" . $obrazok; $obrazok = imagecreatefromjpeg($cesta_obrázku); //ak sa niečo pokazí if ($image === false) ( return false; ) $veľkosť = getimagesize($cesta k obrázku); // vložte vodoznak na obrázok $dest_x = $veľkosť - $width_watermarku - 5; $dest_y = $veľkosť - $Výška_vodoznaku - 5; imagealphablending($obrazok, pravda); imagealphablending($watermark, true); // vytvorenie nového obrázku imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height); imagejpeg($obrazok); // uvoľnenie pamäte imagedestroy($image); imagedestroy($watermark);

Teraz, ak chcete zobraziť fotografiu, ktorá bude mať vodoznak bez zmeny pôvodného obrázka, použite nasledujúci kód.

Na internete je veľké množstvo obrázkov, ktoré spravidla odovzdávajú vlastníci stránok alebo používatelia stránok. V závislosti od relevantnosti môže obrázok migrovať z webu na web. Nehovoriac o autorských právach, nie každému majiteľovi stránky sa môže páčiť, že obrázky z jeho stránky sú skopírované na iné zdroje. Ako prostriedok boja proti banálnemu kopírovaniu obrázkov stránok bolo vynájdené umiestňovanie vodoznakov na obrázky, čo naznačuje, že obrázok patrí do konkrétneho zdroja. To môže platiť najmä pre stránky, ktoré majú veľké množstvo jedinečných obrázkov.

Pozrime sa na príklad kódu, ktorý demonštruje umiestnenie vodoznaku na nahrané obrázky.

Hlavné nastavenia sú teda obsiahnuté vo forme konštánt a sú na prvom mieste v kóde:

// cesta k obrázku vodoznaku define("WATERMARK_OVERLAY_IMAGE", "/lab/watermark/watermark.png"); // Kompresia, rozsah 0-100 (ovplyvňuje kvalitu obrazu) define("WATERMARK_OUTPUT_QUALITY", 100); // priečinok so zdrojovými obrázkami define("UPLOADED_IMAGE_DESTINATION", "/lab/watermark/upload/src/"); // priečinok so spracovanými obrázkami define("WATERMARK_IMAGE_DESTINATION", "/lab/watermark/upload/");

Na stránku umiestnime formulár na nahrávanie obrázkov, ktorý sa použije na odosielanie obrázkov na server.
Kód formulára:

Vyberte súbor obrázka:
pôvodný obrázok
"style="max-width: 300px;" />
Obrázok s vodoznakom
"style="max-width: 300px;" />

No a teraz sú najdôležitejšie funkcie na spracovanie obrazu. Umiestnite tieto funkcie pred zobrazením formulára na stránke.

Dve kľúčové funkcie, pomocou jednej sa obrázok nahrá na server, pomocou druhej sa prekryje vodoznak. Možno sú komentáre k funkciám popísané viac než podrobne a bolo by zbytočné písať to isté sem.

Vlastníci stránok (fóra, nástenky atď.) často čelia problému vodoznaku všetkých veľkých obrázkov stránok.

Tento problém je samozrejme možné vyriešiť ručným vytvorením vodoznaku na každom obrázku, avšak po prvé to trvá veľa času a po druhé je potrebné uložiť dve verzie obrázka s vodoznakom a bez neho.

Riešením tohto problému môže byť dynamická aplikácia vodoznaku na obrázok pred jeho prenosom na návštevníka stránky.

Na internete existuje riešenie tohto problému vo forme dvoch súborov, ktorých obsah je uvedený nižšie.
Zdrojový kód súboru ".htaccess".

DirectoryIndex index.php RewriteEngine On RewriteCond %(REQUEST_FILENAME) -f RewriteRule ^(.*)$ /watermark/_watermark.php

Zdrojový kód súboru "_watermark.php"

250) && ($info_o > 250)) ( // Pre obrázky bez alfa kanála // Posledným parametrom funkcie je stupeň nepriehľadnosti vodoznaku imageCopyMerge($out, $watermark, ($info_o-$info_w)/ 2, ($info_o -$info_w)/2, 0, 0, $info_w, $info_w, 25); // Pre obrázky s alfa kanálom // V tomto prípade je priehľadnosť riadená alfa kanálom samotného obrázka // imageCopy($out, $watermark, ($info_o-$info_w)/2, ($info_o-$info_w)/2, 0, 0, $info_w, $info_w); ) prepínač ($info_o) ( prípad 1 : imageGIF($out); break; case 2: imageJPEG($out); break; case 3: imagePNG($out); break; default: return false; ) imageDestroy($out); imageDestroy($original); imageDestroy($watermark); vrátiť true; ) ?>

Riešenie sa scvrkáva na nasledovné: súbor ".htaccess" sa umiestni do adresára so súbormi obrázkov. Okrem toho sa na serveri vytvorí priečinok „watermark“, ktorý obsahuje súbor skriptu „_watermark.php“ a samotný súbor vodoznaku „watermark.png“.

Zároveň som oproti pôvodnej verzii nájdenej na internete urobil menšie zmeny v oboch textových súboroch.

V súbore „.htaccess“ bola do regulárneho výrazu vyhľadávania obrázkového súboru pridaná prípona „jpeg“, ako je tiež bežné.

Skript "_watermark.php" je prepracovaný tak, aby sa vodotlač umiestnila do stredu obrázku (vyžadovalo si to konkrétna riešená úloha) a pribudla možnosť upraviť priehľadnosť vytvorenej vodotlače (komentáre v skripte body vám pomôže nastaviť tento parameter sami).

Pozor si treba dať aj na to, že umiestnením priečinka „vodoznak“ do priečinka s obrázkami, ako radia pôvodné zdroje, nedosiahnete požadovaný výsledok, pretože. v tomto prípade budeme musieť mať v každom priečinku vlastný súbor „.htaccess“ a priečinok „vodoznak“. Je to spôsobené tým, že súbor „.htaccess“ obsahuje absolútne cesty z koreňového adresára stránky k súboru „_watermark.php“. Ak máme teda v každom priečinku s obrázkami samostatný podpriečinok „vodoznak“, ak potrebujeme zmeniť vodoznak (alebo skript, ktorý ho prekrýva na obrázku), budeme musieť vykonať zmeny vo všetkých priečinkoch.

Aby ste predišli tomuto problému, odporúčam vytvoriť priečinok „watermark“ v koreňovom adresári stránky a umiestniť súbor „.htaccess“ do adresárov obrázkov bez toho, aby ste ho museli zakaždým meniť. V tomto prípade, ak chcete zmeniť vodoznak alebo skript, budeme musieť vykonať zmeny iba na jednom mieste na stránke. V tomto prípade môžete vytvoriť rôzne vodoznaky pre rôzne priečinky s obrázkami odkazovaním na rôzne skripty z rôznych súborov „.htaccess“, napríklad „_watermark-1.php“, „_watermark-2.php“ atď.

Ak to zhrnieme, môžeme povedať, že ak chcete použiť vodoznaky na všetky obrázky lokality, musíte si stiahnuť archív priložený nižšie, rozbaliť ho, umiestniť priečinok „vodoznak“ do koreňového adresára lokality, nahradiť súbor vodoznaku “ watermark.png" v ňom s vlastným a umiestnite súbor ".htaccess" do tých adresárov stránky, z ktorých obrázky by mali byť označené vodoznakom.

Z tohto si môžete stiahnuť archív obsahujúci všetky potrebné súbory