Zmenšování obrázků
Školení, která pořádám ![](feed-icon.gif)
Jednu funkci na změnu velikosti obrázků jsem už uváděl. Pokud je zdrojový obrázek menší než maximální povolené rozměry, může být zvětšení, které daná funkce provede, nežádoucí. Pokud si navíc chceme do databáze poznamenat výsledné rozměry, tak bychom je potřebovali vrátit. A pokud soubor navíc chceme pojmenovat podle ID přidruženého záznamu, tak bude nejšikovnější funkci rozdělit do dvou:
<?php
/** Vrácení rozměrů obrázku po zmenšení
* @param string název zmenšovaného souboru
* @param int maximální šířka výsledného obrázku, 0 pokud na ní nezáleží
* @param int maximální výška výsledného obrázku, 0 pokud na ní nezáleží
* @return array ($width, $height) výsledná šířka a výška
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function image_shrink_size($file_in, $max_x = 0, $max_y = 0) {
list($width, $height) = getimagesize($file_in);
if (!$width || !$height) {
return array(0, 0);
}
if ($max_x && $width > $max_x) {
$height = round($height * $max_x / $width);
$width = $max_x;
}
if ($max_y && $height > $max_y) {
$width = round($width * $max_y / $height);
$height = $max_y;
}
return array($width, $height);
}
/** Převzorkování obrázku GIF, PNG nebo JPG
* @param string název zmenšovaného souboru
* @param string název výsledného souboru
* @param int šířka výsledného obrázku
* @param int výška výsledného obrázku
* @return bool true, false v případě chyby
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function image_resize($file_in, $file_out, $width, $height) {
$imagesize = getimagesize($file_in);
if ((!$width && !$height) || !$imagesize[0] || !$imagesize[1]) {
return false;
}
if ($imagesize[0] == $width && $imagesize[1] == $height) {
return copy($file_in, $file_out);
}
switch ($imagesize[2]) {
case 1: $img = imagecreatefromgif($file_in); break;
case 2: $img = imagecreatefromjpeg($file_in); break;
case 3: $img = imagecreatefrompng($file_in); break;
default: return false;
}
if (!$img) {
return false;
}
$img2 = imagecreatetruecolor($width, $height);
imagecopyresampled($img2, $img, 0, 0, 0, 0, $width, $height, $imagesize[0], $imagesize[1]);
if ($imagesize[2] == 2) {
return imagejpeg($img2, $file_out);
} elseif ($imagesize[2] == 1 && function_exists("imagegif")) {
imagetruecolortopalette($img2, false, 256);
return imagegif($img2, $file_out);
} else {
return imagepng($img2, $file_out);
}
}
// použití
list($width, $height) = image_shrink_size($_FILES["obrazek"]["tmp_name"], 760, 760);
if ($width && $height && mysql_query("INSERT INTO obrazky (jmeno, sirka, vyska) VALUES ('" . $_FILES["obrazek"]["name"] . "', $width, $height)")) {
$filename = mysql_insert_id() . "." . pathinfo($_FILES["obrazek"]["name"], PATHINFO_EXTENSION);
image_resize($_FILES["obrazek"]["tmp_name"], $filename, $width, $height);
}
?>
Diskuse
Michal:
Jelikoz zmensovani obrazku je vypecetne celkem narocne, je velice vhodne vyledne zmensene obrazky ukladat na serveru na disk.
Termiter:
A pokud ti hosting příliš omezí přidělenou paměť, nebo je obrázek moc velký (oroginál foto), tak to moc nefunguje.
Z tohoto důvodu při práci s fotografiemi používám náhled v EXIFu.
ALe jinak pro menší obrázky je to v pohodě.
lukas:
S timhle problemem se dost casto setkavam. Nijak se mi dopredu zjistit, jestli gd funkce ma dost pameti a pri zavolani nespadne. Jedine, cim tenhle problem trochu omezuju je, ze si pres ini_set zvetsim velikost dostupne pameti na 32 MB a pak je obtiznejsi vytvorit obrazek, ktery nebude mozne zpracovat. Nicmene pokud se to i pres to stane, tak cely skript konci chybou a stranky, kde je ten obrazek vlozeny, se nezobrazi (popr. se zobrazi jen cast, zalezi na tom, jak se zastaveni skriptu projevi).
Jinak resamplovane obrazky si ukladam na disk vetsinou ve formatu puvodnijmeno_w200_h133.jpg (kde 200 a 133 muzou byt odlisne).
lukas:
Jinak, pokud se pred zminene funkce da @ tak to taky spadne.
karel:
nezapomeň ještě taky, že když zmenšuješ GIF s průhlednou barvou, musíš touto barvou nejprve vyplnit cílový obrázek a nastavit ji jako průhlednou
Lampicka:
osobne bych GD asi nepouzil; myslim ze podstatne lepsi vysledky se daji dosahnout pomoci imagicku/magickwandu
Filip:
Konkretne treba to, ze na tech x radku ktere tam mas staci jeden radek exec('....');
Navic moznosti imagemagicku co se tyce konverzi obrazku jsou diametralne odlisne od moznosti gd
vice: man convert
ondra:
pri zmenseni bych rad vyuzil nejakou funkci pro zostreni fotky, ale nepodarilo sem mi nic takoveho v php najit, zmensenim (treba nahledy fotek) dost kvalita trpi
martin:
Kdysi jsem zkoušel tento skript
http://vikjavev.no/computing/ump.php , ale Imagemagick je mnohem lepší, výkonnější. Pomocí volby -sharpen se jím dá i ostřit (resp. měnit kontrast v hranách - zlepšení ostrosti za cenu horší kontrasti).
ondra:
jeste jednou, funkce imagejpeg ma treti parametr pro kvalitu vysledneho jpg, tim se da regulovat vysledna velikost a kvalita samozrejme, ale zostreni to neni
MiSHAK:
Hm... čekal jsem něco bombastického (asi jsem naivní), ale tento příklad se hodí.
Abych se přidal :) "V minulosti jsem "taky" něco podobného řešil."
No max_x = 0 stačí napsat max_x, protože zatím nikde překladač neuhádné jaky parametr máme na mysli.
Možná by se hodilo určit v parametrech i výstupní formát...
Třeba pomocí dalšího parametru img_type. Například u malých fotek ( 50x50 nebo 100x100 atp.) by bylo jpg větší než třeba png. Je to jen domněnka...
Jakub Vrána
:
$max_x = 0, $max_y = 0 znamená, že oba parametry jsou nepovinné. Výstupní formát se nastavuje podle vstupního, což je obvykle ta nejlepší volba.
Juraj:
Co sa tyka formatov, na ukladanie fotiek je najlepsi jpeg i u velkosti 50x50. Format png(8 bit) doporucujem pouzivat iba u graf. materialov s poctom farieb < 256 (napr. zoscanovane dokumenty).
Abulafia:
A nechce se náhodou někomu napsat nějakou chytrou a jednoduchou fci na doostřování fotek? Co si budem povídat - když fotografii zmenšujete a nedoostříte, tak vám vypadnou pěkný blafy :-)
Jája:
Při použití této funkce se mi obrázky občas uloží nedodělané. Kus je obrázek OK a kus jen šedivej. Nevíte čím to je a jak se toho zbavit?
Pepino:
Nevím jestli jsem něco udělal špatně, ale ta první funkce na získání velikosti náhledu, mi blbne například při velikosti obrázku 384x477. Vrátilo mi to asi jenom výšku, šířka byla 0.
kachnak:
zdravim prosim vas tato funkcia imagecopyresized ak zmensi obrazok tak je taky "kockaty" hranaty nezaostreny a ked zmensim obrazok v PC pomocou irfanview softu tak je ovela krajsi ako ked sa zmensi na servery s atributom kvality 100 ( imagejpeg($thumb,"$meno",100); )... neviete ako spravit aby bol aj ten na servery po zmenseni pekny ako cez soft v pc..
ten na servery po zmenseni zabera ovela viac KB ako ten povodny vacsieho rozslisenia pred uploadom na net.. a i ked zabera viac kb je ovela skaredsi... :(
dakujem
jakub:
mam stejny problem a reseni jsem este nenasel
jde to nejvice vydet na nocnich fotografii...je tam mnoho sumu
jakub:
odpovim si sam :) .. nasel jsem fci imagecopyresampled, ktera dava vyrazne lepsi vysledky, bohuzel jsem ale take zaznamenal jeji vetsi narocnost na vypocetni vykon
Jakub Vrána
:
Je to tak. Jen nevím, proč to píšete pod ukázku kódu, která používá imagecopyresampled() od samého začátku :-).
temistokles:
Ono je všeobecne vhodnejšie po zistení rozmerov sa rozhodnúť, či najskôr nebude vhodné obrázok zmenšiť pomocou imagecopyresized() a až následne pomocou imagecopyresampled(). Kvalitou je výsledok skoro rovnaký a pamäťová náročnosť podstatne klesne. Je už len potrebné rozhodnúť sa, od akej veľkosti sa podstúpi medzikrok s imagecopyresized().
Jakub Vrána
:
Rozhodně bych neřekl, že je výsledek skoro stejný. U funkce imagecopyresized() jsou výsledky naopak dost žalostné a odpovídají zhruba zmenšení obrázku v prohlížečích uvedením jiných rozměrů.
J4cker:
nefunguje mi $file_in jsem zadal $file_in = $nazev_obrazku_uploadovaneho a nejde potreboval bych vice porad 316-071-469 dík
Vigez:
Je tato myslienka spravna?
<?php
if ($max_x && $width > $max_x) {
$height = round($height * $max_x / $width);
$width = $max_x;
}
if ($max_y && $height > $max_y) {
$width = round($width * $max_y / $height);
$height = $max_y;
}
?>
Totiz ak je obrazok nizsi a sirsi, zmensi ho na vysku $max_y a sirku vypocita proporcialne, cize zrejme viac ako 100px.
Skusal som si spravit priklad a nastava tam tento problem.
Jakub Vrána
:
Tak ten příklad uveď... První větev zaručí, že obrázek nebude širší než $max_x. Druhá větev může šířku pouze zmenšit (protože $height > $max_y => $max_y/$height < 1).
Vigez:
Tu je spominany priklad:
<?php
if(($maxx >= $imagesize[0]) && ($maxy >= $imagesize[1]))
{
@copy($inputfile,$outputfile);
@chmod($outputfile,0644);
}
else
{
if($maxx && $imagesize[0]>$maxx)
{
$height = round($imagesize[1] * $maxx / $imagesize[0]);
$width = $maxx;
}
if($maxy && $imagesize[1]>$maxy)
{
$width = round($imagesize[0] * $maxy / $imagesize[1]);
$height = $maxy;
}
switch ($imagesize[2])
{
case 1: $img = imagecreatefromgif($inputfile); break;
case 2: $img = imagecreatefromjpeg($inputfile); break;
case 3: $img = imagecreatefrompng($inputfile); break;
}
$img2 = imagecreatetruecolor($width, $height);
imagecopyresampled($img2, $img, 0, 0, 0, 0, $width, $height, $imagesize[0], $imagesize[1]);
...
}
?>
...
Popis: $maxx - maximalna sirka
$maxy - maximalna vyska
$imagesize[0] - skutocna sirka obrazku
$imagesize[1] - skutocna vyska obrazku
Jakub Vrána
:
Čeho to je prosímtě příklad? Chtěl jsem, abys uvedl čtyři čísla ($max_x, $max_y, $width, $height), pro která můj kód podle tebe nefunguje.
Vigez:
$max_x=100;
$max_y=100;
$width=420;
$height=70;
Ak sirka $width prekracuje hranicu $max_x a pritom je vyska $height mensia ako $max_y narazim na neuspech.
Jakub Vrána
:
V čem spočívá ten neúspěch? Pro tento vstup vrátí můj kód správný výstup (100, 17).
Jakub Vrána
:
Chyba spočívá v tom, že místo $height>$max_y používáš $imagesize[1]>$maxy.
DrMizerie:
Mám problém s ukládáním a následným zmenšováním pro ukládání požívám skript z vašich stránek:
<?php
$koncovky = array('jpg', 'jpeg', 'png', 'gif');
$chybao = "";
if (!$_FILES || $_FILES["fotka1"]["error"] == UPLOAD_ERR_INI_SIZE) {
$chybao = "Soubor je příliš velký, maximální velikost je " . ini_get('upload_max_filesize') . ".\n";
} elseif ($_FILES["fotka1"]["error"] == UPLOAD_ERR_NO_FILE) {
$chybao = "Nevybrali jste soubor, který chcete nahrát.\n";
} elseif ($_FILES["fotka1"]["error"]) {
$chybao = "Soubor se nepodařilo nahrát, kontaktujte prosím správce serveru.\n";
} elseif (!in_array(strtolower(pathinfo($_FILES["fotka1"]["name"], PATHINFO_EXTENSION)), $koncovky)) {
$chybao = "Koncovka souboru musí být jedna z: " . implode(", ", $koncovky) . ".\n";
} elseif (!($imagesize = getimagesize($_FILES["fotka1"]["tmp_name"])) || $imagesize[2] > 3 ) {
$chybao = "Typ obrázku musí být JPG, PNG nebo GIF.\n";
} else {
move_uploaded_file($_FILES["fotka1"]["tmp_name"], "Photo/" . $_FILES["fotka1"]["name"]);
}
if ($chybao) echo "<span style=\"color: red\"><p><b>Došlo k chybě!!!!!</b>
<p>$chybao<p>Opravte tyto chyby a odešlete formulář znovu.<p></span>";
?>
A když použiji vaše funkce pro zmenšení a skript:
<?php
IF (!$chybao){
list($width, $height) = image_shrink_size($_FILES["fotka1"]["tmp_name"], 150, 150);
If ($width && $height){
$filename = "./Photo/" .$_FILES["fotka1"]["name"] . "_X" . pathinfo($_FILES["fotka1"]["name"], PATHINFO_EXTENSION);
image_resize($_FILES["fotka1"]["tmp_name"], $filename, $width, $height);
}
}
?>
Tak to hlásí neustále chybu....Neveděl by někdo kde je chyba nebo co dělám špatně? Díky za odpověď
Jakub Vrána
:
Kdybys aspoň napsal, jakou chybu to hlásí. Potom by třeba někomu stálo za to se tvým problémem zabývat.
DrMizerie:
Warning: getimagesize() [function.getimagesize]: Unable to access /tmp/phpmW5xye in /home/www/.... on line 38
Warning: getimagesize(/tmp/phpmW5xye) [function.getimagesize]: failed to open stream: No such file or directory in /home/www/.... on line 38
Štěpán Svoboda:
Tohle nemá nic společného se zmenšováním obrázků, nýbrž s nastavením oprávnění souborového systému. Obrázek se Vám po upoloadu uloží pod dočasným jménem (/tmp/phpmW5xye), který webový server (PHP) nemůže přečíst.
maylow:
mam problem. nevite cim to muze byt, že všechny gify i png se najednou tmavujou? mám pocit, ze driv nedelalo. teprve pak jsem objevil tento clanek a dělá to uplne to samé. stalo se to taky nekomu?
lubo:
Skús ppoužiť ImageCreateTrueColor
Petr Chmelar:
Toz jsem si s tim chvili taky hral a vymyslel (prevzal ode vseho to nejlepsi :) tuhle funkci... Jinak souhlasim a jeste ji rozdelim na 2 ;)
Pokud myslite, ze nefunguje, piste na chmelarp at fit vutbr cz (se zavinacem a teckama).
Petan
<?php
$file_in = "img.jpg";
// get width, height
if (! imagemagic($file_in, null, 400, 300) ) {
print("<b>Nevyslo to...</b><br />");
}
/**
* need GD library (first PHP line WIN: dl("php_gd.dll"); UNIX: dl("gd.so");
* www.boutell.com/gd/
* interval.cz/clanky/php-skript-pro-generovani-galerie-obrazku-2/
* cz.php.net/imagecopyresampled
* www.linuxsoft.cz/sw_detail.php?id_item=871
* www.webtip.cz/art/wt_tech_php/liquid_ir.html
* php.vrana.cz/zmensovani-obrazku.php
* diskuse.jakpsatweb.cz/
*
* @param string $file_in Vstupni soubor (mel by existovat)
* @param string $file_out Vystupni soubor, null ho jenom zobrazi (taky kdyz nema pravo se zapsat :)
* @param int $width Vysledna sirka (maximalni)
* @param int $height Vysledna vyska (maximalni)
* @param bool $crop Orez (true, obrazek bude presne tak velky), jinak jenom Resample (udane maximalni rozmery)
* @param int $type_out IMAGETYPE_type vystupniho obrazku
* @return bool Chyba kdyz vrati false
*/
function imagemagic($file_in, $file_out=null, $width=null, $height=null, $crop=null, $type_out=null) {
if ($file_in !=="" && File_Exists($file_in))
{
// get width, height, IMAGETYPE_type
list($w, $h, $type) = GetImageSize($file_in); //array of width, height, IMAGETYPE, "height=x width=x" (string)
// print("Input: ". image_type_to_mime_type($type) ." $w x $h<br>");
// vyber funkce pro nacteni vstupu
switch($type)
{
case IMAGETYPE_JPEG: $imgIn = 'ImageCreateFromJPEG'; break;
case IMAGETYPE_PNG : $imgIn = 'ImageCreateFromPNG'; break;
case IMAGETYPE_GIF : $imgIn = 'ImageCreateFromGIF'; break;
case IMAGETYPE_WBMP: $imgIn = 'ImageCreateFromWBMP'; break;
default: return false; break;
}
// jaky typ chcem vyrobit? jestli je to fuk, tak ten samy...
if ($type_out == null) { // ...krom Wbitmapy, ta je blba :)
$type_out = ($type == IMAGETYPE_WBMP) ? IMAGETYPE_PNG : $type;
}
switch($type_out)
{
case IMAGETYPE_JPEG: $imgOut = 'ImageJPEG'; break;
case IMAGETYPE_PNG : $imgOut = 'ImagePNG'; break;
case IMAGETYPE_GIF : $imgOut = 'ImageGIF'; break;
case IMAGETYPE_WBMP: $imgOut = 'ImageWBMP'; break; // bitmapa je blbost
default: return false; break;
}
// toz, jak ma byt vysledek veliky?
if ($width == null || $width == 0) { // neni zadana sirka
$width = $w;
}
else if ($height == null || $height == 0) { // neni zadana vyska, ale sirka jo... hmm, toz je dam stejne :)
$height = $width;
}
if ($height == null || $height == 0) { // neni zadana vyska, ale sirka taky ne :)
$height = $h;
}
// jestli se ma jenom zmensovat...
if (!$crop) { // prepocti velikost - nw, nh (new width/height)
$scale = (($width / $w) < ($height / $h)) ? ($width / $w) : ($height / $h); // vyber mensi pomer
$src = array(0,0, $w, $h);
$dst = array(0,0, floor($w*$scale), floor($h*$scale));
}
else { // bude se orezavat
$scale = (($width / $w) > ($height / $h)) ? ($width / $w) : ($height / $h); // vyber vetsi pomer a zkus to nejak dopasovat...
$newW = $width/$scale; // jak by mel byt zdroj velky (pro poradek :)
$newH = $height/$scale;
// ktera strana precuhuje vic (kvuli chybe v zaokrouhleni)
if (($w - $newW) > ($h - $newH)) {
$src = array(floor(($w - $newW)/2), 0, floor($newW), $h);
}
else {
$src = array(0, floor(($h - $newH)/2), $w, floor($newH));
}
$dst = array(0,0, floor($width), floor($height));
}
// print("posX\t posY\t widt\t heig\t - transformation:<br>"."$src[0]\t $src[1]\t $src[2]\t $src[3]\t <br>"."$dst[0]\t $dst[1]\t $dst[2]\t $dst[3]\t <br>");
// print("Output: ". image_type_to_mime_type($type) ." $dst[2] x $dst[3]<br>");
// proved resampling...
if (@$image1 = $imgIn($file_in))
{
$image2 = ImageCreateTruecolor($dst[2], $dst[3]);
ImageCopyResampled($image2, $image1, $dst[0],$dst[1], $src[0],$src[1], $dst[2],$dst[3], $src[2],$src[3]);
// pokud se ma pouze zobrazit, dej vedet co prijde (MIME type)... (tedko uz se snad nic nepokazi)
if ($file_out == null) {
header("Content-type: ". image_type_to_mime_type($type_out));
}
// set jpeg/png quality to 85 before saving
if ($type_out == IMAGETYPE_JPEG || $type_out == IMAGETYPE_PNG) {
$imgOut($image2, $file_out, 85);
}
else { // save the image
$imgOut($image2, $file_out);
}
ImageDestroy($image1); // free memory
ImageDestroy($image2);
return true; // tohle je jediny misto, kde se da vratit uspech
}
}
return false;
}
?>
Honza:
Ahoj, poradil by mi někdo jak z tohodle posledního skriptu od Petra dostanu kopii obrázku resp. nově změněný obrázek
něco jako return copy (file_in, $file_out);
SeET:
no sice asi nechápu jakou kopii chces ale poduk myslíš jak nový obrázek uložit, tak tady je řešení :
<?php
$file_in = "img.jpg";
// get width, height
$nazev_noveho = "img2.jpg";
if (! imagemagic($file_in, $nazev_noveho, 400, 300) ) {
print("<b>Nevyslo to...</b><br />");
}
?>
......
je to puze zmenseny obrazek ve stejnem formatu.
Stefan:
Použil som to takto:
<?php
include_once("zmensimg.php");
?>
<HTML><HEAD>
<META content="text/html; charset=windows-1250" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 8.00.6001.18854">
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<IMG border=0 hspace=0 align=baseline src="
<?php imagemagic("hus_hody.gif",null, 0, 100);?>">;
</BODY></HTML>
zobrazuje mi vsak namiesto obrázku <„2 9ćtĐŤ 5 ĆĆ4ň ÜčrĂ <ęňOŽl<ÂÍ .l! ät Ę ä( A"ˇt A Ęt †•Ćx ... atď... Pritom tam je header ... atď... V čom je problém? Ako to použiť ako funkciu na zobrazenie zmenšeniny? Ďakujem
Jirka:
Díky, výborný script
Traverz:
Tento script mi nefunguje pre znacne sirsie obrazky napr.: sirka: 760px a vyska: 151px
Ine obrazky funguju perfektne az na obrazky s vacsiou velkostou, pri ktorych sa zmensenina neulozi ale vytvori iba ciernu zmenseninu. No toto nemusi byt chyba scriptu.
Zial doposial som nevedel vyriesit problem so sirsimi obrazkami.
Neviete niekto pomoct?
Jakub Vrána
:
Dej odkaz na obrázek, se kterým jsou problémy, a uveď přesný kód, který pro zmenšení používáš (musí obsahovat stanovení výsledných rozměrů).
Teprve potom máš šanci, že se tvým dotazem bude někdo zabývat.
Traverz:
Obrazok:
http://geryon.org/adds/gallery/normal/14_goticky-kriz.jpgZdrojovy kod:
<?php
$path="adresar_full/"; //adresar pre plne nahlady
$pathmini="adresar_mini/"; //adresar pre zmenseniny
$maxsize=524288; //maximalna velkost v b
$inputfile = $path.$name; //vstupny udaj
$outputfile = $pathmini.$name; //vystupny udaj
$maxx=100; //maximalny rozmer sirky
$maxy=100; //maximalny rozmer vysky
$imagesize = @getimagesize($inputfile);
if($imagesize[0] && $imagesize[1])
{
if(($maxx >= $imagesize[0]) && ($maxy >= $imagesize[1]))
{
@copy($inputfile,$outputfile);
@chmod($outputfile,0644);
}
else
{
if($maxx && $imagesize[0]>$maxx)
{
$height = round($imagesize[1] * $maxx / $imagesize[0]);
$width = $maxx;
}
if($maxy && $imagesize[1]>$maxy)
{
$width = round($imagesize[0] * $maxy / $imagesize[1]);
$height = $maxy;
}
switch ($imagesize[2])
{
case 1: $img = imagecreatefromgif($inputfile); break;
case 2: $img = imagecreatefromjpeg($inputfile); break;
case 3: $img = imagecreatefrompng($inputfile); break;
}
$img2 = imagecreatetruecolor($width, $height);
imagecopyresampled($img2, $img, 0, 0, 0, 0, $width, $height, $imagesize[0], $imagesize[1]);
if ($imagesize[2] == 2)
{
imagejpeg($img2,$outputfile);
}
elseif ($imagesize[2] == 1 && function_exists("imagegif"))
{
imagetruecolortopalette($img2, false, 256);
imagegif($img2,$outputfile);
}
else
{
imagepng($img2,$outputfile);
}
ImageDestroy($img);
ImageDestroy($img2);
@chmod($outputfile,0644);
}
}
?>
Toto je kod, ktory pouzivam, prosim ak by mi vedel niekto pomoct, budem mu velmi povdacny, lebo tento problem ma valmi trapi.
Jakub Vrána
:
Chyba spočívá v tom, že místo $height>$max_y používáš $imagesize[1]>$maxy.
Traverz:
Mozno je to neprofesionalna otazka, ale neviem sa dopatrat k spravnemu rieseniu.
Je nejaky vyrazny rozdiel medzi $imagesize[1] ($imagesize = @getimagesize($inputfile);) a $height (list($width, $height) = getimagesize($file_in);) ?
Jakub Vrána
:
Zásadní rozdíl spočívá v tom, že proměnná $height se o kousek výš může nastavit na jinou hodnotu než $imagesize[1].
Traverz:
Skusal som si zostavit novy script a tato zmena nepriniesla ziaden uspech, tiez nepredpokladam, ze by sa premenna prepisala.
machajda:
jak se ty skripty používaj? teprve sem začal
máca:
Nevím jak vám, ale tenhle kód (jak jsem již tušil dle náhledu) mi nevyřešil problém s žalostnou kvalitou zmenšenin obrázků typu gif a černým pozadím u obrázků typu png.
Jakub Vrána
:
Pro zmenšování paletových obrázků se je vyplatí nejdříve převést na plné barvy a potom zase zpátky. Průhlednost respektuje funkce imagecopymerge().
Jirka:
Mohl by jste rozvést tu informaci více uvedením příkladu, jak se zbavit toho černého pozadí u formátu PNG. např. jak tam dát pozadí bílé ?
Ma.Cizek:
Já mám též problém při ukládání do databáze se mi všechny proměné i data z originálního obrázku uloží ale z proměné $file_out kdy by měla být data ze zmensěného obrázku se nic neuloží možná ta proměná něco udělala ale uložila jen 0b. Nemohl by mi někdo poradit.
<?php
require('xxx.php'); // Připojení k MySQL serveru
// Pokud uživatel nevybral žádný soubor, nastane chyba.
if($_FILES['soubor']['error']) {
die('Chyba při získávání souboru');
}
$jmeno = $_POST['jmeno'];
$obsah = $_FILES['soubor']['tmp_name']; // Umístění dočasného souboru
$nazev = $_FILES['soubor']['name']; // Původní název
$mime = $_FILES['soubor']['type']; // MIME typ
// Načteme obsah dočasného souboru
$file_in = implode('', file("$obsah"))
or die("Nelze načíst dočasný soubor $obsah");
/** Vrácení rozměrů obrázku po zmenšení
* @param string $file_in název zmenšovaného souboru
* @param int [$max_x] maximální šířka výsledného obrázku, 0 pokud na ní nezáleží
* @param int [$max_y] maximální výška výsledného obrázku, 0 pokud na ní nezáleží
* @return array ($width, $height) výsledná šířka a výška
* @copyright Jakub Vrána, http://php.vrana.cz
*/
function image_shrink_size($obsah, $max_x = 0, $max_y = 180) {
list($width, $height) = getimagesize($obsah);
if (!$width || !$height) {
return array(0, 0);
}
if ($max_x && $width > $max_x) {
$height = round($height * $max_x / $width);
$width = $max_x;
}
if ($max_y && $height > $max_y) {
$width = round($width * $max_y / $height);
$height = $max_y;
}
return array($width, $height);
}
/** Převzorkování obrázku GIF, PNG nebo JPG
* @param string $file_in název zmenšovaného souboru
* @param string $file_out název výsledného souboru
* @param int $width šířka výsledného obrázku
* @param int $height výška výsledného obrázku
* @return bool true, false v případě chyby
* @copyright Jakub Vrána, http://php.vrana.cz
*/
function image_resize($obsah, $file_out, $width, $height) {
$imagesize = getimagesize($obsah);
if ((!$width && !$height) || !$imagesize[0] || !$imagesize[1]) {
return false;
}
if ($imagesize[0] == $width && $imagesize[1] == $height) {
return copy($obsah, $file_out);
}
switch ($imagesize[2]) {
case 1: $img = imagecreatefromgif($obsah); break;
case 2: $img = imagecreatefromjpeg($obsah); break;
case 3: $img = imagecreatefrompng($obsah); break;
default: return false;
}
if (!$img) {
return false;
}
$img2 = imagecreatetruecolor($width, $height);
imagecopyresampled($img2, $img, 0, 0, 0, 0, $width, $height, $imagesize[0], $imagesize[1]);
if ($imagesize[2] == 2) {
return imagejpeg($img2, $file_out);
} elseif ($imagesize[2] == 1 && function_exists("imagegif")) {
imagetruecolortopalette($img2, false, 256);
return imagegif($img2, $file_out);
} else {
return imagepng($img2, $file_out);
}
}
// použití
$dc=Date("Y-m-d H:i:s");
$da=Date("d.m. Y H:i:s");
list($width, $height) = image_shrink_size($_FILES["obrazek"]["tmp_name"], 760, 760);
if (mysql_query (sprintf ("INSERT INTO obrazky (mime, obsah, mini, jmeno, datum, datim) VALUES ('$mime', '%s', '%s', '$nazev', '$da', '$dc')",mysql_escape_string("$file_in"),mysql_escape_string("$file_out")))) {
$filename = mysql_insert_id() . "." . pathinfo($_FILES["obrazek"]["name"], PATHINFO_EXTENSION);
image_resize($_FILES["obrazek"]["tmp_name"], $filename, $width, $height);
}
?>
Mch81:
Zdravim,
mam problem s touto casti kodu <?php imagecopyresampled($image_p, $image, 0, 0, 0, 0, $NewWidth, $NewHeight, $OrigWidth, $OrigHeight);?>
Na lokalu mi to jede, ale na hostingu u OneBit uz ne, na tomto radku se to kousne. Jen dodam max uploaded file size je 30M.
Diky za odpoved
Michal
Mch81:
Problem hledejte u allow_url_fopen musi byt ON. Aspon tak jsem vyresil problem ja
Honza:
Ví někdo, jak je funkce getimagesize náročná na paměť? Můžu ji s klidným svědomím použít před každým zobrazením obrázku na stránce (pro nastavení atributů width a height)?
Jakub Vrána
:
Paměťově náročná funkce není, ze souboru načte jen prvních 12 bajtů. Nicméně pokud se seznam obrázků načítá např. z databáze, doporučil bych uložení rozměrů tam, což ušetří provádění souborových operací.
Honza:
Diky moc za odpoved, predpokladal jsem to, ale nikde jsem nemohl nalezt potvrzeni.
David:
mám menší problém...při použiti imagecreatefromJPEG mi to celé spadne s tím že jsem překročil množství přidělené paměti
Kubajs:
Zdravím, mám script, který sice nepracuje s databazí, ale jinak zmenšování je prakticky shodné s tím vaším.
Problém: obrázek (png) se sice zmenší, ale rozměry podkladu zůstanou stejné (zmenšený obrázek zůstane jen usazený v rohu). Nemáte tip v čem by mohl být problém?
Kubajs:
Tak už nic, chyba ve verzi GD knihovny.
Jarda:
Byl by někdo tak hodný a vysvětlil mi matematicky toto:
<?php
if ($max_x && $width > $max_x) {
$height = round($height * $max_x / $width);
$width = $max_x;
}
if ($max_y && $height > $max_y) {
$width = round($width * $max_y / $height);
$height = $max_y;
}
?>
Respektive nejsem si jistý proč se takto vypočítává ten poměr $height = round($height * $max_x / $width);
Děkuji
Jakub Vrána
:
$max_x / $height je poměr zvětšení. Po vynásobení původní výškou vyjde nová výška.
Jarda:
Předpokládám, že si chtěl napsat $max_y / $height. Nějak mi to nedocvaklo, že tím vlastně počítám poměr :) Děkuji.
Ještě jednu otázečku bych však měl. Řeší uvedené jestli je obrázek orientován na výšku nebo na šířku? Nedokážu totiž najít, jestli např. poměr zmenšení strany X je větší než poměr zmenšení strany Y a proto se má zmenšit na výchozí hodnotu jedna ze stran dle výsledku.
Podle uvedené rovnice bych totiž předpokládal že se bude v drtivé většině zmenšovat dle výšky a šířka se bude dopočítávat. (Neboť předpokládám poslední if bude skoro pokaždé true).
Možná se mýlím, nejsem v matematice moc dobrý (ale snažím se :))
Jakub Vrána
:
Chtěl jsem napsat $max_x / $width. Ale platí to samozřejmě i pro $max_y / $height.
Druhý if přijde ke slovu tehdy, když je obrázek víc na výšku než požadované rozměry. Takže když jsou požadované maximální rozměry třeba 100x100, tak se spustí pro všechny obrázky na výšku.
Jarda:
Mějme obrázek o rozměrech 1000 (šířka) x 200 (výška)
Chci ho zmenšit např. na max rozměry 150 x 100.
<?php
$width = 1000;
$height = 200;
$max_y = 100;
if (100 && 200 > 100) { //TRUE
$width = round($width * $max_y / $height); //$width = 500;
$height = 100;
}
?>
Obrázek je tedy orientován na šířku a přesto se bude zmenšovat podle poměru výšky a dostávám tak na šířku větší rozměr (500), než který jsem si určil na začátku (150)
Nebo dělám někde chybu?
Jakub Vrána
:
Nebylo by jednodušší si to spustit (nezapomeň nastavit $max_x)? Před tím, než se testuje $max_y, se ověří $max_x, které výšku upraví. Výsledné rozměry budou tedy 150 x 30.
Jarda:
Já jsem blbec, nedošlo mi, že se vlastně už pracuje s upravenou výškou. Děkuji, teď už mi to je vše jasné. :D
Aleš Spurný:
Dobrý den,
zkoušel jsem Váš kód na zmenšení obrázků. Zjistil jsem ale, že při zmenšení obrázku dojde ke zhoršení kvality a ptám se, jestli jde napsat takový script, který by patřičně změnil rozměry obrázku a přitom nechal kvalitu stejnou ? Jinak se omlouvám, pokud je dotaz nevhodný.
Výtvarník Jiří Dvořák:
Zdravím, přesně tak.
Když zmenšuji pomocí imagecopyresampled, tak stejnak i když vypnu antialiasing, tak fotografie jsou nepatrně roostřené, i když výstup imagejpeg je na 100. Když je antialiasing zapnut tak je to hrůza, když to dělám přes imagecopyresized, tak je to o něco lepší, ale stejnak to není úplně ostrý, tak jako původní fotografie. Nevím jak na to. Ale si Vítek Č. bude muset zmenšit fotografie ručně. Sice mají 500 kB, což je zlo pro isdn gprs káře, ale to mi řeší preloader. Předem díky za jakékoliv rady ohledně zachování ostrosti (nikoliv doostřování) při zmenšování nahrávaných fotografiích.
JD
Oldřich Válek:
Možná zkusit Imagick, když na všech serverech není k dispozici.
Marek:
Zdar děcka, mám dotaz dá se změnit rozlišení obrázku? Z 300 obr/palec na 72 v PHP? Díky Mára
Diskuse je zrušena z důvodu spamu.