resizing an image with php and imagemagick take too much time - php

After several test i decided use scaleimage method of imagick for reduce images, the problem is because i want to get a square image and some of the images to process are rectangular.
To make it square i placed a blank square image as background after the scaled image, this point took me 4 second per image and it's too much.
// Create an image
$scaledimage = new Imagick();
// Set as black
$scaledimage->newImage(800,600,'black');
//Scale the image
$scaledimage->scaleImage(500,500,true); // I need the same aspect
// Create an image
$image = new Imagick();
// Set as white
$image->newImage(500,500,'white');
// compose an image onto another
$image->compositeImage($scaledimage,Imagick::COMPOSITE_DEFAULT,62,0);
// Clone
$scaledimage = clone $image;
Do you known how could i do to make the scaled image square without use this approach.

Related

How can I shrink and center the output size of a pdf image using ImageMagick?

I am getting a .gif image back from the UPS API that I need to build an 8.5x11 pdf image out of (for printing). I can build a PDF, but it's huge - more like 11x8.5. How can I shrink the width of the output document? The resizeImage call didn't seem to do it.
$base64_string = $accept->PackageResults->LabelImage->GraphicImage;
$imageBlob = base64_decode( $base64_string);
$img = new Imagick();
$img->readImageBlob($imageBlob);
$img->setImageFormat('pdf');
$img->setImagePage(612,792); // Letter size
$success = $img->writeImage($label_file);
It seems like I can reduce the size with
$img->setResolution(216, 216);
but then the smaller image appears in the upper left hand edge of the page, which still makes it unusable. How could I center the image on the page or at least create a 2" left margin?
Is something like
$img->borderImage('white', <some_number>, 0);
the way to go? (The use case here is that people want to send this image directly to their label printer.)

Cropping an image from the center into the largest square you can make in Yii2 Imagine?

I'm using the Yii2 extension Imagine and I need to make 150x150 images from user uploads.
Currently I am just doing something like this:
use yii\imagine\Image;
....
Image::thumbnail($save_path, $img_size, $img_size)->save($save_path);
Obviously this can cause issues if one of the dimensions is < 150px once resized.
So what I'm trying to primarily figure out is how to crop the image into a square before it is resized, so that when I resize it there won't be any aspect ratio issues.
Now, I know you can crop the image with something like:
Image::crop($save_path, $img_size, $img_size, [5, 5]);
But problem is doing this before resizing the image will likely not give you what you want since the image may be so large and cropping it after resizing won't work either as one dimension may already have been reduced to < 150px.
So what I'm trying to work out is how can I crop the image before resizing to the maximum size square possible and from the center out?
Edit:
Ok, I have worked out a way to handle this, but was wondering if there was anyway to accomplish the below easily or will I need to code it myself?
Work out the smallest dimension (width or height)
Then take that dimension and that will be the largest square you can have
Work out how to position that in the center for the crop
Now you can do the resize
If after the resize either side is smaller than 150, create new white background image and then center the new image on that
Save image
Done!
Another try :p
<?php
use yii\imagine\Image;
use Imagine\Image\Box;
use Imagine\Image\Point;
// ...
$thumbnail = Image::thumbnail($save_path, $img_size, $img_size);
$size = $thumbnail->getSize();
if ($size->getWidth() < $img_size or $size->getHeight() < $img_size) {
$white = Image::getImagine()->create(new Box($img_size, $img_size));
$thumbnail = $white->paste($thumbnail, new Point($img_size / 2 - $size->getWidth() / 2, $img_size / 2 - $size->getHeight() / 2));
}
$thumbnail->save($save_path);
Can't you just use the fourth parameter of Image::thumbnail()?
Image::thumbnail($save_path, $img_size, $img_size, Image\ImageInterface::THUMBNAIL_INSET)->save($save_path);
From http://www.yiiframework.com/doc-2.0/yii-imagine-baseimage.html#thumbnail()-detail:
If thumbnail mode is ImageInterface::THUMBNAIL_INSET, the original
image is scaled down so it is fully contained within the thumbnail
dimensions. The rest is filled with background that could be
configured via yii\imagine\Image::$thumbnailBackgroundColor and
yii\imagine\Image::$thumbnailBackgroundAlpha.

Make image background transparent by detecting Object edges using Imagick?

I am trying to make background of image transparent.Using following code
$strInputFile = 'test.jpg';
$target = 'test_transparent.png';
$im = new Imagick($strInputFile);
$im->paintTransparentImage($im->getImageBackgroundColor(), 0, 7000);
$im->setImageFormat('png');
$im->writeImage($target);
$im->destroy();
This code is working great for few images.But for most of the images output doesn't come out well.Wanted result come from script.
Unwanted result come from script.
Is it possible to detect edges of model and remove color before model?

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.

WideImage - Transparent areas of converted PNG should be white

Whenever a user uploads a photo using my script, WideImage converts it to JPEG. However, I just noticed that if I upload a PNG picture, with a transparent background, it makes it black instead.
Is there any way to make this white instead?
This is how i save the image:
$img->resizeDown('500', null)->saveToFile('annonce_billeder/'.$bnavn.'.jpeg', 70);
Not really directly. You wnt to read about how transparency is stored in pictures: it is an ordinary color value (any color) that has been marked especially as transparent.
So most likely the color specified in the example pictures you try actually is coded as black and the transparency gets lost whilst converting.
You might have a try to find out if you can detect if there is a color marked as transparent in the incoming picture and then manually change that color to non-transparcy and white before converting the picture.
Might be similar, but I was able to create an empty truecolor image and fill it with its own transparent color before doing any drawing:
$img = WideImage_TrueColorImage::create(100, 100);
$img->fill(0,0,$img->getTransparentColor());
// then text, watermark, etc
$img->save('...');
I assume you'll do something more like:
$img = WideImage::load(<source>);
if( <$img is png> ) {
$img->fill(0,0, $img->getTransparentColor());
}
$img->resizeDown(500, null)->saveToFile('target.jpg', 70);
This is how to do it:
// Load the original image
$original = WideImage::load("image.png");
$original->resizeDown(1000); // Do whatever resize or crop you need to do
// Create an empty canvas with the original image sizes
$img = WideImage::createTrueColorImage($resized->getWidth(),$resized->getHeight());
$bg = $img->allocateColor(255,255,255);
$img->fill(0,0,$bg);
// Finally merge and do whatever you need...
$img->merge($original)->saveToFile("image.jpg");
With some changes (corrections) on Ricardo Gamba's solution code, it does the job...
// Load the original image
$original = WideImage::load("image.png");
$resized = $original->resizeDown('500', null); // Do whatever resize or crop you need to do
$original->destroy(); // free some memory (original image not needed any more)
// Create an empty canvas with the resized image sizes
$img = WideImage::createTrueColorImage($resized->getWidth(), $resized->getHeight());
$bg = $img->allocateColor(255,255,255);
$img->fill(0,0,$bg);
// Finally merge and do whatever you need...
$img->merge($resized)->saveToFile("image.jpg", 70);

Categories