2010-07-21 12 views
5

Sono stato incuriosito da this discussion di ridimensionamento delle immagini e successivamente ho scoperto che il codice PHP che sto usando per creare miniature dalle immagini caricate soffre dello stesso problema. Ho deciso di provare la correzione PHP postata in basso (convertendo la gamma da 2.2 a 1.0, ridimensionando l'immagine, convertendo la gamma da 1.0 a 2.2). Questo funziona per risolvere il problema indicato nell'articolo, tuttavia questa modifica al codice ha lo sfortunato effetto collaterale di eliminare la trasparenza del canale alfa PNG.PHP GD2: come mantenere la trasparenza del canale alfa e correggere gamma

Ecco il codice che ho con la correzione della gamma in atto.

<?php 
$image = imagecreatefrompng($source_file); 
$resized_image = imagecreatetruecolor($new_width, $new_height); 
imagealphablending($resized_image, false); 
imagesavealpha($resized_image, true); 
imagegammacorrect($image, 2.2, 1.0); 
imagecopyresampled($resized_image, $image, 0, 0, 0, 0, $new_width, $new_height, $image_width, $image_height); 
imagegammacorrect($resized_image, 1.0, 2.2); 
imagepng($resized_image, $dest_file); 
?> 

Qualcuno sa come ridimensionare l'immagine, che impiega la correzione trucco gamma, pur mantenendo la trasparenza canale alfa dell'immagine originale?

Modifica

immagini di esempio:

  1. file originale - PNG con trasparenza canale alfa
  2. di file ridimensionato con entrambe le imagegammacorrect chiamate di funzione() commentate
  3. file di ridimensionamento sia con imagegammacorrect() chiamate di funzione sul posto

Si può vedere che La trasparenza è buona fino a quando non si tenta di correggere la gamma. (Modo più semplice per vedere la trasparenza sta lavorando sotto è per ispezionare il tag di paragrafo avvolto intorno alle immagini e aggiungere uno sfondo:. Nero; al suo attributo di stile tramite Firebug o simili)

original image http://ender.hosting.emarketsouth.com/images/test-image.png no gamma correction http://ender.hosting.emarketsouth.com/images/test-image-resized-no-gamma.png gamma corrected - no transparency http://ender.hosting.emarketsouth.com/images/test-image-resized.png

risposta

2

Ecco un codice che funziona. Fondamentalmente, separa il canale alfa, ridimensiona l'immagine usando la gamma corretta, ridimensiona il canale alfa senza gamma corretto, quindi copia sul canale alfa sull'immagine ridimensionata che è stata eseguita con gamma corretta.

La mia ipotesi è che la funzione imagegammacorrect() abbia un bug. Forse la gamma si applica solo a RGB e GD prova a fare lo stesso calcolo anche sul canale alfa? La teoria del colore non è il mio forte.

In ogni caso, ecco il codice. Sfortunatamente non sono riuscito a trovare un modo migliore per separare i canali piuttosto che scorrere i pixel uno alla volta. Vabbè ...

<?php 
// Load image 
$image = imagecreatefrompng('test-image.png'); 

// Create destination 
$resized_image = imagecreatetruecolor(100, 100); 
imagealphablending($resized_image, false); // Overwrite alpha 
imagesavealpha($resized_image, true); 

// Create a separate alpha channel 
$alpha_image = imagecreatetruecolor(200, 200); 
imagealphablending($alpha_image, false); // Overwrite alpha 
imagesavealpha($alpha_image, true); 

for ($x = 0; $x < 200; $x++) { 
    for ($y = 0; $y < 200; $y++) { 
     $alpha = (imagecolorat($image, $x, $y) >> 24) & 0xFF; 
     $color = imagecolorallocatealpha($alpha_image, 0, 0, 0, $alpha); 
     imagesetpixel($alpha_image, $x, $y, $color); 
    } 
} 

// Resize image to destination, using gamma correction 
imagegammacorrect($image, 2.2, 1.0); 
imagecopyresampled($resized_image, $image, 0, 0, 0, 0, 100, 100, 200, 200); 
imagegammacorrect($resized_image, 1.0, 2.2); 

// Resize alpha channel 
$alpha_resized_image = imagecreatetruecolor(200, 200); 
imagealphablending($alpha_resized_image, false); 
imagesavealpha($alpha_resized_image, true); 

imagecopyresampled($alpha_resized_image, $alpha_image, 0, 0, 0, 0, 100, 100, 200, 200); 

// Copy alpha channel back to resized image 
for ($x = 0; $x < 100; $x++) { 
    for ($y = 0; $y < 100; $y++) { 
     $alpha = (imagecolorat($alpha_resized_image, $x, $y) >> 24) & 0xFF; 
     $rgb = imagecolorat($resized_image, $x, $y); 
     $r = ($rgb >> 16) & 0xFF; 
     $g = ($rgb >> 8) & 0xFF; 
     $b = $rgb & 0xFF; 
     $color = imagecolorallocatealpha($resized_image, $r, $g, $b, $alpha); 
     imagesetpixel($resized_image, $x, $y, $color); 
    } 
} 

imagepng($resized_image, 'test-image-scaled.png'); 
?> 

Sostituire valori hard-coded con le variabili, naturalmente ... Ed ecco il risultato che ottengo utilizzando l'immagine e il mio codice:

Resized image http://www.jejik.com/sander/test-image-scaled.png

+0

interessante, dovrò passare un po 'di tempo con questo domani quando torno in ufficio :) –

+0

ha avuto un piccolo refactoring da fare per combinare questo con il mio codice esistente, ma alla fine funziona benissimo. Molto apprezzato! –

-1

C'è un problema con imagecopyresampled() e la trasparenza. Dai un'occhiata a this comment on php.net per una possibile soluzione.

+0

no, la trasparenza è conservato senza problemi quando rimuovo le chiamate alla funzione imagegammacorrect(). http://stackoverflow.com/questions/313070/png-transparency-with-php/313103#313103 ha contribuito a questo. –

+0

Ah, una sfida allora! MrGreen Vedi la mia nuova risposta. –