getting image dimensions in imagick - php

I'm trying to get the dimensions of images that i converted with imagick. This is my code:
$imagick = new \Imagick();
$imagick->setresolution(300,300);
$imagick->readimage($this->uploadPath . '/original/test.pdf');
$imagick->writeImages($this->uploadPath . "/large/preview-%d.jpg", false);
So i'm reading a multipage pdf file and i'm converting it to seperate jpg files.
What i want is to retrieve the jpg file dimensions from each image. Can i do this in an easy way? Or do i first need to write the images to the disc and then loop through each of them again?

What about Imagick::getImageGeometry? (http://www.php.net/manual/en/imagick.getimagegeometry.php)
In your case it should look something like this:
$imagick = new \Imagick();
$imagick->setresolution(300,300);
$imagick->readimage($this->uploadPath . '/original/test.pdf');
$geometryInfo = $imagick->getImageGeometry();
// now $geometryInfo is an associative array with 'width' and 'height' items in it
$imagick->writeImages($this->uploadPath . "/large/preview-%d.jpg", false);
Update:
If you want to read concrete page from multipage PDF, try to use such trick:
$pageIndex = 0; // you can create "for/foreach" loop to go through all pages
$imagick->readimage($this->uploadPath . '/original/test.pdf[' . $pageIndex . ']');

Related

Convert .HEIC sequence to animated .GIF using Imagick

I've managed to install Imagemagick 7 on my server and set-up the appropriate PHP module in order to work with HEIC and WebP files using Imagick.
I can convert these files easily to other formats like PNG or JPEG without any problems.
Now, I try to convert a HEIC sequence (original file) to GIF, but the result is imperfect.
First off all, it seems, that Imagick isn't able to determine the delay between every image. This results in a lightning fast animation. So for now, I've hardcoded a delay of 40 ticks using Imagick::setImageDelay. I'm not sure, if I'm missing something, or if Imagick/Imagemagick isn't able to do this on HEIC sequences.
The next problem I'm experiencing is, that Imagick can't handle the original image dimensions properly. To get around this, I have to get the original image's dimensions and perform Imagick::cropImage and Imagick::thumbnailImage on every frame, before I finalize it with Imagick::setImagePage.
However, my biggest problem for now is, that the result has a broken, first frame:
So the final (broken) result looks like this:
While the expected result (generated by heic2any) is:
The (simplified) code I am using:
<?php
if (!in_array('HEIC', \Imagick::queryFormats("HEI*"))) {
throw new \Exception('Unsupported format');
}
$sourceFile = __DIR__ . '/3.heic';
$targetFile = __DIR__ . '/3.gif';
if (!file_exists($sourceFile)) {
try {
$content = file_get_contents('https://github.com/alexcorvi/heic2any/blob/master/demo/' . basename($sourceFile) . '?raw=true');
if ($content === false) {
throw new \Exception('Unable to download source file.');
}
file_put_contents($sourceFile, $content);
} catch (\Exception $e) {
throw new \Exception('Unable to download source file: ' . $e->getMessage());
}
if (!file_exists($sourceFile)) {
throw new \Exception('Cannot find source file.');
}
}
$im = new \Imagick($sourceFile);
$width = $im->getImageWidth();
$height = $im->getImageHeight();
$im = $im->coalesceImages();
foreach ($im as $frame) {
$im->setImageDelay(40);
$frame->cropImage($width, $height, 0, 0);
$frame->thumbnailImage($width, $height);
$frame->setImagePage($width, $height, 0, 0);
}
$im = $im->deconstructImages();
$im->writeImages($targetFile, true);
echo 'Size: ' . $width . 'x' . $height . '<br />Result:<br /><br /><img src="' . basename($targetFile) . '?v=' . time() . '" alt="" />';
So my questions are:
Where does the 1st frame come from?
How can I avoid it?
Is there anything to optimize the conversion (code)?
UPDATE:
There's another .HEIC sequence to play with (click) and this one can be converted without problems:
UPDATE:
Even conversion services like cloudconvert can't handle the image correctly and producing GIF animations like this:

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

Html to PDF to JPEG

I am basically all the way there. I am unsure how to push the temporary pdf object to imagick to generate and return the jpeg image. Using mPDF's standard output(), I get the pdf rendered to the screen:
$mpdf=new mPDF();
$mpdf->WriteHTML($output);
$img = new Imagick($mpdf->output());
$img->setResolution(300,300);
$img->resampleImage(150,150,imagick::FILTER_UNDEFINED,1);
$img->resizeImage(512,700,Imagick::FILTER_LANCZOS,0);
$img->setImageFormat('jpeg');
$img->setImageUnits(imagick::RESOLUTION_PIXELSPERINCH);
$img->writeImage ("test.jpeg");
Under this scenario I get the pdf outputed to the screen instead of a jpg image returned/created. What is the proper way to pass the pdf into imagick?
I think you need: $mpdf->Output('temp/'.$filename.'.pdf','F');
$mpdf->Output('temp/'.$filename.'.pdf','F');
$pdf_file = 'temp/'.$filename.'.pdf';
$savepath = 'temp/'.$filename.'.jpg';
$img = new imagick($pdf_file);
$img->setImageFormat('jpg');
$img->writeImage($savepath);
echo "<img src='temp/$filename.jpg' />";
http://phpform.net/pdf-to-image.php

Zend pdf errors with function Image drawing

I want to put image to my pdf file from code function in zend that i get simple example from here http://framework.zend.com/manual/1.12/en/zend.pdf.drawing.html and this is my code
$image = Zend_Pdf_Image::imageWithPath("' . $base . '/images/logo1.png");
$page->drawImage($image, 100, 100, 400, 300);
// add page to document
$pdf->pages[] = $page;
$pdf->save("data/reports/-report.pdf");
but i get errors like this
PDF error: Cannot create image resource. File not found.
any help with it. thanks
your including single quotes inside a file name.
$image = Zend_Pdf_Image::imageWithPath("' . $base . '/images/logo1.png");
change it so it reads
$image = Zend_Pdf_Image::imageWithPath($base . "/images/logo1.png");

Categories