2013-05-06 12 views
10

Come si può specificare un'immagine e applicare una sfumatura radiale trasparente dove si dissolve radialmente. Non ho installato Imagemagick.Come posso avere un gradiente trasparente radiale applicato a un'immagine con PHP?

esempio marginale:

Gradient Transparent image fade PHP

+0

http://stackoverflow.com/questions/6615602/radial-gradients-with-opacity-in-php?rq=1 # answer-6615727 –

+0

Usa CSS: http://stackoverflow.com/a/4527735/738201 – Chad

+0

Scenario di caso peggiore, è possibile tracciare un gradiente di cerchio PNG utilizzando i primitivi GD, ma piuttosto che applicare un cambiamento di colore, applicare uno spostamento di opacità. Quindi, sovrapponi quel PNG sopra l'immagine corrente. Non ho alcun codice per questo, ma potrebbe darti alcune nuove idee sulle frasi di ricerca. – halfer

risposta

3

Grazie alla funzione collegata da @Baba ho potuto modificare lo script per consentire l'effetto vignetta semi trasparente.

<?php 
class PhotoEffect 
{ 
    private $_photoLocation; 
    private $_width; 
    private $_height; 
    private $_type; 

    private $_originalImage; 
    private $_afterImage; 

    /** 
    * Load image URL in constructor 
    */ 
    final public function __construct($photoLocation) 
    { 
    $this->_photoLocation = $photoLocation; 
    if (!$size = @getimagesize($this->_photoLocation)){ 
     throw new Exception('Image cannot be handled'); 
    } 
    $this->_width = $size[0]; 
    $this->_height = $size[1]; 
    $this->_type = $size[2]; 


    switch ($this->_type) { 
     case IMAGETYPE_GIF: 
     $this->_originalImage = imagecreatefromgif($this->_photoLocation); 
     break; 
     case IMAGETYPE_JPEG: 
     $this->_originalImage = imagecreatefromjpeg($this->_photoLocation); 
     break; 
     case IMAGETYPE_PNG: 
     $this->_originalImage = imagecreatefrompng($this->_photoLocation); 
     break; 
     default: 
     throw new Exception('Unknown image type'); 
    } 
    } 

    /** 
    * Destroy created images 
    */ 
    final private function __destruct() { 
    if (!empty($this->_originalImage)) 
    { 
     imagedestroy($this->_originalImage); 
    } 

    if (!empty($this->_afterImage)) 
    { 
     imagedestroy($this->_afterImage); 
    } 
    } 

    /** 
    * Apply vignette effect 
    */ 
    final public function Vignette($sharp=0.4, $level=1, $alpha=1) 
    { 
    if (empty($this->_originalImage)) 
    { 
     throw new Exception('No image'); 
    } 

    if (!is_numeric($sharp) || !($sharp>=0 && $sharp<=10)) 
    { 
     throw new Exception('sharp must be between 0 and 10');    
    } 

    if (!is_numeric($level) || !($level>=0 && $level<=1)) 
    { 
     throw new Exception('level must be between 0 and 10');    
    } 

    if (!is_numeric($alpha) || !($alpha>=0 && $alpha<=10)) 
    { 
     throw new Exception('alpha must be between 0 and 1');   
    } 

    $this->_afterImage = imagecreatetruecolor($this->_width, $this->_height); 
    imagesavealpha($this->_afterImage, true); 
    $trans_colour = imagecolorallocatealpha($this->_afterImage, 0, 0, 0, 127); 
    imagefill($this->_afterImage, 0, 0, $trans_colour); 


    for($x = 0; $x < $this->_width; ++$x){ 
     for($y = 0; $y < $this->_height; ++$y){ 
     $index = imagecolorat($this->_originalImage, $x, $y); 
     $rgb = imagecolorsforindex($this->_originalImage, $index); 

     $l = sin(M_PI/$this->_width * $x) * sin(M_PI/$this->_height * $y); 
     $l = pow($l, $sharp); 

     $l = 1 - $level * (1 - $l); 

     $rgb['red'] *= $l; 
     $rgb['green'] *= $l; 
     $rgb['blue'] *= $l; 
     $rgb['alpha'] = 127 - (127 * ($l*$alpha)); 


     $color = imagecolorallocatealpha($this->_afterImage, $rgb['red'], $rgb['green'], $rgb['blue'], $rgb['alpha']); 

     imagesetpixel($this->_afterImage, $x, $y, $color); 
     } 
    } 

    } 


    /** 
    * Ouput PNG with correct header 
    */ 
    final public function OutputPng() 
    { 
    if (empty($this->_afterImage)) 
    { 
     if (empty($this->_originalImage)) 
     { 
     throw new Exception('No image'); 
     } 
     $this->_afterImage = $this->_originalImage; 
    } 

    header('Content-type: image/png'); 
    imagepng($this->_afterImage); 
    } 

    /** 
    * Save PNG 
    */ 
    final public function SavePng($filename) 
    { 
    if (empty($filename)) { 
     throw new Exception('Filename is required'); 
    } 

    if (empty($this->_afterImage)) 
    { 
     if (empty($this->_originalImage)) 
     { 
     throw new Exception('No image'); 
     } 
     $this->_afterImage = $this->_originalImage; 
    } 

    imagepng($this->_afterImage, $filename); 
    } 

} 


/** 
* How to use 
*/ 
$effect = new PhotoEffect('test.jpg'); 
$effect->Vignette(); 
$effect->OutputPng(); 
?> 

Working phpfiddle con l'unica immagine che ho trovato sul loro server, quindi non così grande.

+0

Hey Hugo questo codice non sembra funzionare per me. Non sono sicuro del voto negativo. –

+0

Ho aggiornato l'intero codice a una classe. Ho fatto in modo di aggiungere anche altri effetti –

+0

Ho provato un normale file PNG e ho ottenuto questo: 'PHP Errore irreversibile: eccezione non rilevata 'Eccezione' con messaggio 'L'immagine non può essere gestita'' –

17

Introduzione

Credo che si dovrebbe ottenere installato Imagemagick perché ciò che si vuole è un semplice effetto vignette, si può facilmente in modo che con ImageMagic (convert input.jpg -background black -vignette 70x80 output.png) senza dover ciclare ogni pixel che può essere molto lento quando si tratta di immagini di grandi dimensioni

Immagine originale

$file = __DIR__ . "/golf.jpg"; 

enter image description here

Effect 1

$image = new imagick($file); 
$image->vignetteImage(20, 20, 40, - 20); 
header("Content-Type: image/png"); 
echo $image; 

enter image description here

Effect 2

$image = new imagick($file); 
$image->vignetteImage(100, 100, 200, 200); 
header("Content-Type: image/png"); 
echo $image; 

enter image description here

vignetta con GD

Beh, se si è costretti a utilizzare GB ... Utilizzare può utilizzare questa cool vignette script

function vignette($im) { 
    $width = imagesx($im); 
    $height = imagesy($im); 

    $effect = function ($x, $y, &$rgb) use($width, $height) { 
     $sharp = 0.4; // 0 - 10 small is sharpnes, 
     $level = 0.7; // 0 - 1 small is brighter 
     $l = sin(M_PI/$width * $x) * sin(M_PI/$height * $y); 
     $l = pow($l, $sharp); 
     $l = 1 - $level * (1 - $l); 
     $rgb['red'] *= $l; 
     $rgb['green'] *= $l; 
     $rgb['blue'] *= $l; 
    }; 

    for($x = 0; $x < imagesx($im); ++ $x) { 
     for($y = 0; $y < imagesy($im); ++ $y) { 
      $index = imagecolorat($im, $x, $y); 
      $rgb = imagecolorsforindex($im, $index); 
      $effect($x, $y, $rgb); 
      $color = imagecolorallocate($im, $rgb['red'], $rgb['green'], $rgb['blue']); 

      imagesetpixel($im, $x, $y, $color); 
     } 
    } 
    return (true); 
} 

veloce GD approccio vignetta

Una migliore avvicinato usato in GD Filter testing sarebbe ... per creare una maschera e oltre trovava

$overlay = 'vignette_white.png'; 
    $png = imagecreatefrompng($overlay); 
    imagecopyresampled($filter, $png, 0, 0, 0, 0, $width, $height, $width, $height); 

L'unico svantaggio è che l'immagine deve avere la stessa dimensione con la maschera per l'effetto di apparire cool

Conclusione

Se questo è ciò che si intende per radial transparent gradient allora vi consiglio di ottenere ImageMagic se non almeno la signora il quadro è carino.

+0

haha ​​vero e grazie per la risposta ma il gradiente di immagine si sta sbiadendo in bianco non trasparente. Semplicemente non è possibile? Se noterai che l'immagine marginale nel post può sfumare su qualsiasi sfondo. –

+0

Puoi facilmente cambiare lo sfondo nella versione GB .... Puoi usare Imagemagic? – Baba

0

Sono consapevole che si tratta di una domanda correlata a PHP, ma è possibile ottenere gradienti trasparenti con l'uso di elementi canvas javascript e html5.

Così ho scritto questo piccolo script che:

  • rileva i browser che supportano elemento canvas, se browser non supporta tela (per fortuna solo una piccola percentuale di utenti sono a sinistra), allora viene visualizzata l'immagine.
  • crea tele e aggiunge elemento dopo immagine
  • argomenti nella funzione create_gradient() può essere modificata per la personalizzazione dà forma
  • funziona con tutti i formati di immagine più diffusi (testato con .jpg, .bmp, .gif, .png)
  • è possibile aggiungere più 'colorstops' (grd.addColorStop()) per modificare il flusso del gradiente

sceneggiatura

window.onload = function() { 
    if (typeof CanvasRenderingContext2D !== 'function') { 
     document.getElementById('gradient-image').style.visibility = "visible"; 
     return; 
    } 

    var image = document.getElementById('gradient-image'); 

    // these are the default values, change them for custom shapes 
    create_gradient(image, image.width/2, image.height/2, image.height/4, image.width/2, image.height/2, image.height/2); 
} 

function create_gradient(image, start_x, start_y, start_r, end_x, end_y, end_r){ 

    var canvas = document.createElement('canvas'); 

    var parent = image.parentNode; 
    if (parent.lastchild == image) parent.appendChild(canvas); 
    else parent.insertBefore(canvas, image.nextSibling); 

    canvas.width = image.width; 
    canvas.height = image.height; 

    var context = canvas.getContext('2d'); 

    var grd = context.createRadialGradient(start_x, start_y, start_r, end_x, end_y, end_r); 
    grd.addColorStop(0, 'rgba(0,0,0,1)'); 
    // grd.addColorStop(0.2, 'rgba(0,0,0,0.8)'); 
    grd.addColorStop(1, 'rgba(0,0,0,0)'); 

    context.fillStyle = grd; 
    context.fillRect(0, 0, image.width, image.height); 

    var grd_data = context.getImageData(0, 0, image.width, image.height); 

    context.drawImage(image, 0, 0); 
    var img_data = context.getImageData(0, 0, image.width, image.height); 

    var grd_pixel = grd_data.data; 
    var img_pixel = img_data.data; 
    var length = img_data.data.length 

    for (i = 3; i < length; i += 4) { 
     img_pixel[i] = grd_pixel[i]; 
    } 
    context.putImageData(img_data, 0, 0); 
} 

html

<img id="gradient-image"src=""> 

css

#gradient-image { 
    position: absolute; 
    visibility: hidden; 
} 
+0

Considerando questo articolo (pochi mesi, ma ancora) http://thenextweb.com/apps/2012/10/01/internet-explorer-8-falls-25-market-share-firefox-15-passes-10- mark-chrome-loses-users/c'è ancora più del 25% su IE8 o inferiore. Quindi, anche con un calo significativo del 15% che dubito sia accaduto, stai dicendo a molte persone che non sono abbastanza buone per il tuo sito. E considerando che canvas/javascript è terribilmente lento sui dispositivi Android e sui vecchi dispositivi iOS, non utilizzerei sicuramente javascript per cose come questa. –

Problemi correlati