Php Imagick : Pdf are converted into JPG with Very bad quality - php

I am using Imagick extension in my one of project. This is new for me.
The following is my code.
$pdfPath = $config['upload_path'] . '/' . $fileName;
$im = new imagick();
$im->setResolution(300, 300);
$im->readImage($pdfPath);
$im->setImageFormat('jpeg');
$im->setImageCompression(imagick::COMPRESSION_JPEG);
$im->setImageCompressionQuality(100);
$im->writeImage($config['upload_path'] . '/' . str_replace('pdf', 'jpeg', $fileName));
$im->clear();
$im->destroy();
This gives me very poor quality in image.
All text are converted into black background. Images are also not showing proper.
See below image, which is converted from PDF.
Please help me.

You need to put options for the image background color set white. For here I have added options of $im->->flattenImages();
Here you can find out the solutions https://www.binarytides.com/convert-pdf-image-imagemagick-php/
From
$pdfPath = $config['upload_path'] . '/' . $fileName;
$im = new imagick();
$im->setResolution(300, 300);
$im->readImage($pdfPath);
$im->setImageFormat('jpeg');
$im->setImageCompression(imagick::COMPRESSION_JPEG);
$im->setImageCompressionQuality(100);
$im->writeImage($config['upload_path'] . '/' . str_replace('pdf', 'jpeg', $fileName));
$im->clear();
$im->destroy();
TO
$pdfPath = $config['upload_path'] . '/' . $fileName;
$im = new imagick();
$im->setResolution(300, 300);
$im->readImage($pdfPath);
$im->setImageFormat('jpeg');
$im->setImageCompression(imagick::COMPRESSION_JPEG);
$im->setImageCompressionQuality(100);
// -flatten option, this is necessary for images with transparency, it will produce white background for transparent regions
$im = $im->flattenImages();
$im->writeImage($config['upload_path'] . '/' . str_replace('pdf', 'jpeg', $fileName));
$im->clear();
$im->destroy();
I am not sure it will be help for you or not.

I think the problem lies in the fact that we are inputing a resolution of dots per inch from the pdf and outputting it as pixels per inch as we make the jpeg.
This codes works as far as it appears to keep the correct aspect ration and I can make out the pdf that I used to test. But it's not very clear at all, I cant read any text. Here is what I used.
$pdfPath = $config['upload_path'] . '/' . $fileName;
$img = new imagick();
$img->setResolution(300, 300);
$img->readImage($pdfPath); //Open after yuo set resolution.
$img->setImageUnits(imagick::RESOLUTION_PIXELSPERINCH); //Declare the units for resolution.
$img->setImageFormat('jpeg');
$img->setImageCompression(imagick::COMPRESSION_JPEG);
$img->setImageCompressionQuality(100);
$img->writeImage($config['upload_path'] . '/' . str_replace('pdf', 'jpeg', $fileName));
$img->clear();
$img->destroy();
From what I have read you may need to install Ghostscript on your machine and executing the script from your command line seems to be preferred and offer better results and performance.
I found this article and it looks like it's loaded with a bunch of info for image formats and how imagemagik handles them. It has a bit in there on PDFs.
http://www.imagemagick.org/Usage/formats/#tiff
I might look into a PHP PDF library that has all the stuff already built into it. No sense in reinventing the wheel. There might be a function already build in to do exactly what your trying to do.

Related

Create PDF thumbnail with Imagick and write to file

I'm trying to create a pdf thumbnail with Imagick and save it on the server in the same location as the pdf. The code below works fine as is. The problem is that I don't want to echo the image. But if I remove the echo statement, the resulting jpg file contains errors and is unreadable. How can I create the thumbnail and write to a file without sending it to the browser?
$pdfThumb = new \imagick();
$pdfThumb->setResolution(10, 10);
$pdfThumb->readImage($filePath . $fileName . $fileExt . '[0]');
$pdfThumb->setImageFormat('jpg');
header("Content-Type: image/jpeg");
echo $pdfThumb;
$fp = fopen($filePath . $fileName . '.jpg', "x");
$pdfThumb->writeImageFile($fp);
fclose($fp);
DaGhostman Dimitrov provided some helpful code on #16606642, but it doesn't work for me for some reason.
I would try:
$pdfThumb = new imagick();
$pdfThumb->setResolution(10, 10);
$pdfThumb->readImage($filePath . $fileName . $fileExt . '[0]');
$pdfThumb->setImageFormat('jpg');
$fp = $filePath . $fileName . '.jpg';
$pdfThumb->writeImage($fp);
Bonzo's answer requires imagick on the webserver. If imagick is not on the webserver you can try to execute imagemagick from the commandline by php command exec():
exec('convert -thumbnail "178^>" -background white -alpha remove -crop 178x178+0+0 my_pdf.pdf[0] my_pdf.png')
And if you like to convert all pdfs in one step from same folder where your script is located try this:
exec('for f in *.pdf; do convert -thumbnail "178^>" -background white -alpha remove -crop 178x178+0+0 "$f"[0] "${f%.pdf}.png"; done');
In this examples I create a png thumbnail 178x178 pixel from the first page (my_pdf.pdf[0] the 0 means first pdf page).

PHP Imagick() is taking to long to excecute

I running this script to create a jpg image from a pdf.
$im = new Imagick();
$im->setResolution(300, 300);
$im->readImage($temp_path . $file);
if ($im->getImageColorspace() == \Imagick::COLORSPACE_CMYK) {
$profiles = $im->getImageProfiles('*', false);
// we're only interested if ICC profile(s) exist
$has_icc_profile = (array_search('icc', $profiles) !== false);
// if it doesnt have a CMYK ICC profile, we add one
if ($has_icc_profile === false) {
$icc_cmyk = file_get_contents(dirname(dirname(__FILE__)) . '/USWebUncoated.icc');
$im->profileImage('icc', $icc_cmyk);
unset($icc_cmyk);
}
// then we add an RGB profile
$icc_rgb = file_get_contents(dirname(dirname(__FILE__)) . '/sRGB_v4_ICC_preference.icc');
$im->profileImage('icc', $icc_rgb);
unset($icc_rgb);
}
$im->setImageBackgroundColor('white');
$im = $im->flattenImages();
$im->setImageFormat('jpeg');
$im->thumbnailImage(900, 900, true);
Is working fine but the problem is that is taking to long to excecute. and some time if the file have to much detail I get a timeout excecution from php.
I was using it before without the profileImage() file and was working perfect, but the color on the CMYK was not right.
How can I make better and efficient. I running this on linux with php5.5.9
Thanks.
I recommend using cloudinary.com, check it out, it will save you a lot of time.
See if this is any faster and still contains the correct color:
<php
$im = new Imagick();
$im->readImage($temp_path . $file); //pdf
if ($im->getImageColorspace() == \Imagick::COLORSPACE_CMYK) {
$im->transformImageColorspace(\Imagick::COLORSPACE_SRGB);
}
$im->writeImage('out.jpg'); // jpg
?>

IMagick RGB to CMYK corrupt conversion

I'm converting images from RGB to CMYK with IMagick in PHP.
During conversion some images get black grids on them.
Code:
$IMagick = new IMagick();
$IMagick->clear();
$IMagick->readImage(SITE_ROOT . 'userfiles/image/products/' . $image);
$IMagick->negateImage(false, Imagick::CHANNEL_ALL);
$IMagick->setImageColorspace(13);
$icc_cmyk = file_get_contents(dirname(__FILE__).'/USWebCoatedSWOP.icc');
$IMagick->profileImage('icc', $icc_cmyk);
unset($icc_cmyk);
$IMagick->setImageColorspace(12);
$IMagick->writeImage (SITE_ROOT . 'userfiles/image/products/cmyk/' . $image);
Images:
Original
Converted
I'm converting around 80 images in a loop and most of them are OK.
Any idea why it happens?
EDIT:
Working code:
$IMagick = new IMagick();
$IMagick->clear();
$IMagick->readImage(SITE_ROOT . 'userfiles/image/products/' . $image);
$icc_cmyk = file_get_contents(dirname(__FILE__).'/USWebCoatedSWOP.icc');
$IMagick->profileImage('icc', $icc_cmyk);
unset($icc_cmyk);
$IMagick->transformImageColorspace(12);
$IMagick->writeImage (SITE_ROOT . 'userfiles/image/products/cmyk/' . $image);
setImageColorspace should only be used when creating new images, either through Imagick::newPseudoImage or rendering an ImagickDraw instance into an image.
For existing images, the correct method to change the colorspace of the image is Imagick::transformImageColorspace.

Resize copied image on upload as thumbnail

I am working on an uploader and slowly getting it working, I am uploading 3 images at once, and setting arrays for each one as keys, with an increment of ++1. I am wanting to resize the image before it gets copied to the thumbnail folder.
I have this code.
Everything works with it.
As you see, I started on getting the file info, but after that I am totally stuck on what to do after to resize the image proportionally with a maximum width of xpx and height to match it without looking distorted.
Any help would be really appreciated. Thank You.
EDIT --- I started working on it myself and wondering if this is the right approach to what i am doing.
<?php
if (isset($_POST['addpart'])) {
$image = $_FILES['images']['tmp_name'];
$name = $_POST['username'];
$i = 0;
foreach ($image as $key) {
$fileData = pathinfo(basename($_FILES["images"]["name"][$i]));
$fileName[] = $name . '_' . uniqid() . '.' . $fileData['extension'];
move_uploaded_file($key, "image/" . end($fileName));
copy("image/" . end($fileName), "image_thumbnail/" . end($fileName));
// START -- THE RESIZER THAT IS BEING WORKED ON
$source = "image_thumb/" . end($fileName);
$dest = "image_thumb/" . end($fileName);
$quality = 100;
$scale = 1 / 2;
$imsize = getimagesize($source);
$x = $scale * $imsize[0];
$y = $scale * $imsize[1];
$im = imagecreatefromjpeg($source);
$newim = imagecreatetruecolor($x, $y);
imagecopyresampled($newim, $im, 0, 0, 0, 0, $x, $y, $imsize[0], $imsize[1]);
imagejpeg($newim, $dest, $quality);
// END -- THE RESIZER THAT IS BEING WORKED ON
$i++;
}
echo 'Uploaded<br>';
echo 'Main Image - ' . $fileName[0] . '<br>';
echo 'Extra Image 1 - ' . $fileName[1] . '<br>';
echo 'Extra Image 2 - ' . $fileName[2] . '<br>';
echo '<hr>';
}
?>
thanks
Use GD library.
Create input image object using imagecreatefromstring() for example: imagecreatefromstring(file_get_contents($_FILES['images']['tmp_name'][$i]))
It's the simplest way.
Another option is to detect file type and use functions like imagecreatefromjpeg (), imagecreatefrompng(), etc.
Create output empty image using imagecreate()
Use imagecopyresampled() or imagecopyresized() to resize image and copy+paste it from input image to output image
Save output image using function like imagejpeg()
Clean memory using imagedestroy()
The built-in image manipulation commands of PHP makes your code difficult to understand and to maintain. I suggest you to use a library which wraps it into a more productive way.
If you use Intervention/image, for example, your code will look like this:
<?php
// target file to manipulate
$filename = $_FILES['images']['tmp_name'];
// create image instance
$img = Image::make($filename);
// resize to width, height
$img->resize(320, 240);
// save it!
$img->save('thumbs/'. uniqid() . '.' . pathinfo($filename, PATHINFO_EXTENSION));
Read the full documentation here: http://image.intervention.io/use/uploads

PHP imagefilter and uploadify

I have a question on how to filter image while moving the file. I used uploadify to upload image. What I did is, before he move the image to the directory, the code filter will covert the image to grayscale.
Here is my code
if (!empty($_FILES)) {
$tempFile = $_FILES['Filedata']['tmp_name'];
$targetPath = $_SERVER['DOCUMENT_ROOT'] . $_REQUEST['folder'] . '/';
$targetFile = str_replace('//','/',$targetPath) . $_FILES['Filedata']['name'];
$newImg = imagefilter($tempFile, IMG_FILTER_GRAYSCALE); // This is what I insert
move_uploaded_file($newImg,$targetFile);
echo "1";
}
The code is uploadify.php and I just inserted a filter to make it grayscale. Please help me. Thanks in advance.
Imagefilter works on an image resource, not a file, and also a boolean, not a new image. It's probably worth reading through the documentation, but you'll need to change your code to something along these lines
if (!empty($_FILES)) {
$tempFile = $_FILES['Filedata']['tmp_name'];
$targetPath = $_SERVER['DOCUMENT_ROOT'] . $_REQUEST['folder'] . '/';
$targetFile = str_replace('//','/',$targetPath) . $_FILES['Filedata']['name'];
// Create an image resource - exact method will depend on the image type (PNG, JPEG, etc)
$im = imagecreatefrompng($tempFile);
// Apply your filter
imagefilter($im, IMG_FILTER_GRAYSCALE);
// Save your changes
imagepng($im, $tempFile);
move_uploaded_file($tempFile,$targetFile);
echo "1";
}
To use imagefilter you have to load image first. Use one of GD load functions ( like: imagecreatefrompng).
Then you can use filter on loaded image. By the way check parameters for imagefilter (which requires loaded image, not path to image). Here is some example code (that replaces your imagefilter()):
// Check extension of the file, here is example if the file is png, but you have to check for extension and use specified function
$img = imagecreatefrompng($tempFile);
if( imagefilter($img, IMG_FILTER_GRAYSCALE) )
{
// success
}
else
{
// failture
}
// Save file as png to $targetFile
imagepng($img, $targetFile);
// Destroy useless resource
imagedestroy($img);

Categories