Как я могу иметь хороший радиальный прозрачный градиент, применяемый к изображению с PHP?
как можно указать изображение и применить радиальный прозрачный градиент, где он исчезает радиально. У меня нет установленного Imagemagick.
маргинальный пример:
3 ответов
благодаря функции, связанной с @Baba, я смог изменить сценарий, чтобы обеспечить полупрозрачный эффект виньетки.
<?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();
?>
рабочий phpfiddle С единственным изображением, которое я мог найти на их сервере, поэтому не такой большой.
введение
Я думаю, вы должны получить Imagemagick установлен, потому что то, что вы хотите, это просто vignette
эффект, вы можете легко так, что с ImageMagic (convert input.jpg -background black -vignette 70x80 output.png
) без необходимости петли каждого пикселя, который может быть очень медленным при работе с большими изображениями
Исходное Изображение
$file = __DIR__ . "/golf.jpg";
эффект 1
$image = new imagick($file);
$image->vignetteImage(20, 20, 40, - 20);
header("Content-Type: image/png");
echo $image;
действие 2
$image = new imagick($file);
$image->vignetteImage(100, 100, 200, 200);
header("Content-Type: image/png");
echo $image;
виньетка с GD
Ну, если вы вынуждены использовать GB ... Использовать можно использовать это классный виньетка скрипт
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);
}
быстрее GD виньетка подход
лучше подошел в тестирование фильтра GD будет ... для создания маски и более лей!--12-->
$overlay = 'vignette_white.png';
$png = imagecreatefrompng($overlay);
imagecopyresampled($filter, $png, 0, 0, 0, 0, $width, $height, $width, $height);
единственным недостатком является то, что изображение должно быть того же размера с маской, чтобы эффект выглядел круто
вывод
если это то, что вы имеете в виду radial transparent gradient
тогда я советую вам сделать ImageMagic
если не по крайней мере, девушка на картинке симпатичная.
Я знаю, что это вопрос, связанный с PHP, но вы можете достичь хороших прозрачных градиентов с использованием javascript и html5 canvas element.
поэтому я написал этот небольшой скрипт:
- обнаруживает браузеры, которые поддерживают элемент canvas, если браузер не поддерживает canvas (к счастью, осталось всего несколько процентов пользователей), то отображается полное изображение.
- создает холст и добавляет элемент после изображения
- аргументы в функция create_gradient () может быть изменена для пользовательских фигур
- он работает со всеми популярными форматами изображений ( проверено на .формат JPG. ,формат BMP. ,файл GIF. ,png)
- вы можете добавить больше colorstops’ (
grd.addColorStop()
) изменить поток градиента
скрипт
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;
}