Nette\Image – přídání metod fromString + transparentní po­zadí

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Petr Motejlek
Člen | 293
+
0
-

Ahoj,
bylo by možné přidat do Nette\Image metodu fromString (korespondující s imagecreatefromstring()) ?

Také bych potřeboval, aby bylo možné vytvořit obrázky s transparentním pozadím, nejlépe aby fromNěco metody nedělali černej obdélník, když je jejich 3. parametr null, ale aby udělali obrázek s danými rozměry, ale s transparentním pozadím.

Děkuji mockrát ;).

David Grudl
Nette Core | 8218
+
0
-

Továrničky si můžeš vytvořit klidně sám ve vlastní třídě nebo rovnou použít

$image = new Image(imagecreatefromstring($str));

nicméně Image::fromString() přidám.

Jak udělat transparentní pozadí netuším. Co třeba ho vyplnit barvou s plným alpha kanálem?

Petr Motejlek
Člen | 293
+
0
-

Jéé, ohledně toho fromString – ani bych neotravoval, kdybych si nemyslel, že konstruktor Image je private ;))), nicméně i to, že bude existovat fromString je super.

Mě trochu zatáží to transparentní pozadí – mám-li png obrázek, který ho má, a udělám-li fromFile na Nette\Image, nebo jen klasické imagecreatefrompng a následně to nechám poslat do prohlížeče (ať už send(), nebo imagepng()), vypadne to tak, že se k tomu vždycky samo dobastlí černé pozadí ;). Budu ohledně toho muset ještě něco zjistit, doufám, že to doladíme ;).

David Grudl napsal(a):

Továrničky si můžeš vytvořit klidně sám ve vlastní třídě nebo rovnou použít

$image = new Image(imagecreatefromstring($str));

nicméně Image::fromString() přidám.

Jak udělat transparentní pozadí netuším. Co třeba ho vyplnit barvou s plným alpha kanálem?

Jod
Člen | 701
+
0
-

Mne transparentné pozadie s Nette/Image funguje v pohode, chyba bude asi inde.

Petr Motejlek
Člen | 293
+
0
-

Jod napsal(a):

Mne transparentné pozadie s Nette/Image funguje v pohode, chyba bude asi inde.

Tak, že bych něco dělal špatně já? Systém, který používám:

  1. Vytvořím png soubor v Gimpu s průhledným pozadím.
  2. V PHP použiju násloedující kód:

    $image = Image::fromFile(‚soubor.png‘);

    $image->send(Image::PNG);

  3. Soubor se objeví v prohlížeči, ale má místo průhl, pozadí pozadí černé – prohlížím to v FF3, tak snad to není jeho problém.

Mám to dělat nějak jinak? ;)

Petr Motejlek
Člen | 293
+
0
-

Odpovím si sám – když otevřu obrázek s transparentním pozadím a uložím jej (nebo odešlu do prohlížeče) – neukládá se implicitně informace o alpha kanálech – našel jsem na jednom fóru, že je potřeba u toho obrázku vypnout alphablending (imagealphablending($imageResource, false)) a zapnout ukládání informací o alpha kanálu (imagesavealpha($imageResource, true)), to vše se musí udělat před imagepng($imageResource). Když potom v PHP udělám následující kód, vše funguje jak má:

$image = imagecreatefrompng(‚cesta k obrázku.png‘);
imagealphablending($image, false);
imagesavealpha($image, true);
imagepng($image);

Bylo by možné něco podobného přidat do Nette?

(Pokud dělám něco složitě, tak to nedělám schválně, ale protože jsem to tak našel ;)).

romansklenar
Člen | 655
+
0
-

Já jsem taky neměl s průhlednými obrázky problém (tak jak je popisuješ). Ztráty průhlednosti jsem si ale všiml, až když se obrázek zmenšoval/zvětšovat ($image->resize(150, 100);), nebo při použití průhledného obrázku jako vodoznaku, který přidáš k původnímu obrázku (a zmenšíš ho).

Jod
Člen | 701
+
0
-

Ja grafiku neriešim, png som dostal od grafika, použil ho a všetko ok.
So zmenšovaním priehľadného vodoznaku som tiež nemal problém.
Aby ste mi aspoň s tým watermarkom verili: :D

Normálna velkosť

Zmenšený detail

Náhľad

Thumb

David Grudl
Nette Core | 8218
+
0
-

m0t3jl napsal(a):

Odpovím si sám – když otevřu obrázek s transparentním pozadím a uložím jej (nebo odešlu do prohlížeče) – neukládá se implicitně informace o alpha kanálech – našel jsem na jednom fóru, že je potřeba u toho obrázku vypnout alphablending (imagealphablending($imageResource, false)) a zapnout ukládání informací o alpha kanálu (imagesavealpha($imageResource, true)), to vše se musí udělat před imagepng($imageResource). Když potom v PHP udělám následující kód, vše funguje jak má:

A když se vynechá to imagealphablending, tak to nefunguje?

Jinak dá se volat i $image->saveAlpha(TRUE)

David Grudl
Nette Core | 8218
+
0
-

romansklenar napsal(a):

Já jsem taky neměl s průhlednými obrázky problém (tak jak je popisuješ). Ztráty průhlednosti jsem si ale všiml, až když se obrázek zmenšoval/zvětšovat ($image->resize(150, 100);), nebo při použití průhledného obrázku jako vodoznaku, který přidáš k původnímu obrázku (a zmenšíš ho).

Tam může být rozdíl v tom, jestli je to PNG-8 nebo PNG-24

kravčo
Člen | 721
+
0
-

Našiel som zrejme to isté fórum ako m0t3jl, no v Nette sa to dá zapísať i krajšie:

$img = Image::fromFile('alpha-test.png');

$img->alphaBlending(false);
$img->saveAlpha(true);

$img->send(Image::PNG);

Na vytváranie priehľadných prázdnych obrázkov sa dá použiť vyplnenie transparentnou farbou – pri tom je ale nutné vypnúť alphablending, aby sa vyplnením neurobila len priesvitná vrstva nad čiernou, ale nastavil sa alfa-kanál na maximum (medzi týmito módmi pracovania nad obrázkami s alfa kanálom prepína práve alphablending)

$img = Image::fromBlank(200, 200);

$img->alphaBlending(false);
$img->saveAlpha(true);

$transparent = $img->colorAllocateAlpha(0, 0, 0, 127); // 100% transparent black
$img->filledRectangle(0, 0, $img->width, $img->height, $transparent);

$img->send(Image::PNG);

Editoval kravco (16. 3. 2009 16:17)

kravčo
Člen | 721
+
0
-

Jod napsal(a):

Ja grafiku neriešim, png som dostal od grafika, použil ho a všetko ok.
So zmenšovaním priehľadného vodoznaku som tiež nemal problém.
Aby ste mi aspoň s tým watermarkom verili: :D

Rozdiel je zrejme v tom, že ty neukladáš PNG, len vkladáš priesvitné png/whatever do obrázka a ten ukladáš ako JPEG, teda bez alfa kanálu…

David Grudl napsal(a):

A když se vynechá to imagealphablending, tak to nefunguje?

V mojej verzii PHP+GD áno, no je možné, že tá poznámka v manuáli má svoje (historické) opodstatnenie…

Editoval kravco (16. 3. 2009 15:41)

David Grudl
Nette Core | 8218
+
0
-

kravco napsal(a):

V mojej verzii PHP+GD áno, no je možné, že tá poznámka v manuáli má svoje (historické) opodstatnenie…

No mám zkušenost, že na fóreach je lepší ničemu nevěřit ;-)

kravčo
Člen | 721
+
0
-

romansklenar napsal(a):

Já jsem taky neměl s průhlednými obrázky problém (tak jak je popisuješ). Ztráty průhlednosti jsem si ale všiml, až když se obrázek zmenšoval/zvětšovat ($image->resize(150, 100);), nebo při použití průhledného obrázku jako vodoznaku, který přidáš k původnímu obrázku (a zmenšíš ho).

Toto som trochu skúmal a prišiel som na to, kde je pes zakopaný.

Problém naozaj spôsobuje metóda Image::resize() (rovnako sa správa i Image::crop()), ktorá pri priesvitnom PNG obrázku vytvorí nový prázdny s čiernym pozadím cez ktorý štandardným spôsobom preloží miestami priesvitný PNG obrázok, čiže cez priesvitné miesta čierna farba pozadia nutne presvitá… riešením je napríklad vypnúť alphablending – tým pádom sa čierna prekryje ale priesvitnosť sa zachová. Problémom je, že som neprišiel na spôsob ako zistiť, či alphablending zapnutý je, alebo nie – teda nie je možné jeho prípadne zmenenú hodnotu (štandardne je zapnutý) nastaviť jednoducho späť.

David Grudl napsal(a):

kravco napsal(a):

V mojej verzii PHP+GD áno, no je možné, že tá poznámka v manuáli má svoje (historické) opodstatnenie…

No mám zkušenost, že na fóreach je lepší ničemu nevěřit ;-)

Práveže, tá informácia nie je na fóre, ale priamo v manuáli. Tam je pravdepodobnosť fóru síce menšia, ale samozrejme prednosť má vždy zdravý rozum. To rozhodne…

Editoval kravco (16. 3. 2009 18:27)

kravčo
Člen | 721
+
0
-

kravčo napsal(a):

romansklenar napsal(a):

Já jsem taky neměl s průhlednými obrázky problém (tak jak je popisuješ). Ztráty průhlednosti jsem si ale všiml, až když se obrázek zmenšoval/zvětšovat ($image->resize(150, 100);), nebo při použití průhledného obrázku jako vodoznaku, který přidáš k původnímu obrázku (a zmenšíš ho).

Toto som trochu skúmal a prišiel som na to, kde je pes zakopaný.

Problém naozaj spôsobuje metóda Image::resize() (rovnako sa správa i Image::crop()), ktorá pri priesvitnom PNG obrázku vytvorí nový prázdny s čiernym pozadím cez ktorý štandardným spôsobom preloží miestami priesvitný PNG obrázok, čiže cez priesvitné miesta čierna farba pozadia nutne presvitá… riešením je napríklad vypnúť alphablending – tým pádom sa čierna prekryje ale priesvitnosť sa zachová. Problémom je, že som neprišiel na spôsob ako zistiť, či alphablending zapnutý je, alebo nie – teda nie je možné jeho prípadne zmenenú hodnotu (štandardne je zapnutý) nastaviť jednoducho späť.

Myslím, že sa mi podarilo nájsť riešenie.

David Grudl
Nette Core | 8218
+
0
-

Máš to v kódu.

lucass
Člen | 89
+
0
-

Zdarec,

aktualizoval jsem Nette na poslední revizi kvůli podpoře transparentního pozadí ve třídě Image, ale přesto se mi nedaří z původních průhledných obrázků PNG a GIF dostat opět to samé.

  1. u PNG stačí načíst už jen Image::fromFile a zpětně získaný obrázek má černé pozadí,
  2. u GIFů se černé pozadí objeví až při použití resize.

Můj postup vytváření náhledů originálu:

<?php
$img = Image::fromFile($originalPath);
$img->resize($width, $height);
$this->binary = $img->toString();
?>

Zkoušel jsem i $img->send() – bez úspěchu, obdobně pak $img->save($thumbPath), abych zjistil, do jakého formátu to ukládá – ukládá to do původního, tj. PNG do PNG, GIF do GIF, JPEG do JPEG.

Věděl byste někdo, jak to ještě debugovat, abych našel zakopaného psa?

Díky.

Editoval lucass (9. 9. 2009 10:34)

kravčo
Člen | 721
+
0
-

Metódy Image::toString() a Image::send() ukladajú štandardne JPEG, preto im treba pri vypisovaní dať parameter, aký typ obrázka chceme vypísať.

U PNG sa štandardne neukladá alfa kanál (priesvitnosť), ukladanie treba zapnúť:

$img = Image::fromFile('gradient.png');
$img->saveAlpha(true);
$img->send(Image::PNG);

Pri zmenšovaní GIFu za prevedie obrázok z indexovaného na true color, čo môže spôsobiť, že sa stratí informácia o (jedinej) priesvinej farbe. Viac neviem, GIFy nepoužívam.

lucass
Člen | 89
+
0
-

SaveAlpha jsem měl na špatném místě, GIFy zlobily, tak je převádím na PNG. Díky.