www.romver.ru
/ /



( )

Stat'a opisivaet metodiku slojnogo formatirovania izobrajeniy na PHP pod nujniy format nezavisimo ot ix na4al'nix razmerov i orientacii, no vsegda vidat izobrajenia strogo opredelnnogo razmera. V skripte ispol'zuutsa funkcii obrabotki izobrajeniy biblioteki GD. Skript budet polezen dla novostnix saytov i fotogalerey.

Sut' problemi

Rabotaa nad novostnim saytom, a stolknulsa s problemoy xranenia kartinok k stat'am v dvux formatax melkiy (90 na 90 dla zagolovo4nix blokov) i krupniy (218 na skol'ko est'). Novosti xranilis' v baze i dobavlalis' o4en' prosto. S kartinkami vixodilo slojnee. Isxodnie izobrajenia s cifrovoy fotokameri (ili cifrovogo maketa bumajnoy gazeti) zagrujalis' v PhotoShop i obrabativalis' dizaynerom pod nujniy format. Uje sam fakt ru4noy raboti s grafikoy zastavil zadumat'sa ob avtomatizacii. Krome togo, prixodilos' lokal'no soxranat' dve kartinki, a potom zaka4ivat' ix 4erez formu po otdel'nosti, da 4tob e6 i ne pereputat', gde kakaa! Voznikaet izbito4nost', a razmer zanimaemogo mesta stanovilsa vs bol'6e i bol'6e.

Pervie idei

S samogo na4ala raboti nad proektom a znal, 4to su6estvuet takaa ve6', kak ImageMagick dla Perl. Zapustit' etot 4udo-modul' mne tak i ne udalos'. Potom a pere6l na PHP, i ponal, 4to Perl ne sovsem prisposoblen dla takix ve6ey. Na PHP toje mojno formirovat' kartinki s pomo6'u modula GD. On xot' i popro6e budet, no funkcii mas6tabirovania v nm est', 4to i trebovalos'.

Postanovka zada4i napisat' skript, polu4au6iy put' isxodnogo izobrajenia i vivodil bi dannie image/jpeg kartinku nujnogo formata (sm. opisanie protokola HTTP).

Skript mas6tabirovania resize.php

Vxodnie parametri:

  • $f ima fayla v vide path/file.jpg. Mojno bilo pridumat' bolee za6i6nniy sposob adresacii, no sut' algoritma ne menaetsa. Naprimer, predavat' tol'ko nomer stat'i iz bazi, a skript sam bi opredelil mestonaxojdenie kartinki;
  • $q ka4estvo sjatia JPEG;
  • $type format kartinki (v smisle lineynie razmeri) gde v zavisimosti ot zna4enia $type proizvodatsa sleduu6ie deystvia:
    • $type = 0 iz isxodnoy kartinki virezaetsa kvadratnaa seredinka i privoditsa k formatu 90x90 pikseley;
    • $type = 1 isxodnaa kartinka mas6tabiruetsa proporcional'no i privoditsa k 6irine 218 pikseley (opcional'no nanositsa nadpis');
    • $type = 2 isxodnaa kartinka vivoditsa bez izmeneniy.

Posmotrim na4alo skripta:

resize.php

<?php 

// f - ima fayla
// type - sposob mas6tabirovania
// q - ka4estvo sjatia
// src - isxodnoe izobrajenie
// dest - rezul'tiruu6ee izobrajenie
// w - 6irnia izobrajenia
// ratio - koefficient proporcional'nosti
// str - tekstovaa stroka

// tip preobrazovania, esli ne ukazani razmeri
if ($type == 0) $w = 70; // kvadratnaa 70x70
if ($type == 1) $w = 90; // kvadratnaa 90x90
if ($type == 2) $w = 218; // proporcional'naa 6irinoy 218


// ka4estvo jpeg po umol4aniu
if (!isset($q)) $q = 100;

Zdes' kak obi4no proverautsa vxodnie parametri. Vi, kone4no, mojete zadat' bolee jstkie uslovia proverki. Smotrim dal'6e.

// sozdam isxodnoe izobrajenie na osnove 
// isxodnogo fayla i operedelaem ego razmeri
$src = imagecreatefromjpeg($f);
$w_src = imagesx($src);
$h_src = imagesy($src);

header("Content-type: image/jpeg");

V etoy 4asti programmi mi zagrujaem isxodnoe izobrajenie v peremennuu $src. Funkcii imagesx i imagesy opredelaut razmeri isxodnoy kartinki i zapisivaut ix v sootvetstvuu6ie peremennie. Oni nam ponadobatsa dla vi4islenia koefficienta proporcional'nosti. Zdes' je s pomo6'u funkcii header peredam zagolovok Content-type: image/jpeg v brauzer pol'zovatela. Posle etogo on ojidaet, 4to sleduu6iy potok dannix budet jpeg-faylom.

Sleduu6ee uslovie otve4aet za razmer vivodimoy kartinki i neposredstvenno za vivod. Vozmojno, 4to isxodnaa kartinka uje nujnogo razmera. Esli eto ne tak, obrabotaem e. Dla etogo postavim sleduu6ee uslovie:

// esli razmer isxodnogo izobrajenia 
// otli4aetsa ot trebuemogo razmera
if ($w_src != $w)
{

Sleduu6aa 4ast' programmi budet podgonat' kartinku pod 6irinu 218 pikseley (proporcional'noe umen'6enie) dla slu4aa $type=1.

// operacii dla polu4enia pramougol'nogo fayla 
if ($type==2)
{
// vi4islenie proporciy
$ratio = $w_src/$w;
$w_dest = round($w_src/$ratio);
$h_dest = round($h_src/$ratio);

// sozdam pustuu kartinku
// vajno imenno truecolor!, ina4e budem imet' 8-bitniy rezul'tat
$dest = imagecreatetruecolor($w_dest,$h_dest);
$str = "foxweb.net.ru";
imagecopyresized($dest, $src, 0, 0, 0, 0, $w_dest, $h_dest, $w_src, $h_src);

Vna4ale vi4islaem koefficient $ratio, 4tobi srazu vi4islit' razmeri rezul'tiruu6ey kartinki $w_dest i $h_dest. Potom sozdam novuu kartinku $dest s takim je razmerami, eto zagotovka dla mas6tabirovannoy kartinki. Samaa slojnaa 4ast' algoritma funkcia imagecopyresized. V ney a ukazal rezul'tiruu6uu i isxodnuu kartinku, koordinati levogo verxnego ugla dla oboix kartinok (0, 0, 0, 0) i koordinati pravogo nijnego ugla dla oboix kartinok ($w_dest, $h_dest, $w_src, $h_src). Vot oficial'naa spravka na etu funkciu:

imagecopyresized - kopiruet i izmenaet razmeri 4asti izobrajenia

int imagecopyresized ( resource dst_im, resource src_im, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)

imagecopyresized() kopiruet pramougol'nuu 4ast' odnogo izobrajenia v drugoe izobrajenie. Dst_im - rezul'tiruu6ee izobrajenie, src_im - isxodnoe izobrajenie. Esli isxodnie i koordinati raspolojenia i 6irini i visot otli4autsa, budet vipolneno rastajenie ili sjatie fragmenta izobrajenia. Na4alo koordinat - verxniy leviy ugol. Eta funkcia mojet bit' ispol'zovana, 4tobi kopirovat' oblasti v predelax togo je izobrajenia (esli dst_im i src_im sovpadaut), no esli oblasti perekrivaut rezul'tati bit' nepredskazuemim.

Vmesto ne mojno ispol'zovat' imagecopyresampled() - resemplirovanie so sglajivaniem. Kartinka polu4itsa bolee ka4estvennoy. Podrobnee o parametrax funkcii mojno uznat' v dokumentacii na sayte http://php.net/imagecopyresized/ .

Sleduu6aa 4ast' koda sover6enno neobazatel'na. Ona pe4ataet proizvol'nuu nadpis' na gotovoy kartinke. Pri4m, kontrastnim cvetom: na tmnom fone nadpis' budet belaa, na svetlom 4rnaa. Sna4ala opredelim koordinati vivoda teksta (v na6em primere eto vnizu sprava) i tri cveta $white, $black i $gray s pomo6'u funkcii imagecolorallocate. 4tobi opredelit', kakim cvetom pe4atat' nadpis', sravnim cvet to4ki (funkcia imagecolorat), gde budet nadpis', so srednim cvetom $gray. Esli cvet to4ki okajetsa svetlee serogo, to nadpis' budet 4rnogo cveta ($color = $black). Esli cvet to4ki okajetsa temnee serogo, to nadpis' budet belogo cveta ($color = $white). Nakonec opredelaem stroku $str i nanosim e funkciey imagestring, ukazav razmer 6rifta, koordinati, stroku i cvet. Pomnite, 4to eta funkcia vivodit tol'ko latinskie simvoli odnim 6riftom. Xota nikto ne zapre6aet vam pol'zovat'sa TrueType 6riftami, blago takie funkcii est'.

 // opredelaem koordinati vivoda teksta 
$size = 2; // razmer 6rifta
$x_text = $w_dest-imagefontwidth($size)*strlen($str)-3;
$y_text = $h_dest-imagefontheight($size)-3;

// opredelaem kakim cvetom na kakom fone vivodit' tekst
$white = imagecolorallocate($dest, 255, 255, 255);
$black = imagecolorallocate($dest, 0, 0, 0);
$gray = imagecolorallocate($dest, 127, 127, 127);
if (imagecolorat($dest,$x_text,$y_text)>$gray) $color = $black;
if (imagecolorat($dest,$x_text,$y_text)<$gray) $color = $white;

// vivodim tekst
imagestring($dest, $size, $x_text-1, $y_text-1, $str,$white-$color);
imagestring($dest, $size, $x_text+1, $y_text+1, $str,$white-$color);
imagestring($dest, $size, $x_text+1, $y_text-1, $str,$white-$color);
imagestring($dest, $size, $x_text-1, $y_text+1, $str,$white-$color);

imagestring($dest, $size, $x_text-1, $y_text, $str,$white-$color);
imagestring($dest, $size, $x_text+1, $y_text, $str,$white-$color);
imagestring($dest, $size, $x_text, $y_text-1, $str,$white-$color);
imagestring($dest, $size, $x_text, $y_text+1, $str,$white-$color);

imagestring($dest, $size, $x_text, $y_text, $str,$color);
}

Neskol'ko slojnee vigladit 4ast' koda dla polu4enia kvadratnogo fragmenta.

 // operacii dla polu4enia kvadratnogo fayla 
if (($type==0)||($type==1))
{
// sozdam pustuu kvadratnuu kartinku
// vajno imenno truecolor!, ina4e budem imet' 8-bitniy rezul'tat
$dest = imagecreatetruecolor($w,$w);

// virezaem kvadratnuu seredinku po x, esli foto gorizontal'noe
if ($w_src>$h_src)
imagecopyresized($dest, $src, 0, 0,
round((max($w_src,$h_src)-min($w_src,$h_src))/2),
0, $w, $w, min($w_src,$h_src), min($w_src,$h_src));

// virezaem kvadratnuu verxu6ku po y,
// esli foto vertikal'noe (xota mojno toje seredinku)
if ($w_src<$h_src)
imagecopyresized($dest, $src, 0, 0, 0, 0, $w, $w,
min($w_src,$h_src), min($w_src,$h_src));

// kvadratnaa kartinka mas6tabiruetsa bez virezok
if ($w_src==$h_src)
imagecopyresized($dest, $src, 0, 0, 0, 0, $w, $w, $w_src, $w_src);
}

// vivod kartinki i o4istka pamati
imagejpeg($dest,'',$q);
imagedestroy($dest);
imagedestroy($src);
}

Mi ne opredelaem koefficient mas6tabirovania, poskol'ku kartinka budet kvadratnoy zaranee izvestnogo razmera. Po razmeru kartinka mojet bit' trx tipov gorizontal'naa, vertikal'naa i kvadratnaa. V pervix dvux slu4aax nam pridtsa virezat' i mas6tabirovat' kvadratnuu oblast' iz pramougol'noy kartinki. V tret'em prosto mas6tabirovat'.

Nemnogo poasnu konstrukciu: round((max($w_src, $h_src) min($w_src, $h_src)) / 2). Eto virajenie vi4islaet koordinatu x ili y verxnego levogo ugla kvadratnogo bloka (bez raznici dla gorizontal'noy ili vertikal'noy kartinki). Eto vidno na risunkax.

Gorizontal'noe izobrajenie
Vertikal'noe izobrajenie

Obi4no v gorizontal'nix kartinkax (lica, peyzaji, ob&ekti) naibolee informativna central'naa 4ast', a v vertikal'nix (4a6e vsego eto stoa6ie ludi) - naibolee vajna verxnaa 4ast'. 4tobi izmenit' virezaemiy fragment vertikal'noy kartinke, stroku:

imagecopyresized($dest, $src, 0, 0, 0, 0, $w,
$w, min($w_src,$h_src), min($w_src,$h_src));

mojno zamenit' na

imagecopyresized($dest, $src, 0, 0, 0,
round((max($w_src,$h_src)-min($w_src,$h_src))/2),
$w, $w, min($w_src,$h_src), min($w_src,$h_src));

Togda v vertikal'noy kartinke budet brat'sa ne verxnaa 4ast', a srednaa (eto zavisit ot raspolojenia ob&ektov na fotografii). To4no tak je mojno brat' nijnuu 4ast' ili pravuu/levuu 4ast' gorizontal'noy kartinki poeksperimentiruyte s koordinatami. Osobenno etot metod prigoditsa, esli nujno sozdat' kvadratnie prev'u6ki (thumbnails) v odnoy tablice.

V konce vivodim kartinku imagejpeg() i o4i6aem pamat' imagedestroy().

Demonstracia mas6tabirovania

4tobi vam ne prixodilos' lixorado4no menat' vxodnie peremennie v processe otladki na lokal'nom servere, predlagau demo-strani4ku, kotoraa zagrujaet 4etire kartinki raznix formatov. Testovie isxodnie kartinki doljni xranit'sa v teku6ey direktorii pod imenami image1.jpg i image2.jpg. Zdes' je doljen naxodit'sa fayl resize.php, kotoriy na vivode vidat jpeg-izobrajenie.

resize.htm

<html>
<head>
<title></title>
</head>
<body>
<h3 align="center">Demonstracionniy primer mas6tabirovania kartinok</h3>
<table align="center">
<tr align="center" valign="top">
<td>90*90<br><img src="resize1.php?f=av.jpg&t=1&w=90&s=0" border=0></td>
<td>90*90<br><img src="resize.php?f=news114.jpg&type=1" border=0></td>
</tr>
<tr align="center" valign="top">
<td>218*x<br><img src="resize.php?f=av.jpg&type=2" border=0></td>
<td>218*x<br><img src="resize.php?f=news114.jpg&type=2" border=0></td>
</tr>
</table>
</body>
</html>

Prosmotrov6ik kartinok

Etot skript dostato4no prost, on vsego li6' formiruet stranicu, ssilki, osu6estvlaet vsu navigaciu po katalogu kartinok. Vsa rabota po zagruzke kartinok proizvoditsa 4erez resize.php. Ego mojno vzat' za osnovu prostogo veb-al'boma.

preview.php

<html>
<head>
<title></title>
</head>
<body>
<?php

// 4itaem spisok jpg-faylov v massiv list
$list = array();
if ($dir = opendir('.')) // uspe6noe otkritie teku6ey direktorii
{
// perebiraem imena faylov, polu4ennie readdir
while (false !== ($file = readdir($dir)))
{
// otbiraem tol'ko .jpg, otsekaem ssilki '.' i '..'
if ($file != "." && $file != ".." && preg_match("/.jpg/i", $file))
{
$list[] = $file; // pi6em ima fayla v massiv
$i++; // s4t4ik faylov, nujen dla opredelenia granic massiva
}
}
closedir($dir); // zakrivaem direktoriu
}

// peremennie po umol4aniu, polu4ennie 4erez GET
if ($f == '') $f = $list[0]; // esli fayl ne ukazan, berm perviy iz spiska
if ($num == '') $num = 0; // nomer zapro6ennogo fayla
if ($type == '') $type = 1; // tip po umol4aniu "sredniy"

// zagolovo4ek - ima fayla
echo "<p>$list[$num]</p>n";

// opredelaem ssilku s kartinki analizirua type
// 6lkaa po kartinke fayl budet perezagrujat'sa s novim type
if ($type == 0) $link = "href="?type=1&num=$num" title="pokazat' 90"";
if ($type == 1) $link = "href="?type=2&num=$num" title="pokazat' 218"";
if ($type == 2) $link = "href="?type=full&num=$num" title="pokazat' ves'"";
if ($type == "full") $link = "href="?type=0&num=$num" title="pokazat' 70"";
echo "<a $link><img src="resize.php?f=$list[$num]&type=$type" border=0></a>";

// opredelaem, kraynie li elementi spiska
$num1 = $num-1;
if ($num1<0) $num1 = $i-1; // esli num vi6el za 0, perevodim ego na 0
$num2 = $num+1;
if ($num2>$i-1) $num2 = 0; // esli num vi6el za i, perevodim ego na i-1

// ssilki navigacii
echo "<br><a href="?type=$type&num=$num1">pred</a>
<a href="?type=$type&num=$num2">sled</a>";

?>
</body>
</html>

Dumau, 4to skript dostato4no xoro6o kommentirovan, potomu ob&asnu li6' sut'. Vna4ale proisxodit zagruzka imn jpg-faylov v teku6em kataloge v massiv $list. Potom zagrujaem kartinku s nujnimi parametrami iz skripta resize.php, pri4m na kartinke visit ssilka na e uveli4ennuu kopiu (izmenaetsa parametr $type). V konce formiruem ssilki na sleduu6uu i predidu6uu kartinku. Vot i vs. V ka4estve testirovania nakidayte v katalog skripta dva desatka fotografiy i vi polu4ite prosten'kuu smotrelku. Navigaciu, kone4no, mojno uslojnit', no togda skript uje budet slojnen'kim.

Po4emu ne rabotaet GD?

A otlajivau skripti v Windows, poetomu ob&asnu re6enie problemi imenno dla etoy OS. Skoree vsego, pri4ina nerabotosposobnosti skripta v otsutstvii modula php_gd.dll (ili bolee noviy php_gd2.dll). Otkroyte direktoriu s interpretatorom PHP, sozdayte direktoriu extensions, esli e net. Naydite vi6eukazanniy modul' on est' v polnix distributivax PHP. Propi6ite v php. ini (lejit v c: windows) stro4ku extension = php_gd2.dll (a zaodno i extension_dir = "c:phpextensions", esli takoy net). Puti mogut bit' drugimi. Posle etogo vs doljno zarabotat'. Ne sme6ivayte moduli php_gd.dll i php_gd2.dll interpretator budet rugat'sa na dublirovanie funkciy v bibliotekax.

Zaklu4enie

Vot takie interesnie ve6i mojno sdelat' pri pomo6i pari grafi4eskix funkciy zato kakaa ekonomia na izgotovlenii i xranenii dubliruu6ix kartinok. Ne PhotoShop kone4no, no dla massovogo primenenia eto samoe to. Kartinok na sayte o4en' mnogo, ka4estvenno ix vivodit' neobazatel'no, glavnoe 4tobi bistro i prosto. Skript polu4ilsa ne o4en' universal'niy, no s moey zada4ey on spravlaetsa prekrasno. Sleduet otmetit' tonkuu raznicu mejdu funkciami imagecopyresized i imagecopyresampled. Pervaa prosto izmenaet razmer kartinki bez sglajivania, ona rabotaet bistro, no rezul'tat bol'6ie iskajenia. Vtoraa funkcia resemplirovanie, izmenenie razmerov so sglajivaniem. Rabotaet ona namnogo medlennee, no kartinka polu4aetsa 4istoy, kak v professional'nix grafi4eskix paketax. O resemplirovanii mojno po4itat' zdes'. Vibirat' sposob sleduet isxoda iz va6ix potrebnostey bistree ili ka4estvennee. Vozmojno, vi realizuete drugie idei: zadavat' proizvol'niy razmer x i y, nali4ie ili otsutstvie nadpisi, format vixodnogo fayla, risovanie ramo4ki, vodanix znakov, podpisi na kartinke 6riftami TrueType, vivod kartinki-zaglu6ki v slu4ae o6ibki.

Esli kto zametil kakie-to glupie ili sme6nie mesta v programmax, jdu va6ix kommentariev.

Demonstraciu fotogalerei na osnove opisannoy metodiki mojno uvidet' na http://foxweb.net.ru/photo/.

Sayt, dla kotorogo eto vs izna4al'no razrabativalos' 58region.ru/. Pravda tam ispol'zuetsa uslojnnniy variant resize.php rabotaet s trema tipami faylov, vivodit nadpis' po jelaniu i vivodit kartinku-zaglu6ku v slu4ae otsutstvia isxodnogo fayla.

Proverit' rabotosposobnost' skriptov v onlayne i ska4at' isxodniki obeix versiy mojno tut foxweb.net.ru/test/resize/.

Vsegda jdu va6ix kommentariev. Uda4i!


3
  ,
:
. +7(812) 984 5721

e-mail
icq 415547094  romver  mail.ru  romverinbox.ru
1997 - 2020 romver.ru

Display Pagerank