Imagick - set paper size of output pdf - php

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.

Related

Imagick - When resizing, image gets blurry

I am trying to resize a pdf (which i converted from image), and I am trying to resize (increase) the image in its ratio.
$imagick = new \Imagick();
$imagick->readImage($path);
$imagick->resizeImage(595,842,\Imagick::FILTER_CUBIC, 1, true);
// and this:
// $imagick->adaptiveResizeImage(595,842, true);
$imagick->setImageFormat('pdf');
$imagick->writeImage($endpath);
But the image is getting blurry. However, it's not a bad quality image and the image can go that size without getting disturbed. (For example, if I let Twilio to do it (via fax api), the same image can get to that scale).
I have also tried with putting blur parameter of resizeImage between '1' and '0.1'
Original pdf (you can also see it here, if you want to try):
My resized pdf (with blur 1):
My "adaptive resized" pdf:
You are starting with a very small pdf if rasterized and enlarging. So that would cause blurring. But if you increase the input density, it works fine for me in ImageMagick as
convert -density 600 input.pdf -resize 595x842 result.png
I do not know Imagick well, but try the following. Reduce the blur value in resizeImage as desired to make it sharper.
$imagick = new \Imagick();
$imagick->readImage($path);
$imagick->Imagick::setImageResolution( 600, 600 );
$imagick->resizeImage(595,842,\Imagick::FILTER_CATROM, 1, true);
$imagick->setImageFormat('pdf');
$imagick->writeImage($endpath);

ImageMagick - Convert PDF to JPG and Set Width

I am currently converting a PDF to a set of images using ImageMagick like this..
// create Imagick object
$imagick = new Imagick();
// Reads image from PDF
$imagick->readImage('book.pdf');
// Writes an image
$imagick->writeImages('converted.jpg', false);
The resulting images are quite small, is there a way to set a defined width and then let the height work itself out?

Convert PDF (with transparency *and* CMYK) to jpg

I need to generate jpg images from PDF files (first page only). The PDF files are user generated, so they can contain anything. I'm currently using the following code:
// Load PDF.
$i = new Imagick;
// Create thumbnail of first page of PDF.
$i->setResolution(150, 150);
$i->loadImage("test.pdf[0]");
$i->thumbnailImage(640, 480, true);
// Remove transparency, fill transparent areas with white rather than black.
$i->setImageBackgroundColor("white");
$i->setImageAlphaChannel(11); // Imagick::ALPHACHANNEL_REMOVE
$i->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
// Output.
$i->writeImage("test.jpg");
This works as expected in that transparency becomes white instead of black. However, I've run into problems with some generated jpg images, so I ran jpeginfo on them:
$ jpeginfo -c test.jpg
test.jpg 960 x 480 32bit JFIF N 9481 Unsupported color conversion request [ERROR]
It turns out that some source PDFs actually use CMYK, and apparently are not converted to RGB when saved as jpg. So I changed my code to the following (addition of a single line) to explicitly convert to RGB:
// Load PDF.
$i = new Imagick;
// Create thumbnail of first page of PDF.
$i->setResolution(150, 150);
$i->loadImage("test.pdf[0]");
$i->thumbnailImage(640, 480, true);
// Remove transparency, fill transparent areas with white rather than black.
$i->setImageBackgroundColor("white");
$i->setImageAlphaChannel(11); // Imagick::ALPHACHANNEL_REMOVE
$i->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
// Convert to RGB to prevent creating a jpg with CMYK colors.
$i->setImageColorspace(Imagick::COLORSPACE_RGB);
// Output.
$i->writeImage("test.jpg");
This creates a jpeg with an RGB color profile, all right. However, for some obscure reason it results in an image with a black background again. In other words: the transparency problem is back. Why does Imagick do this, and more importantly, what's the solution to both the transparency problem and the CMYK problem?
The correct function to use is transformImageColorspace not setImageColorspace. transformImageColorspace is used for existing images, setImageColorspace is for new images e.g. svg drawing..
I've added it to the manual and it should show up soon.

Optimize PNG when resizing with GD/PHP - How to determine color palette?

I had troubles resizing a PNG and maintaining small file sizes. Solution found here.
When resizing the PNG, however, I ran into problems regarding image quality. As far as I could see, GD uses indexed 8-bit-color palette which distorts text and colors get lost, see:
Original Image
Resized Image with solution given above
Resized Image with a tweak²
²The idea for the tweak I found here in stackoverflow: Create truecolor-image, resize it, and copy it to a new image, so the palette is determined based on the resampled result and the image quality is better as you can see in the image above.
// create new image
$newImageTmp = imagecreatetruecolor($newwidth,$newheight);
// we create a temporary truecolor image
// do the image resizing by copying from the original into $newImageTmp image
imagecopyresampled($newImageTmp,$src,0,0,0,0,$newwidth,$newheight,$width,$height);
// create output image
$newImage = imagecreate($newwidth,$newheight);
// copy resized truecolor image onto index-color image
imagecopy($newImage,$newImageTmp,0,0,0,0,$newwidth,$newheight);
// write image to buffer and save in variable
ob_start(); // stdout --> buffer
imagepng($newImage,NULL,6);
$newImageToSave = ob_get_contents(); // store stdout in $newImageToSave
ob_end_clean(); // clear buffer
// remove images from php buffer
imagedestroy($src);
imagedestroy($newImageTmp);
imagedestroy($newImage);
Problem: None of both results are satisfactory.
I am quite sure that there must be a way to 1. determine the color palette, and 2. maintain most of the image's colors, so that 3. the PNG looks similar to the original and has an acceptable file size.
Now, I only see going for JPG instead of PNG. But if you know a solution, it would greatly be appreciated if you let me/us know.
Thank you!
All you need is to replace
$newImage = imagecreate($newwidth,$newheight);
With
$newImage = imagecreatetruecolor($newwidth, $newheight);
Output $maxImgWidth = 200;
PHP's fork of GD doesn't have usable palette generation, so you only get PNG32 with vanialla libpng compression.
For small PNG8 with palette use pngquant, e.g. http://pngquant.org/php.html
And then compress it further with advpng or zopfli-png.

imagemagick - downsize/crop/save to jpeg in one go?

I have a php script that will receive a bunch of images uploaded.
What I need to do is create a small thumbnail of each, on the fly using imagemagick.
I can do that easy enough but I also need to crop it so that the thumbnail is always 100x100.
the images supplied won't be the same proportions so simply downsizing won't work.
Can I downsize, crop to 100x100 and save to jpeg all in one step?
I believe this should do what you want:
convert 'just_uploaded/*' -resize 100x100^ -gravity center -extent 100x100 -set filename:f '%t' +adjoin 'just_uploaded_thumbs/%[filename:f].jpg'
resize will downsize, extent (in combination with gravity) will crop, and the rest takes care of saving with a modified name, in JPEG format, in a different directory.
Short answer: no. That'll be 3 steps, no less.
Longer answer: you can do it using the command line interface. In PHP, the only way is to write a function that will do what you ask. Then, for each image, you can just call your function. I'm not sure how this is more beneficial than just using the 3 Imagick functions separately...
I like the sfThumbnailPlugin. It wraps around both ImageMagick or GD
http://www.symfony-project.org/plugins/sfThumbnailPlugin
Example:
public function executeUpload()
{
// Retrieve the name of the uploaded file
$fileName = $this->getRequest()->getFileName('file');
// Create the thumbnail
$thumbnail = new sfThumbnail(150, 150);
$thumbnail->loadFile($this->getRequest()->getFilePath('file'));
$thumbnail->save(sfConfig::get('sf_upload_dir').'/thumbnail/'.$fileName, 'image/png');
// Move the uploaded file to the 'uploads' directory
$this->getRequest()->moveFile('file', sfConfig::get('sf_upload_dir').'/'.$fileName);
// Do whatever is next
$this->redirect('media/show?filename='.$fileName);
}

Categories