Converting transparent PDF files with Imagick - php

I have a problem creating thumbnails with PHP and imagick. The code is working ok and the thumbnail is generated in the correct size etc but when I try to place a PDF logo on the thumbnail it turns half transparent. I guess it has something to do with the PDF file being generated in InDesign and it probably doesn't have any background defined. Has anyone come across this problem or has an idea what to do about it? I tried to put a white canvas in the background but that didn't help. I also specified a channel for the compositeImage function but that didn't help either.
This is the PDF file I'm having issues with: https://dl.dropbox.com/u/13712643/Case_Study.pdf
The generated Thumbnail looks like this:
https://dl.dropbox.com/u/13712643/Case_Study1.jpg
The code I have produced so far: http:// pastebin.com/74CYC972
Any ideas? Thank you for your help.

I had the same issue and I solved it by using Imagick::compositeImage that was found in here: php imagick convert PNG to jpg
The code goes something like this:
$im = new Imagick();
$im->readimage($pdfFile."[$currentPage]");
$res = $im->getimageresolution();
$bg = new Imagick();
$bg->setresolution($res["x"],$res["y"]); //setting the same image resolution
//create a white background image with the same width and height
$bg->newimage($im->getimagewidth(), $im->getimageheight(), 'white');
$bg->compositeimage($im, Imagick::COMPOSITE_OVER, 0, 0); //merging both images
$bg->setimageformat("png");
//then you can write to a file
$bg->writeImage('white-background-pdf-image.png');
//or output it
header('Content-type: image/png');
echo $bg;

May be this what you are looking for :
$im->setBackgroundColor(new ImagickPixel('transparent'));
http://www.php.net/manual/en/imagick.setbackgroundcolor.php

None of the existing answers worked for me. Flatten the image just after creating a new imagick() worked instead:
$im = $im->flattenImages();
Edit: The flattenImages method has been deprecated & removed. Use
$im = $im->mergeImageLayers( imagick::LAYERMETHOD_FLATTEN );

Related

Imagick php class not working when I try to set image resolution and color space for a base64 image then saving it in jpg format

I'm trying to generate a high resolution jpg image from base24 image string using imagick php class. the code runs with no errors.
However, the image saved does not show any resolution or color space in photo viewers or browsers. I don't know whether my code is working or not?!
Any help on this is highly appreciated.
$image_data = base64_decode($data);
$imagick = new Imagick();
$imagick->readImageBlob($image_data);
$jpegimagequality = 95;
$imagick->setImageCompression(Imagick::COMPRESSION_JPEG);
$imagick->setImageCompressionQuality($jpegimagequality);
$imagick->setImageResolution(300,300);
$imagick->setImageColorspace(Imagick::COLORSPACE_SRGB);
$imageResampled = $imagick->resampleImage(300, 300, Imagick::FILTER_UNDEFINED, 1);
$imagick->setImageFormat("jpg");
$devimageSaved = $imagick->writeImage('jpg:'.$hiResPosterImagePathDev);

php Imagick rotate and merge

i have 2 images one background and another one is layer first i want to rotate it then i want to place it somewhere using x and y.. it can be done using GD but in gd when rotate the image i get low quality and zigzag border.. so i tried to rotate in imagick it done its job good without zigzag and without loosing quality.. so i want to know how to place that rotated image to background...
Background
Image_2
Output should look like this
EDIT:
The code I have tried so far:
<?php
$imagick = new Imagick();
$imagick->readImage('137.png');
$imagick->rotateImage(new ImagickPixel('none'), -13.55);
$imagick->writeImage('my_rotated.png');
$imagick->clear();
$imagick->destroy();
?>
I was trying to find a solution myself. I guess this should get what you need:
$background = 'background.png';
$image = new Imagick($background);
// you can place the code below in a loop to put more images in order
$imgfile = 'foreground-image.png';
$part1 = new Imagick($imgfile);
$part1->rotateImage(new ImagickPixel('none'), -13.55);
$image->compositeImage($part1, Imagick::COMPOSITE_OVER, $left, $top);
$image->writeImage('my_rotated.png');
//save , flush , destroy etc...

php Imagemagick jpg black background

I have a php script to create jpg thumbnail of pdf as follows;
<?php
$file ="test.pdf";
$im = new imagick(realpath($file).'[0]');
$im->setImageFormat("jpg");
$im->resizeImage(200,200,1,0);
// start buffering
ob_start();
$thumbnail = $im->getImageBlob();
$contents = ob_get_contents();
ob_end_clean();
echo "<img src='data:image/jpg;base64,".base64_encode($thumbnail)."' />";
?>
But the resulting jpg have black background instead of white.. How can I fix this??
None of the previously posted answers worked for me however the below did:
$image = new Imagick;
$image->setResolution(300, 300);
$image->readImage("{$originalPath}[0]");
$image->setImageFormat('jpg');
$image->scaleImage(500, 500, true);
$image->setImageAlphaChannel(Imagick::VIRTUALPIXELMETHOD_WHITE);
As I'm using the Laravel framework I then take the converted image and store it using Laravels filesystem.
Storage::put($storePath, $image->getImageBlob());
Update: So I recently changed OS and whereas this previously worked on my Ubuntu machine on my Mac certain images were still coming out black.
I had to change the script to the below:
$image = new Imagick;
$image->setResolution(300, 300);
$image->setBackgroundColor('white');
$image->readImage("{$originalPath}[0]");
$image->setImageFormat('jpg');
$image->scaleImage(500, 500, true);
$image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$image->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
Seems important to set the background colour before reading in the image. I also flatten any possible layers and remove the alpha channel. I feel like I tried ALPHACHANNEL_REMOVE on my Ubuntu machine and it didn't work so hopefully between these answers readers can find something that works for them.
If your version of Imagick is not up to date, the setImageBackgroundColor may be wrong.
Swap the following line
$im->setImageBackgroundColor("red");
to this (Imagick version >= 2.1.0)
$im->setBackgroundColor(new ImagickPixel("red"));
or (Imagick version < 2.1.0)
$im->setBackgroundColor("red");
I solved it by;
$im = new imagick(realpath($file).'[0]');
$im->setCompression(Imagick::COMPRESSION_JPEG);
$im->setCompressionQuality(100);
$im->setImageFormat("jpeg");
$im->writeImage("imagename.jpg");
Simply adding this prevents the JPG to be created with a black background
-alpha off
change this code $im->setimageformat("jpg"); to this code
$im->setimageformat("png"); if you face a background colour issue.
Just use flattenImages() right after creating a new imagick():
$im = new Imagick('file.pdf[0]');
$im = $im->flattenImages();
Edit: The flattenImages method has been deprecated & removed. Use
$im = $im->mergeImageLayers( imagick::LAYERMETHOD_FLATTEN );
After endless attempts to append a pdf file with a jpeg image without getting black areas, I found the solution: the function transformImageColorspace
Used in this order works perfectly:
$im = new Imagick();
$im->readImage("file.pdf");
$im->transformImageColorspace(Imagick::COLORSPACE_SRGB);
$im->setImageFormat('jpeg');
$im->writeImage('image.jpg');
I would like to add to the excellent and helpful answers by saying that a slightly different approach is required if your PDF has multiple pages.
Something I was surprised to discover is that the Imagick class implements Iterable, which means you can run it through a foreach loop and operate on each page in turn (which it turns out is necessary because the layer, colour, and alpha channel changes appear to only take effect on the last page) which will be presented to you as a separate Imagick object:
$im = new Imagick('path/to/file.pdf');
foreach ($im as $c => $page)
{
// do what you need to do with each page and then...
$im->writeImage('path/to/image-'.$c.'.jpg');
}

Transparent to white in Imagick for PHP

I have a png image with a transparent background and I want to convert it to a jpg image with a white background.
The code is basically this:
$image = new Imagick('transparent.png');
$image->writeImage('opaque.jpg');
But that creates a black background jpg. I've been struggling with the worst documentation ever trying to find a way to convert the transparent to white to no avail.
Edit:
Well, I tried Marc B's idea and kind of got it to work.
$image = new Imagick('transparent.png');
$white = new Imagick();
$white->newImage($image->getImageWidth(), $image->getImageHeight(), "white");
$white->compositeimage($image, Imagick::COMPOSITE_OVER, 0, 0);
$white->writeImage('opaque.jpg');
$image->destroy();
$white->destroy();
The problem now is, it always causes the script to segfault.
flattenImages() actually works.
But keep in mind that it doesn't modify the given \Imagick() object but returns a new one:
$image = new \Imagick('transparent.png');
// Need to use the result of $image->flattenImages() here!
$image = $image->flattenImages();
$image->writeImage('opaque.jpg');
flattenImages() defaults to the background color white. If you want to use another background color you have to set it before loading the image:
$image = new \Imagick();
// Needs to be called before the image is loaded!
$image->setbackgroundcolor('green');
$image->readimage('transparent.png');
$image = $image->flattenImages();
$image->writeImage('opaque.jpg');
In general the Imagick API is very sensible when it comes to the order of function calls (just like convert and its parameters on the command line) so always check if your order is correct.
Good luck!
Edit April 2016:
$image->flattenImages() was deprecated and should be replaced by:
$image->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN)
It's hard to find exact informations about this, but it seems that this applies to PHP >= 5.6.
Thanks to vee for the tip!
Try:
$image = new Imagick('transparent.png');
$image->setImageMatte(true);
$image->setImageMatteColor('white');
$image->setImageAlphaChannel(Imagick::ALPHACHANNEL_OPAQUE);
$image->writeImage('opaque.jpg');
I ran into the same problem when converting PDFs to PNGs, and I used flattenImages().
//get the first page of the PDF
$im = new imagick( $file.'[0]' );
//set the background to white
$im->setImageBackgroundColor('white');
//flatten the image
$im = $im->flattenImages();
//do the rest of the image operations
$im->setResolution( 181, 181 );
$im->setCompressionQuality(100);
$im->resizeImage ( 181, 181, imagick::FILTER_LANCZOS, 1, TRUE);
$im->setImageFormat('png');
$imageName = $title.'_thumb.png';
$image = new Imagick('transparent.pdf');
$image->setImageType (imagick::IMGTYPE_TRUECOLOR);
$image->writeImage('opaque.tif');
did for me!
(instead of the formerly imagick::IMGTYPE_TRUECOLORMATTE)
Try this one:
$white->newImage($image->getImageWidth(), $image->getImageHeight(), "transparent");
You can try it by changing Imagick constant as shown below
//$image will conatains image which needs background to be transparent
$white = new Imagick();
$white->newImage($image->getImageWidth(), $image->getImageHeight(), new ImagickPixel( "white" ));
$white->compositeimage($image, Imagick::COMPOSITE_DEFAULT, $x1OfTransparentImage, $y1OfTransparentImage,);
$white->flattenImages();
$white->writeImage('opaque.jpg');
$white->destroy();
Try the following, it works for me:
$im = new Imagick('trans.png');
$im->setimagebackgroundcolor('white');
$im = $im->flattenimages();
$im->writeimage('transToWhite.jpg');
Hope that helps!
Regarding the issue with segfault I ran into the same issue.
Apparently $image->writeImage('somename') destroys $image or the reference to it.
I was running into the same issue. The way I got around it was by removing the call to destroy on the object that I had finished writing. Seems sloppy but that solved the issue with the segfault
Segfault issue:
I had a similar problem (script kept giving me segfault, even when the image was properly processed and written), the solution I found came after checking bug reports, see:
https://bugs.php.net/bug.php?id=61122
Knowing that, try adding
$white->setResourceLimit(6, 1); // 6 means "limit threads to"
before the problematic line (in my case I had to put it before $im->resizeImage(...);)
I had a situation where I was trying to replace transparent background with white (but keep as png). Tried several different methods (including setImageAlphaChannel with setImageBackgroundColor). Combining OP's use of compositeImage I came up with this (hopefully helpful to someone else):
$pic = new Imagick($filelocation); //specify file name
$pic->setResourceLimit(6, 1);
if ($pic->getImageAlphaChannel()) {
$white = new Imagick();
$white->newImage($pic->getImageWidth(), $pic->getImageHeight(), "white");
$white->compositeImage($pic, Imagick::COMPOSITE_OVER, 0, 0);
$pic = clone $white;
$white->destroy();
$pic->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
}
//do more things with $pic

How to change the background black color to transparent?

I am rotating an image using Image Magick (as PHP-GD scales down image).
But it leaves the background to be black. Also, the image doesn't look good at all(but better than PHP-GD).
Any suggestions?
#oren , #razzed
Here's the code
$patchImageS = 'kapeels.png'; // the image to be patched over the final bg
$imagick = new Imagick(); $imagick->readImage($patchImageS);
$imagick->rotateImage(new ImagickPixel(), 355);
$imagick->transparentPaintImage('black', 0.0,0,false);
header('content-type:image/png');
$fp=fopen('tts.png','w+');
fwrite($fp,$imagick->getImage());
fclose($fp);
And this's the image which I am trying to rotate -
http://www.lilpirate.net/kapeels.png
Thanks for the reply guys :-)
After create Imagick object, in him arguments set a background transparent:
$imagick->newimage($width, $height, "rgba(0, 0, 0, 0)");
Rotate the image like this:
$im = new Imagick('kapeels.png');
$im->rotateImage( new ImagickPixel('none'), 7 );
$im->trimImage ( 0 );
$im->resetImagePage( '216x174+0+0' );
$im->writeImage('rotateImage.png');
$im->destroy();
You need thr repage to center the image back on the canvas but I do not know why you need values as Imagemagick does not use them. The only way I can think of automatical setting the values is to get the image size after the trim and use that in the reset.
With the quility all I could suggest is start with a larger image and reduce it after the rotate and see if that helps; perhaps use some sharpening. But I do not think much will help as the lines are so thin and close together.

Categories