php image manipulation - fade to transparency - php

does anyone know how to apply fade effect to an image using PHP ? what I am looking for is a way to apply gradient transparency ( i mean : at the top , the image is opaque , which gradually gets more and more transparent , and at the bottom it is completely transparent).
i have been reading up on http://php.net/manual/en/function.imagecolortransparent.php , but did not see anything about applying a gradient effect to an image.
i also read : PHP - Generate transparency (or opacity) gradient using image , but it kinda trailed off without any solution!
I am also open to any other suggestion / libraries that can do this from command line.

Obviously you'll need to work with a png for this effect, but you can convert any png into a jpg using php. The following question I believe covers what you are asking about. Part of the code will have to be removed to clear the image reflection effect.
Can You Get a Transparent Gradient using PHP ImageMagick?
The piece of code which seems to do what you are trying to accomplish is:
$im = new Imagick('image.jpg'); //Reference image location
if (!$im->getImageAlphaChannel()) {
$im->setImageAlphaChannel(Imagick::ALPHACHANNEL_SET);
}
$refl = $im->clone();
$refl->flipImage();
$gradient = new Imagick();
$gradient->newPseudoImage($refl->getImageWidth() + 10, $refl->getImageHeight() + 10, "gradient:transparent-black");

Related

Saving SVG as PNG [duplicate]

I'm working on a web project that involves a dynamically generated map of the US coloring different states based on a set of data.
This SVG file gives me a good blank map of the US and is very easy to change the color of each state. The difficulty is that IE browsers don't support SVG so in order for me to use the handy syntax the svg offers, I'll need to convert it to a JPG.
Ideally, I'd like to do this with only the GD2 library but could also use ImageMagick. I have absolutely no clue how to do this.
Any solution that would allow me to dynamically change the colors of states on a map of the US will be considered. The key is that it is easy to change the colors on the fly and that it is cross browser. PHP/Apache solutions only, please.
That's funny you asked this, I just did this recently for my work's site and I was thinking I should write a tutorial... Here is how to do it with PHP/Imagick, which uses ImageMagick:
$usmap = '/path/to/blank/us-map.svg';
$im = new Imagick();
$svg = file_get_contents($usmap);
/*loop to color each state as needed, something like*/
$idColorArray = array(
"AL" => "339966"
,"AK" => "0099FF"
...
,"WI" => "FF4B00"
,"WY" => "A3609B"
);
foreach($idColorArray as $state => $color){
//Where $color is a RRGGBB hex value
$svg = preg_replace(
'/id="'.$state.'" style="fill:#([0-9a-f]{6})/'
, 'id="'.$state.'" style="fill:#'.$color
, $svg
);
}
$im->readImageBlob($svg);
/*png settings*/
$im->setImageFormat("png24");
$im->resizeImage(720, 445, imagick::FILTER_LANCZOS, 1); /*Optional, if you need to resize*/
/*jpeg*/
$im->setImageFormat("jpeg");
$im->adaptiveResizeImage(720, 445); /*Optional, if you need to resize*/
$im->writeImage('/path/to/colored/us-map.png');/*(or .jpg)*/
$im->clear();
$im->destroy();
the steps regex color replacement may vary depending on the svg path xml and how you id & color values are stored. If you don't want to store a file on the server, you can output the image as base 64 like
<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '" />';?>
(before you use clear/destroy) but ie has issues with PNG as base64 so you'd probably have to output base64 as jpeg
you can see an example here I did for a former employer's sales territory map:
Start: https://upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg
Finish:
Edit
Since writing the above, I've come up with 2 improved techniques:
1) instead of a regex loop to change the fill on state , use CSS to make style rules like
<style type="text/css">
#CA,#FL,HI{
fill:blue;
}
#Al, #NY, #NM{
fill:#cc6699;
}
/*etc..*/
</style>
and then you can do a single text replace to inject your css rules into the svg before proceeding with the imagick jpeg/png creation. If the colors don't change, check to make sure you don't have any inline fill styles in your path tags overriding the css.
2) If you don't have to actually create a jpeg/png image file (and don't need to support outdated browsers), you can manipulate the svg directly with jQuery. You can't access the svg paths when embedding the svg using img or object tags, so you'll have to directly include the svg xml in your webpage html like:
<div>
<?php echo file_get_contents('/path/to/blank/us-map.svg');?>
</div>
then changing the colors is as easy as:
<script type="text/javascript" src="/path/to/jquery.js"></script>
<script type="text/javascript">
$('#CA').css('fill', 'blue');
$('#NY').css('fill', '#ff0000');
</script>
When converting SVG to transparent PNG, don't forget to put this BEFORE $imagick->readImageBlob():
$imagick->setBackgroundColor(new ImagickPixel('transparent'));
You mention that you are doing this because IE doesn't support SVG.
The good news is that IE does support vector graphics. Okay, so it's in the form of a language called VML which only IE supports, rather than SVG, but it is there, and you can use it.
Google Maps, among others, will detect the browser capabilities to determine whether to serve SVG or VML.
Then there's the Raphael library, which is a Javascript browswer-based graphics library, which supports either SVG or VML, again depending on the browser.
Another one which may help: SVGWeb.
All of which means that you can support your IE users without having to resort to bitmap graphics.
See also the top answer to this question, for example: XSL Transform SVG to VML
This is v. easy, have been doing work on this for the past few weeks.
You need the Batik SVG Toolkit. Download, and place the files in the same directory as the SVG you want to convert to a JPEG, also make sure you unzip it first.
Open the terminal, and run this command:
java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg
That should output a JPEG of the SVG file. Really easy.
You can even just place it in a loop and convert loads of SVGs,
import os
svgs = ('test1.svg', 'test2.svg', 'etc.svg')
for svg in svgs:
os.system('java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 '+str(svg)+'.svg')
This is a method for converting a svg picture to a gif using standard php GD tools
1) You put the image into a canvas element in the browser:
<canvas id=myCanvas></canvas>
<script>
var Key='picturename'
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
base_image = new Image();
base_image.src = myimage.svg;
base_image.onload = function(){
//get the image info as base64 text string
var dataURL = canvas.toDataURL();
//Post the image (dataURL) to the server using jQuery post method
$.post('ProcessPicture.php',{'TheKey':Key,'image': dataURL ,'h': canvas.height,'w':canvas.width,"stemme":stemme } ,function(data,status){ alert(data+' '+status) });
}
</script>
And then convert it at the server (ProcessPicture.php) from (default) png to gif and save it. (you could have saved as png too then use imagepng instead of image gif):
//receive the posted data in php
$pic=$_POST['image'];
$Key=$_POST['TheKey'];
$height=$_POST['h'];
$width=$_POST['w'];
$dir='../gif/'
$gifName=$dir.$Key.'.gif';
$pngName=$dir.$Key.'.png';
//split the generated base64 string before the comma. to remove the 'data:image/png;base64, header created by and get the image data
$data = explode(',', $pic);
$base64img = base64_decode($data[1]);
$dimg=imagecreatefromstring($base64img);
//in order to avoid copying a black figure into a (default) black background you must create a white background
$im_out = ImageCreateTrueColor($width,$height);
$bgfill = imagecolorallocate( $im_out, 255, 255, 255 );
imagefill( $im_out, 0,0, $bgfill );
//Copy the uploaded picture in on the white background
ImageCopyResampled($im_out, $dimg ,0, 0, 0, 0, $width, $height,$width, $height);
//Make the gif and png file
imagegif($im_out, $gifName);
imagepng($im_out, $pngName);
I do not know of a standalone PHP / Apache solution, as this would require a PHP library that can read and render SVG images. I'm not sure such a library exists - I don't know any.
ImageMagick is able to rasterize SVG files, either through the command line or the PHP binding, IMagick, but seems to have a number of quirks and external dependencies as shown e.g. in this forum thread. I think it's still the most promising way to go, it's the first thing I would look into if I were you.
I would like to share my answer too it might help someone.
This it is more for simple case when your svg dose not contain fill style and by default black and you want to convert it to png and add color to result png.
function convertSvgToPng($svgPath, $fillColor, $outPath)
{
$im = new Imagick();
$svg = file_get_contents($svgPath);
// !!! THIS is the trick part - just appending to all <path fill color
$svg = str_replace('<path ', '<path style="fill:'.$fillColor.'" ', $svg);
$im->readImageBlob($svg);
$im->setImageFormat("png24");
$im->writeImage($outPath);
$im->clear();
$im->destroy();
}
You can use Raphaël—JavaScript Library and achieve it easily. It will work in IE also.
$command = 'convert -density 300 ';
if(Input::Post('height')!='' && Input::Post('width')!=''){
$command.='-resize '.Input::Post('width').'x'.Input::Post('height').' ';
}
$command.=$svg.' '.$source;
exec($command);
#unlink($svg);
or using : potrace
demo :Tool4dev.com

Image manipulation using PHP: force 1:1 aspect ratio (sqaure images)

I am looking to add a background to images that users upload that are not square. So if they upload a tall and skinny photo I want to add a white background to the sides of the image to make the resulting image have an aspect ratio of 1:1. Is this possible using PHP or javascript?
You can use the GD library for what, with a library called Wideimage it's a breeze:
$image = WideImage::load('img_form_field_name');
$size = max($image->getHeight(), $image->getWidth());
$white = $image->allocateColor(255, 255, 255);
$image->resizeCanvas($size, $size, 'center', 'center', $white);
See the documentation and examples, many functions can even be tested interactively.
The GD library is the most commonly used image manipulation package. It's a set of functions often installed with PHP which handle image manipulation.
What you'll want to do is either scale and crop your image to a specific aspect ratio so that you place your image on a square canvas and cut off whatever does fit or
You'll want to simply resize your image to a fixed aspect ratio and place it on a square canvas with whitespace around it.
Either way, this tutorial should point you in the right direction
http://return-true.com/2009/02/making-cropping-thumbnails-square-using-php-gd/
Yep you'll want to look into either the GD library or ImageMagik. There are plenty of tutorials available for this task.
Functions like imagecreatetruecolor() etc will allow you to create a new image, and then stack the uploaded image on top of it and save it as a new file.
Yes.
http://www.php.net/manual/en/refs.utilspec.image.php

Imagick roundCorners makes image half-transparant

I'm in the process of writing an image script for a website I'm making, and for one of the image modes I need to both crop the image and make round corners for it. This is the code I'm using now:
$img = new Imagick();
$img->readImageBlob($data);
$img->resizeImage($width, $height, $img->FILTER_GAUSSIAN, 1);
$canvas = new Imagick();
$canvas->newImage($size[0], $size[1], new ImagickPixel('white'));
$canvas->compositeImage($img, imagick::COMPOSITE_OVER, 0, 0);
$canvas->roundCorners(10, 10);
$canvas->setImageFormat('png');
Resulting image
However, the resulting image is about half-transparent, as seen above, except for a 10-ish px border around the edge, created by roundCorner I assume. I've tried a lot of different ways of doing this, including cropping $img directly and roundCorner on it, but then the result is without round corners.
I suspect compositeImage to be the thief in this drama, but I can't say for sure. Anyone?
EDIT: Correction: If I do the crop and round solution, I end up with rounded corners, but they have a black background. This is the code I'm using here. Anyone spot the error/solution?
$img = new Imagick();
$img->readImageBlob($data);
$img->resizeImage($width, $height, $img->FILTER_GAUSSIAN, 1);
$img->cropImage($size[0], $size[1], 0, 0);
$img->roundCorners(10, 10);
EDIT 2:
The solution to the crop and round resolution was to make sure it's a png, so that is has alpha-support. However, the result is the same as the one produced from my original code.
EDIT 3:
Tried this script on my deployment server, and it worked as I wanted it to, so it seems like there's some problem with the version of imagick / php-imagick shipped with macports. Thanks for all the help!
You can tell imagemagick to give you an alpha background with
$img->setImageAlphaChannel ( imagick::ALPHACHANNEL_TRANSPARENT )
or try setting the image format to PNG24 explicitly before doing any transformations.
Order is important here, the image needs an alpha channel before you expose the background.
It was a problem with the version of Imagick / php-imagick shipped with current macports. Haven't solved it for my computer, but the script is working as intended on my deployment server.

Convert SVG image to PNG with PHP

I'm working on a web project that involves a dynamically generated map of the US coloring different states based on a set of data.
This SVG file gives me a good blank map of the US and is very easy to change the color of each state. The difficulty is that IE browsers don't support SVG so in order for me to use the handy syntax the svg offers, I'll need to convert it to a JPG.
Ideally, I'd like to do this with only the GD2 library but could also use ImageMagick. I have absolutely no clue how to do this.
Any solution that would allow me to dynamically change the colors of states on a map of the US will be considered. The key is that it is easy to change the colors on the fly and that it is cross browser. PHP/Apache solutions only, please.
That's funny you asked this, I just did this recently for my work's site and I was thinking I should write a tutorial... Here is how to do it with PHP/Imagick, which uses ImageMagick:
$usmap = '/path/to/blank/us-map.svg';
$im = new Imagick();
$svg = file_get_contents($usmap);
/*loop to color each state as needed, something like*/
$idColorArray = array(
"AL" => "339966"
,"AK" => "0099FF"
...
,"WI" => "FF4B00"
,"WY" => "A3609B"
);
foreach($idColorArray as $state => $color){
//Where $color is a RRGGBB hex value
$svg = preg_replace(
'/id="'.$state.'" style="fill:#([0-9a-f]{6})/'
, 'id="'.$state.'" style="fill:#'.$color
, $svg
);
}
$im->readImageBlob($svg);
/*png settings*/
$im->setImageFormat("png24");
$im->resizeImage(720, 445, imagick::FILTER_LANCZOS, 1); /*Optional, if you need to resize*/
/*jpeg*/
$im->setImageFormat("jpeg");
$im->adaptiveResizeImage(720, 445); /*Optional, if you need to resize*/
$im->writeImage('/path/to/colored/us-map.png');/*(or .jpg)*/
$im->clear();
$im->destroy();
the steps regex color replacement may vary depending on the svg path xml and how you id & color values are stored. If you don't want to store a file on the server, you can output the image as base 64 like
<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '" />';?>
(before you use clear/destroy) but ie has issues with PNG as base64 so you'd probably have to output base64 as jpeg
you can see an example here I did for a former employer's sales territory map:
Start: https://upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg
Finish:
Edit
Since writing the above, I've come up with 2 improved techniques:
1) instead of a regex loop to change the fill on state , use CSS to make style rules like
<style type="text/css">
#CA,#FL,HI{
fill:blue;
}
#Al, #NY, #NM{
fill:#cc6699;
}
/*etc..*/
</style>
and then you can do a single text replace to inject your css rules into the svg before proceeding with the imagick jpeg/png creation. If the colors don't change, check to make sure you don't have any inline fill styles in your path tags overriding the css.
2) If you don't have to actually create a jpeg/png image file (and don't need to support outdated browsers), you can manipulate the svg directly with jQuery. You can't access the svg paths when embedding the svg using img or object tags, so you'll have to directly include the svg xml in your webpage html like:
<div>
<?php echo file_get_contents('/path/to/blank/us-map.svg');?>
</div>
then changing the colors is as easy as:
<script type="text/javascript" src="/path/to/jquery.js"></script>
<script type="text/javascript">
$('#CA').css('fill', 'blue');
$('#NY').css('fill', '#ff0000');
</script>
When converting SVG to transparent PNG, don't forget to put this BEFORE $imagick->readImageBlob():
$imagick->setBackgroundColor(new ImagickPixel('transparent'));
You mention that you are doing this because IE doesn't support SVG.
The good news is that IE does support vector graphics. Okay, so it's in the form of a language called VML which only IE supports, rather than SVG, but it is there, and you can use it.
Google Maps, among others, will detect the browser capabilities to determine whether to serve SVG or VML.
Then there's the Raphael library, which is a Javascript browswer-based graphics library, which supports either SVG or VML, again depending on the browser.
Another one which may help: SVGWeb.
All of which means that you can support your IE users without having to resort to bitmap graphics.
See also the top answer to this question, for example: XSL Transform SVG to VML
This is v. easy, have been doing work on this for the past few weeks.
You need the Batik SVG Toolkit. Download, and place the files in the same directory as the SVG you want to convert to a JPEG, also make sure you unzip it first.
Open the terminal, and run this command:
java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg
That should output a JPEG of the SVG file. Really easy.
You can even just place it in a loop and convert loads of SVGs,
import os
svgs = ('test1.svg', 'test2.svg', 'etc.svg')
for svg in svgs:
os.system('java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 '+str(svg)+'.svg')
This is a method for converting a svg picture to a gif using standard php GD tools
1) You put the image into a canvas element in the browser:
<canvas id=myCanvas></canvas>
<script>
var Key='picturename'
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
base_image = new Image();
base_image.src = myimage.svg;
base_image.onload = function(){
//get the image info as base64 text string
var dataURL = canvas.toDataURL();
//Post the image (dataURL) to the server using jQuery post method
$.post('ProcessPicture.php',{'TheKey':Key,'image': dataURL ,'h': canvas.height,'w':canvas.width,"stemme":stemme } ,function(data,status){ alert(data+' '+status) });
}
</script>
And then convert it at the server (ProcessPicture.php) from (default) png to gif and save it. (you could have saved as png too then use imagepng instead of image gif):
//receive the posted data in php
$pic=$_POST['image'];
$Key=$_POST['TheKey'];
$height=$_POST['h'];
$width=$_POST['w'];
$dir='../gif/'
$gifName=$dir.$Key.'.gif';
$pngName=$dir.$Key.'.png';
//split the generated base64 string before the comma. to remove the 'data:image/png;base64, header created by and get the image data
$data = explode(',', $pic);
$base64img = base64_decode($data[1]);
$dimg=imagecreatefromstring($base64img);
//in order to avoid copying a black figure into a (default) black background you must create a white background
$im_out = ImageCreateTrueColor($width,$height);
$bgfill = imagecolorallocate( $im_out, 255, 255, 255 );
imagefill( $im_out, 0,0, $bgfill );
//Copy the uploaded picture in on the white background
ImageCopyResampled($im_out, $dimg ,0, 0, 0, 0, $width, $height,$width, $height);
//Make the gif and png file
imagegif($im_out, $gifName);
imagepng($im_out, $pngName);
I do not know of a standalone PHP / Apache solution, as this would require a PHP library that can read and render SVG images. I'm not sure such a library exists - I don't know any.
ImageMagick is able to rasterize SVG files, either through the command line or the PHP binding, IMagick, but seems to have a number of quirks and external dependencies as shown e.g. in this forum thread. I think it's still the most promising way to go, it's the first thing I would look into if I were you.
I would like to share my answer too it might help someone.
This it is more for simple case when your svg dose not contain fill style and by default black and you want to convert it to png and add color to result png.
function convertSvgToPng($svgPath, $fillColor, $outPath)
{
$im = new Imagick();
$svg = file_get_contents($svgPath);
// !!! THIS is the trick part - just appending to all <path fill color
$svg = str_replace('<path ', '<path style="fill:'.$fillColor.'" ', $svg);
$im->readImageBlob($svg);
$im->setImageFormat("png24");
$im->writeImage($outPath);
$im->clear();
$im->destroy();
}
You can use Raphaël—JavaScript Library and achieve it easily. It will work in IE also.
$command = 'convert -density 300 ';
if(Input::Post('height')!='' && Input::Post('width')!=''){
$command.='-resize '.Input::Post('width').'x'.Input::Post('height').' ';
}
$command.=$svg.' '.$source;
exec($command);
#unlink($svg);
or using : potrace
demo :Tool4dev.com

Using a transparent PNG as a clip mask

Is it possible to take this image:
And apply this mask:
And turn it into this:
Using either GD or Imagick? I know it's possible to mask an image using shapes but I'm not sure how to go on about doing it with a pre-created alphatransparent image. :s
Using Imagick and ImageMagick version > 6 (I don't know if it will work on older versions):
// Set image path
$path = '/path/to/your/images/';
// Create new objects from png's
$dude = new Imagick($path . 'dude.png');
$mask = new Imagick($path . 'dudemask.png');
// IMPORTANT! Must activate the opacity channel
// See: http://www.php.net/manual/en/function.imagick-setimagematte.php
$dude->setImageMatte(1);
// Create composite of two images using DSTIN
// See: http://www.imagemagick.org/Usage/compose/#dstin
$dude->compositeImage($mask, Imagick::COMPOSITE_DSTIN, 0, 0);
// Write image to a file.
$dude->writeImage($path . 'newimage.png');
// And/or output image directly to browser
header("Content-Type: image/png");
echo $dude;
I think you are looking for imagealphablending. I use it for watermarks, and I believe it will do the effect you are looking for.
Great work with (ImageMagick) NOT GD .. I see the tags of this question is GD!!
Here is a GD version at this link:
PHP GD Use one image to mask another image, including transparency

Categories