Effetto riflesso alle immagini con php gd

Vediamo come creare, tramite le gd2 di php, delle immagini con l’effetto a specchio nella parte bassa dell’immagine, e alla fine vedremo come ottenere un effetto molto simile senza le gd, con un ottimo risultato.

<?php
class image_eff{
    private $im1, $im2;
    public function __construct(){
        $this->im1=NULL;
        $this->im2=NULL;
    }
    public function refl($imgname, $perc, $inperc, $correction = 0){
        //$correction: coefficiente di modifica componenti riflesse[-100, 100]
        //cosi posso specificare inperc come percentuale
        $inperc = (1/$perc)*$inperc;
        //preparo la prima immagine
        $ext = $this->file_ext($imgname);
        $func_ext = (in_array($ext, array('jpg','jpeg') ))?'jpeg':$ext;
        $img_open = 'imagecreatefrom'.$func_ext;
        $img_close = 'image'.((in_array($ext, array('jpg','jpeg') ))?'jpeg':$ext);
        //
        $this->im1 = @$img_open($imgname);
        imagealphablending($this->im1, false);
        imagesavealpha($this->im1, true);
        $width = imagesx($this->im1);
        $height = imagesy($this->im1);
        //
        //creo la nuova immagine
        $this->im2 = @imagecreatetruecolor($width, intval($height*(1 + $perc))) or die(
            "Cannot Initialize new GD image stream"
        );
        imagealphablending($this->im2, false);
        imagesavealpha($this->im2, true);
        //
        //copio la parte originale dell'immagine
        imagecopy($this->im2, $this->im1, 0, 0, 0, 0, $width, $height);
        //
        // PER ORA non so davvero perche' , ma con 64  funziona
        $thresold = 2&lt;&lt;5; // e' una soglia per decidere che fare in caso ci siano alpha (png)
        //
        for($y=0; $y &lt; intval( $height * $perc ); $y++){
            //[0,127]
            $p =intval( $y*127/ ($height * $perc));
            for($x=0; $x&lt;$width; $x++){
                $colRGB = $this->getRGB($this->im1, $x, $height-$y*$inperc-1);
                //
                $steps = array(
                    'red' => min(array(255 - $colRGB['red'] ,$colRGB['red'] )) / 100,
                    'green' => min(array(255 - $colRGB['green'] , $colRGB['green'] )) / 100,
                    'blue' => min(array(255 - $colRGB['blue'] , $colRGB['blue'] )) / 100,
                );
                foreach($colRGB as $k=>$c) $colRGB[$k] += intval($steps[$k]*$correction);
                //
                imagesetpixel(
                    $this->im2,
                    $x,
                    $height+$y,
                    ($colRGB['alpha'] &lt; $thresold)  ?
                        imagecolorexactalpha (
                            $this->im2,
                            abs($colRGB['red']),
                            abs($colRGB['green']),
                            abs($colRGB['blue']),
                            $p 
                        )
                        :
                        imagecolorallocatealpha($this->im2, 0, 0, 0, 127 )
                );  
            }
        }
        if($this->im2!==NULL){
            header("Content-Type: image/".$func_ext);
            $img_close($this->im2);
        }
        return $this;
    }
    //
    private function getRGB($im, $x, $y){
        return imagecolorsforindex($im, imagecolorat($im, $x, $y) );
    }
    private function file_ext($filename){
        $tmp = explode('.',$filename);
        return array_pop($tmp);
    }
}
//
//
//
$filename = $_GET['im'];
$eff = new image_eff();
$eff -> refl($filename, 0.2, 1, -70);

qui i parametri non banali di refl() sono:

  • $perc : percentuale dell’immagine originale (da 0 a 1) dello spazio che verra’ aggiunto per il riflesso;
  • $inperc: percentuale dell’immagine originale (da 0 a 1) che verra’mostrato nell`area di riflessione;
  • $correction: valore che di default vale 0 (non influendo), mentre se diverso da 0 schiarisce o scurisce il riflesso a seconda che sia maggiore o minore di zero; agli estremi si ottiene il massimo effetto possibile senza alterare le differenze cromatiche tra i vari pixel.

Ora, supponendo di aver chiamato il file sopra “image.php”, basta puntare a questo file nell’attributo src di un’immagine, passando in get il parametro im con la path all’immagine (relativa al file image.php)

<img src="image.php?im=prova.jpg" />

ottenendo quanto visto all’inizio del post. Funziona con

jpeg, gif e nel caso delle png viene preservata la trasparenza e la parte riflessa viene sfumata. E se non abbiamo le gd? Se siamo disposti a prenderci un po di divite allora possiamo usare la seguente funzione:

<?php
function noGD_refl($imgname, $w, $h, $perc=1, $inperc=1, $g=1){ 
    $out = '';
    echo '<div id="ext">';
    echo '<img src="'.$imgname.'" style="border:0px; padding:0px; margin:0px" />';
    for($i = $h-1, $j = 0; $i > $h*(1-$perc); $i--, $j++){
        $tmp = $h-$i;
        $opacity = ($g)? $g-($tmp/($h*(1-$perc))) : 1;

        // retta per due punti [$h*(1-$perc)-1, 0] e [$h-1, $h-1]
        // tenendo anche conto di un fattore di scala $inperc

        $minus = ($h-1)*(1-$inperc) + $inperc*(($h-1)/($h-1-($h*(1-$perc)-1) ))*($i-($h*(1-$perc)-1)) -0;
        $x = "&lt;div style=\"width:".$w."px;height:1px;background:url(".$imgname.") 0px -".$minus.
        "px;repeat:norepeat;opacity:".
        $opacity.
        ";filter: alpha(opacity = ".
        ceil(($opacity*100)).
        ");\">&lt;/div>";
        $out = $out.$x;

    }
    echo $out;
    echo '&lt;/div>';

}
// 
noGD_refl('prova.jpg', 450, 337, 0.5, 0.8, 0.7);

qui si hanno vantaggi e svantaggi, il vantaggio e’ che l’effetto alpha funziona con tutte le immagini, non solo con png, visto che e’ dato da css; lo svantaggio e’ che si creano ben h div. I parametri sono nome, larghezza, altezza, percentuale di spazio per la riflessione (rispetto h), percentuale di immagine riflessa nello spazio a disposizione, fattore per regolare alpha.
Ciao Federico

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Posted in php Tagged with:

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

*