I have a php helper function that takes base64 png and outputs a pdf file:
public static function base64PngToPdf($b64, $filePath) {
$imagick = new Imagick();
$imagick->readImageBlob(base64_decode($b64));
// Create PDF File
$pdfFile = new Imagick();
$pdfFile->setFormat('pdf');
// Add image to pdf
$pdfFile->addImage($imagick->getImage());
file_put_contents($filePath, $pdfFile->getImagesBlob());
return $filePath;
}
The problem in my case is, the png I have is 800w x 1200h px. The code above is outputting a label that's 211 x 317mm. I want to get a label that's scaled down to either 101mm wide or 152mm tall (preferrably without scaling the pixels themselves, just changing the physical size).
I did some googling and found the imagick has a density parameter, but I'm not 100% sure if that's what I want in this case, and my library doesn't have a ->setDensity function.
I found a sort-of related solution. I can use $pdfFile->setResolution($resolution[0], $resolution[1]);, and in setResolution I can set for example a ppi of 72.
I'm trying to finish up my image uploader that utilizes imagick for the handling of various image types. One thing specifically that I'm trying to get working is the conversion of jpeg files to progressive jpeg. I've tried the following code below, but when I view the images that get output in irfranview, the jpeg are not progressive. Any ideas?
foreach ($thumbnailScaleWidths as $thumbnailScaleWidth) {
$thumbnail = new imagick($uploadedFile['tmp_name']);
$thumbnailDimensions = $thumbnail->getImageGeometry();
$thumbnailWidth = $thumbnailDimensions['width'];
$thumbnailHeight = $thumbnailDimensions['height'];
$thumbnailScaleHeight = ($thumbnailScaleWidth / $thumbnailWidth) * $thumbnailHeight;
$thumbnail->thumbnailImage($thumbnailScaleWidth, $thumbnailScaleHeight);
$thumbnail->setImageInterlaceScheme(Imagick::INTERLACE_PLANE);
$thumbnail->writeImages($_SERVER['DOCUMENT_ROOT'] . "/Resources/Media/$userId/$internalName-$thumbnailScaleWidth.$fileType", true);
}
Any ideas as to why this isn't outputting progressive jpegs?
Use setInterlaceScheme instead of setImageInterlaceScheme - the latter doesn't appear to do anything, but the former works just fine for me.
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
I was doing some image editing with PHP, since GD provides less functionalities, I switched to Imagick.
One of the processes is to greyscale images. Everything went fine (locally on Windows 7, Imagick 2.2.1-dev 6.5.8-7 Q16) till I uploaded the script to my web hosting server (Linux, Imagick 3.0.1, 6.2.8, 2010-10-20, Q16).
I'v tried to change the quality, but it didn't improve anything.
$img->setImageCompression(imagick::COMPRESSION_JPEG);
$img->setImageCompressionQuality(100);
Here is the results from GD, Imagick and Photoshop
I believe something's wrong with version 3.0.1. Can someone please confirm that?
Q1: Is there an alternative way to convert an image to greyscale with Imagick?
Q2: Is it possible to convert a GD resource to Imagick? So I can use imagefilter($img, IMG_FILTER_GRAYSCALE); to get the correct result and then output with Imagick.
ps: For Q2, you might suggest me to just use GD to process the image. But the problem is that imagejpeg() cannot save images with resolution preserved. and that is actually the reason I switched to Imagick.
This is my preferred way to make a B&W photo in php/imagick: $im = $im->fxImage('intensity');
That applies a function to the image, where intensity is equal to 0.299*red+0.587*green+0.114*blue.
That formula is based on how our eyes are more sensitive to different colours, and as such the difference between that and a "flat" grayscale image really is night and day.
More details here:
http://php.net/manual/en/imagick.fximage.php
http://www.imagemagick.org/script/fx.php
function ImagickToGD($imagick){
$tmpfile = tmpfile();
$imagick->writeImage($tmpfile);
return imagecreatefromstring(file_get_contents($tmpfile));
}
Note that this function does not do any cleanup (except the temp file, which PHP cleans automatically).
So, for example, your code should look like:
$img = new Imagick();
// ...
$gd = ImagickToGD($img);
unset($img); // destroy imagick
imagefilter($gd, IMG_FILTER_GRAYSCALE);
imagejpeg($gd, $target_name, 100);
imagedestroy($gd);
Also, I did not understand the part about "preserving resolution". There is nothing in these operations relating to resolution. My guess is you meant compression? If you want full quality (ie, no compression) simply use 100 as compression value (as I did).
This results in maintaining the existing quality, since opening an image of 70% quality and saving it back with 70% quality actually decreases the final quality by 49% (70% of 70%).
function GDToImagickTo($gd){
$tmpfile = tmpfile();
imagepng($tmpfile); // Png is our best image deal:
// lossless compression, transparency etc..
$imagick = new Imagick()
$imagick->readImage($tmpfile);
return $imagick;
}
Refer this website and check out the image Magick operators found here www.rubblewebs.co.uk/imagemagick/
Also go with www.fmwconcepts.com/imagemagick/ you will find some examples out here...
You can use the image class what you prefer and then use the method readImageBlob to send it to the imagick http://www.php.net/manual/en/imagick.readimageblob.php
While resizing an image, I have noticed that Imagick and Gmagick produce images with different filesize on HDD with the same options:
$image = new Imagick("c.jpg");
$image->thumbnailImage(260,195);
$image->writeImage("c_imagick.jpg");
outputs an Image with 88kb
$image = new Gmagick("c.jpg");
$image->thumbnailImage(260,195);
$image->writeImage("c_gmagick.jpg");
outputs an Image with 15kb
Does someone have any idea, why the difference is so huge?
Try setting the image compression settings prior to resizing.
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality(80);
Additionally, check the size of the resulting image. Comments in the PHP documentation lead me to believe that the automatic fit portion of thumbnailImage does not work as you would expect in IMagick.
From PHP Docs:
The fit functionality of thumbnailImage doesn't work as one would anticipate. Instead, use >this to make a thumbnail that has max of 200x82:
// Create thumbnail max of 200x82
$width=$im->getImageWidth();
if ($width > 200) { $im->thumbnailImage(200,null,0); }
$height=$im->getImageHeight();
if ($height > 82) { $im->thumbnailImage(null,82,0); }