Formáty obrázků

Školení, která pořádám

Často se setkávám s nevhodným používáním formátů obrázků, které způsobuje jejich nízkou kvalitu a vysokou velikost. Nejvíce zneužívaný je formát JPEG, o kterém je řada lidí přesvědčená, že je to ten jediný správný a univerzální formát pro obrázky. Opak je však pravdou – formát JPEG byl vyvinut za účelem ukládání fotografií a jim podobným dat (tedy např. 3D scén) a pro žádný jiný účel se nehodí. JPEG je formát ztrátový a když se v něm pokusíte uložit např. obyčejnou šikmou čáru, bude roztřepená a obrázek bude mít několik KB. Pro ukládání takovýchto – uměle vytvořených – dat se hodí formáty PNG a GIF, které se naopak vůbec nehodí pro ukládání fotek. GIF má některá omezení, dovoluje uložit maximálně 256 barev (což však pro tento typ obrázků obvykle bohatě stačí) a dlouhou dobu byl chráněn patentem (kromě prehistorických verzí se dá použít až v PHP 4.3.9 (září 2004)), naopak dovoluje vytvářet animace.

Protože toto téma s PHP až tak úzce nesouvisí, tak alespoň přikládám univerzální funkci na zmenšování obrázků.

<?php
/** 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 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 bool true, false v případě chyby
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function image_shrink($file_in, $file_out, $max_x, $max_y = 0) {
    $imagesize = getimagesize($file_in);
    if ((!$max_x && !$max_y) || !$imagesize[0] || !$imagesize[1]) {
        return false;
    }
    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;
    }
    if ($max_x) {
        $width = $max_x;
        $height = round($imagesize[1] * $width / $imagesize[0]);
    }
    if ($max_y && (!$max_x || $height > $max_y)) {
        $height = $max_y;
        $width = round($imagesize[0] * $height / $imagesize[1]);
    }
    $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);
    }
}
?>

Viz také: Zmenšování obrázků.

Jakub Vrána, Řešení problému, 22.4.2005, diskuse: 20 (nové: 0)

Diskuse

fi0dor:

Riesi vyssie zmienena funkcia aj zachovanie priehladnosti (transparentnosti resp. alfa kanalu) u formatov GIF a PNG? Tipol by som, ze ani moc nie :(.

ikona spaze:

Dodatek: PNG se na fotky hodi taky, zvlast kdyz je to PNG-24, aneb neztratovej TrueColor :) Animovana verze PNG se nazyva MNG.

Robie:

Spaze hodí a nehodí. Pro web se png na fotky vesms nehodí, protože z toho jsou pořád dost velké soubory. Leda by to byla fotka nějak upravená, aby se tam některé části přesně opakovaly.

ikona spaze:

jasne, nejak jsem nedokoncil myslenkovej pochod :) PNG-24 bych pouzil tam, kde je predpoklad, ze fotka neni urcena pro koncoveho uzivatele, kde se s fotkou bude jeste nejak dale pracovat a je potreba zachovat plnou kvalitu.

Robie:

Oki. :)

mito:

PNG a IE ?
tiez nie najstastnejsia kombinacia

tark:

Jak v čem... Neprůhledný IE je v poho.

bukaJ:

Neni, má "ujeté" barvy.

uzivatel:

to ma vo vsetkom. nie len v obrazkoch. css jak by dal. proste v IE je vsetko o trochu bledsie

hujahu:

IE bych uplne zrusil....

uzivatel:

v com je problem ? png o 256 farbach je zobrazovane uplne tak ako ma byt. to ze IE nezvlada 24bit s alpha kanalom je ina vec.

Aleš:

Se zmenšováním obrázků se tu momentálně peru, všechny programy umí zmenšovat pouze podle pixelů, ale jak zmenšovat podle bytů? Třeba bych chtěl všechny obrázky zmenšit na maximálně 100 kB. Netušíte někdo jak to? Zkouším si něco v PHP napsat, ale nedaří se.

ikona Jakub Vrána OpenID:

Photoshop 6 má v nástroji "Uložit pro web" funkci "Optimalizovat na velikost souboru", která dělá přesně tohle.

Max:

Vinikajuci navod, dakujem za publikaciu a nahliadnutie.

dobry den...:

Dobry den...
rad bych se zeptal proc mate na 8 radku od spoda kontrolau fce imagegif.... pracuji v php teprve tři roky ale zatím jsem se nesetkal aby jakykoliv hosting tuto fci neposkytoval..

mockráte děkuji za odpověd...

ikona Jakub Vrána OpenID:

Několik let byl formát GIF chráněn patentem a PHP do něj nedovolovalo zapisovat.

dobry den...:

mockráte děkuij za odpoved....

Laďa:

Nazdar mám takový problém miniatury obrázků vytvářet není problém, ale jak je obrázek větší než nějakých 1,5MB tak to prekročí hranici danou PHP, nevíte náhodou někdo jak to vyřešit aniž bych to musel dělat v externím programu. Mám vyřešenou fotogalerii s ukládaním, ale někteří mi tam teď nahrávají fotky o velikosti 5-6MB a to je zbytečné na serveru nechávat. Pokud bude mít někdo nějakou radu jak zmenšit 5MB obr na 1MB tak budu rád. Dík Laďa

kozotoč:

Ahoj, Jakube,
Ohledně tvého výroku "GIF […] dovoluje uložit maximálně 256 barev" viz http://www.root.cz/clanky/pravda-a-myty-o-gifu/#k012 bod 4. Zobrazení více než 256 barev současně.

ikona Jakub Vrána OpenID:

Já vím, já vím. Četl jsem to a postupu rozumím, ale mám za to, že by řada obrázkových prohlížečů měla s takovým GIFem problém (píše se to ostatně i v tom článku), takže pro praktické využití to těch 256 barev přeci jen bude.

Diskuse je zrušena z důvodu spamu.

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.