PHP Image editing (am I doing it wrong ?) - php

I need to resize and stitch togehter 7 images, for that I'm using ImageMagick but it's oughly heavy and takes a long time to perform. Is there any other lighter library I can use ?
Or perhaps my code is to blame:
<?php
header('Content-type: image/jpeg');
$thumb = new Imagick();
$thumb->newImage(128*7,128, 'black');
$thumb->borderImage( 'purple', 1, 1 );
$images = new Imagick(glob('*.jpg'));
$counter =0;
foreach($images as $image) {
// Providing 0 forces thumbnailImage to maintain aspect ratio
$image->thumbnailImage(128,128, true);
$thumb->compositeImage($image,Imagick::COMPOSITE_DEFAULT, (128*$counter)+(64-$image->getImageWidth()/2),64-$image->getImageHeight()/2);//echo $image;
$counter++;
}
$thumb->setImageFormat('jpeg');
echo $thumb;
?>
UPDATE:
As it is for an iPhone app I decided to do the resizing and stitching on the iPhone itself (and then upload the result to the server for future use).

I do not use imagick but use Imagemagick command line with php exec() and you can speed up jpg resizing using define as a "hint". I belive it only reads enough of the input image to create the output image.
Anyway there was a post on the Imagemagick forum a couple of weeks ago about speeding up jpg resizing with Imagick and the answer was:
$image = new Imagick();
$image->setOption('jpeg:size', '800x532');
$image->readImage('origional.jpg');
I am not sure how this would work in your case and the original thread is:
http://www.imagemagick.org/discourse-server/viewtopic.php?f=10&t=20586&hilit=speed

As I'm writing an iPhone app and my resources on the server are low I decided to do the "hard" work on the iphone's side.
Daniel

Related

PHP Imagick PSD thumbs getting strange artifacts

We have a server that accepts PSD files. It will load it into a new Imagick object and create 4 jpg thumbs for it.
Oddly the first thumb, the largest one looks great. Each thumb after that experiences some image distortion where a layer was using a stroke effect.
Code:
$image = new Imagick($fileName);
$image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
foreach ($thumbSizes as $key => $size) { //largest to smallest
if($size>$longestSide){
$size = $longestSide;
}
$this->image->thumbnailImage($size,$size,true);
$this->image->writeImage($nameBase . '-' . $key . ".$extension");
}
$image->destroy();
I'm not sure how Imagick works internally, but my intuition tells me that if the largest thumb is accurate then each one after that should be.
NOTE: I expect some image distortion when resizing an image. But if you look at the example I posted it's different than your normal resizing artifacts. It's changing the color of some text. I assume it's a problem with it resizing the stroke effect. But I would have thought since I flattened the image first, the stroke effect wouldn't exist anymore. I can pass in a jpeg representation of the same file and it resizes them all perfectly.
I think the PSD conversion is just borked by the library/special FX on the PSD. This is the first image output by similar code to yours:
The color of the number is transparent rather than black - but similarly, not correct. If the issue is being caused by the FX on that layer and you can't find a version of the library that processes the PSD that works correctly, I would suggest not using Imagick/ImageMagick to do the processing, but instead install a copy of Photoshop on the server and use the CLI processing capabilities of Photoshop itself to do the processing: https://helpx.adobe.com/photoshop/using/processing-batch-files.html .
btw an observation - you are resizing the same image repeatedly, this is less than optimal. You can avoid this by resizing a clone of the original image:
foreach ($thumbSizes as $key => $size) { //largest to smallest
$temp = clone $image;
if($size>$longestSide){
$size = $longestSide;
}
$temp->thumbnailImage($size,$size,true);
$temp->writeImage($nameBase . '-' . $key . ".$extension");
}
This should give a slightly higher output image quality.

COMPOSITE_DISSOLVE is not working in PHP

I want to make the mixed image with fade effect from two images.
Here is my PHP code.
$img1 = new Imagick();
$img1->readImage("images/1.jpg");
$img2 = new Imagick();
$img2->setOption('compose:args', '50');
$img2->readImage("images/2.jpg");
$img1->compositeImage($img2, imagick::COMPOSITE_DISSOLVE, 0, 0);
$img1->writeImage("images/3.jpg");
This code works correctly on my Mac OS.
But it doesn't work on remote server (Cent OS 6.5), the result image is same with 2.jpg.
I tried with COMPOSITE_BLEND constant, it works well.
And I tried the command in terminal.
# composite -dissolve 50 2.jpg 1.jpg 3.jpg
It also works well.
Why doesn't COMPOSITE_DISSOLVE constant work in PHP?
Please help me.
You really ought to just figure out what the difference is between your dev environment and your server. It's very likely to be the case that the version of ImageMagick on the dev server is very out of date, unless you are compiling it yourself, as the Centos packages management system seems to take a long time to get new releases.
However....the way you are blending the images is not fantastic. Although it may work for you, it requires the slightly poorly defined $img2->setOption('compose:args', '50'); line.
A much more powerful technique is to control the alpha channel yourself through the COMPOSITE_COPYOPACITY. This gives you full control for how images are blended. e.g.
$img1 = new \Imagick();
$img1->readImage(realpath("../images/Biter_500.jpg"));
$img2 = new \Imagick();
$img2->readImage(realpath("../images/Skyline_400.jpg"));
//Resize images to the same size, to look pretty.
$img1->resizeimage(
$img2->getImageWidth(),
$img2->getImageHeight(),
\Imagick::FILTER_LANCZOS,
1
);
//Create an image that the alpha will be created in.
$opacity = new \Imagick();
if (true) {
//Create a 50% grey image
$opacity->newPseudoImage($img1->getImageWidth(), $img1->getImageHeight(), "CANVAS:gray(50%)");
}
else {
//Create a far more interesting blend.
//Gradients are created top to bottom, so we need to rotate the image
$opacity->newPseudoImage($img1->getImageHeight(), $img1->getImageWidth(), "gradient:gray(10%)-gray(90%)");
$opacity->rotateimage('black', 90);
}
$img2->compositeImage($opacity, \Imagick::COMPOSITE_COPYOPACITY, 0, 0);
$img1->compositeImage($img2, \Imagick::COMPOSITE_ATOP, 0, 0);
header("Content-Type: image/jpg");
echo $img1->getImageBlob();
The first way of creating the opacity image with "CANVAS:gray(50%)" does what your existing image code does. The second way of blending creates a image that is blended from 10% to 90% across the width of the image.

PHP Imagick - convert image to greyscale (very bad result)

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

How to display image like facebook

i want to display images like facebook find friends page. i dont want to crop an image. want to reduce size of image.and maintains its actuall appereance.how i can do this.
I recommend the IMagick extension for PHP since it's light on resources and easy to use. The GD extension comes bundled with PHP, but is harder to use and uses a lot of memory.
Here's an example for IMagick:
<?php
header('Content-type: image/jpeg');
$image = new Imagick('image.jpg');
$image->thumbnailImage(100, 100, true);
echo $image;
?>
i dont want to crop an image. want to reduce size of image.and maintains its actuall appereance.
If the actual image size is 128*128 pixel you can use
<img src="..." height="64px" />
"actuall appereance." i think you are talking bout ratio ?

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');
}

Categories