Image resizing performance comparison - php

I'm saving two photos from an upload. One is a larger photo and the other is a thumb.
I was wondering if i used less resources to create the thumb copy of a photo from the reduced larger photo say 450*400 or create the thumb from the original that can be say 3mb and say 2500px * whatever or is it 6 one way or a half dozen another?
imagecopyresampled($photo, $source, 0, 0, 0, 0, $photo_width, $photo_height, $width, $height);
imagecopyresampled($thumb_photo, $source, 0, 0, 0, 0, $thumb_width, $thumb_height, $width, $height); // old way
imagecopyresampled($thumb_photo, $photo, 0, 0, 0, 0, $thumb_width, $thumb_height, $photo_width, $photo_height); // new way

It will take much more memory to load a 2500x2500 image into memory than a 450x400. Like, +30x more.
On the other hand, if you're already loading it then you can reuse it with no additional memory usage (besides what's required to make the actual third image).

Yes, it makes sense to reuse the resized image to create the thumb, but only if you remove the original from memory:
imagecopyresampled($photo, $source, 0, 0, 0, 0, $photo_width, $photo_height, $width, $height);
imagedestroy($source);
imagecopyresampled($thumb_photo, $photo, 0, 0, 0, 0, $thumb_width, $thumb_height, $photo_width, $photo_height);

Related

How to make a color transparent in gd lib after merging images?

I am using gd lib to merge several images, but I'm having problems with the transparency. First I merge several images which each have a transparent background (works fine). Then I want to put another picture on top which consists of three parts: one part that I want to keep, a transparent part where the images below should show and one part in a color (e.g. green #00ff00) which is supposed to become transparent as well after merging. The images are pixel images, so I only want #0f0 to become transparent, none other color.
Here is an image of the result of the code.
The first picture shows the merged images ("circle" & "cloud").
The second picture shows the "hat" which is put on top of the merged images.
The third picture shows the result I want to achieve.
The fourth picture is what I actually get.
Whatever I do, I can't seem to find the solution. I'd be grateful for your help!
header("Content-type: image/png");
$img = imagecreatetruecolor(200, 200);
//make an image with transparent background
$transparency = imagecolorallocatealpha($img, 0, 0, 0, 127);
imagefill($img, 0, 0, $transparency);
imagesavealpha($img, true);
$circle = imagecreatefrompng("testcircle.png"); //black circle
$cloud = imagecreatefrompng("testcloud.png"); //brown cloud
$hat = imagecreatefrompng("testhat.png"); //blue hat with green area
imagecopy($img, $circle, 0, 0, 0, 0, 200, 200);
imagealphablending($img,true);
imagecopy($img, $cloud, 0, 0, 0, 0, 200, 200);
imagealphablending($img,true);
$green = imagecolorallocate($hat, 0, 255, 0);
imagecolortransparent($hat, $green);
imagecopy($img, $hat, 0, 0, 0, 0, 200, 200);
imagealphablending($img,true);
/* //With this the green area just keeps being green as in the second picture
$green = imagecolorallocate($img, 0, 255, 0);
imagecolortransparent($img, $green);
imagecopy($img, $hat, 0, 0, 0, 0, 200, 200);
imagealphablending($img,true);
*/
imagepng($img);
imagedestroy($img);
After searching for a long time, I've found the solution for my problem. I hope it will help if someone has the same question as me in future.
$green = imagecolorallocate($img, 0, 255, 0);
imagecopy($img, $hat, 0, 0, 0, 0, 200, 200);
imagecolortransparent($img, $green);
imagefill($img,0,0,imagecolorallocatealpha($img, 0, 0, 0, 127)); //this line does the trick
First of all I define green as a color. Then I copy the "hat" onto the picture and make the color transparent. Then comes the trick about filling the picture and that makes the green area transparent again.
(I found the solution in a german forum).
I noticed that this code only makes the first green area transparent though. If there are two seperated areas (or even more), (at least) one will stay green. So while this is a solution that works for me, there might be one out there that is even better.

Create a tiled image with offset

In the process of creating a tiled image I'd like to set an offset (so that the tile doesn't start at 0, 0) but when I provide what I'd expect to give me the correct image, it's not rendered correctly.
I'm setting the tile using imagesettile($image, $tile); but when I go to draw it (using imagefilledrectangle($image, 10, 10, 300, 300, IMG_COLOR_TILED);), I get an image as though it was tiled from 0, 0 (with the top & left 10 pixels black) instead of it being tiled from 10, 10.
Any ideas as to how I can get it tiled from 10, 10 or do I have to create another tiled image and copy it across?
In the end I had to create a new image which was tiled and copy it in. The final code is along the lines of:
$transparent = imagecolorallocatealpha($background_image, 255, 255, 255, 127);
$tiled_image = imagecreatetruecolor($width, $height);
imagefill($tiled_image, 0, 0, $transparent);
imagesettile($tiled_image, $tile);
imagefilledrectangle($tiled_image, 0, 0, $width, $height, IMG_COLOR_TILED);
imagecopyresampled($image, $tiled_image, $sx, $sy, 0, 0, $ex, $ey, $width, $height);

PHP GD : Can i just fill transparent part?

There is an image which has transparent area. (png image)
Now, while doing a imagecopy, can we just fill that transparent area?
Imagemagick can do this easily. Is that possible in php gd?
A layered approach via imagecopymerge() is one route. The concept is to merge your source image onto a new image, with a pre-set background image, which will show through the source image's transparency once merged.
//create main image - transparent, with opaque red square in middle
$img = imagecreate(60, 60);
$white = imagecolorallocate($img, 255, 255, 255);
imagecolortransparent($img, $white); //make background transparent
$red = imagecolorallocate($img, 255, 0, 0);
imagefilledrectangle($img, imagesx($img) / 4, imagesy($img) / 4, imagesx($img) - (imagesx($img) / 4), imagesy($img) - (imagesy($img) / 4), $red);
//create new image, with pre-filled background, then merge first image across
$img2 = imagecreate(60, 60);
$blue = imagecolorallocate($img2, 0, 0, 255);
imagecopymerge($img2, $img, 0, 0, 0, 0, imagesx($img), imagesy($img), 100);
//output
imagepng($img2);
So the first image creates a transparent image (the white) with a red square in the middle. The second image is simply a blue fill.Merge the two, and the blue shows through the transparent part of the first image, so our red square now sits on the blue fill. Effectively, we've filled the transparent part.
Here's the three states in sequence.
There is nothing to 'fill' where there is transparency. Transparency in a png (or gif) is not the absence of a color, but a single color specifically marked to be shown as transparent. Therefore you want to remove that marker.
Take a look at the php gds function 'imagecolortransparent':
Nope, you can't.
Instead that, you can try to create a copy from a colored rectangle. This code worked for me:
$input = imagecreatefrompng($file_input);
list($width, $height) = getimagesize($file_input);
$output = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($output, 255, 255, 255);
imagefilledrectangle($output, 0, 0, $width, $height, $white);
imagecopy($output, $input, 0, 0, 0, 0, $width, $height);
imagepng($output, $file_output);

Merge images with PHP

I have written a code for merge two images.
My code is:
$rnd = rand("99000", "99999");
$dst_path = "/home/maxioutl/public_html/images/urunler/";
$dst_file_name = "tresim-{$rnd}.jpg";
$dst_file = $dst_path.$dst_file_name;
$dst = imagecreatetruecolor(250, 375);
imagefill($dst, 0, 0, imagecolorallocate($dst, 255, 255, 255));
$src = imagecreatefromjpeg("http://www.goldstore.com.tr/upload/product/raw/3.72925.0332.JPG");
imagecopymerge($dst, $src, 40, 60, 0, 0, 250, 375, 100);
imagejpeg($dst, $dst_file, 90);
Result:
Black background. Where is it?
It's the imagecopymerge($dst, $src, 40, 60, 0, 0, 250, 375, 100); statement that's doing it.
You're passing it the dimensions 250x375, which isn't the watch's actual dimensions. Therefore the merge bounding box continues on and it uses black. You can see this easily if you comment it out because you'll get your white square from the fill like you were expecting.
you need to get the exact dimensions of your watch graphic (i.e. through getimagesize) and pass those to imagecopymerge so it cuts it exactly when it merges.
$arrSize = getimagesize($originalFile);
imagecopymerge($dst, $src, 40, 60, 0, 0, $arrSize[0], $arrSize[1], 100);
The code you wrote superimposes the images. It does not remove the white pixels from the image with the watch.
They are basically overlapped.
You should cycle through both image dimensions and replace each *white pixel with a black pixel or a transparent pixel.
*white pixel may not necessarily mean rgb(255,255,255) you can choose to treat all pixels with rgb(>235,>235,>235) as being "white".
Function imagecreatetruecolor creates completely black image
Taken from here :
imagecreatetruecolor() returns an image identifier representing a
black image of the specified size.

increasing image size with GD and PHP

i seem to be too dumb for this :-)
i have an image say
x=200
y=200
i want the image to stay the same but include a footer watermark lets say a.jpg which has a height of 20
so i want
a final image of 220 and y 200
i tried it this way but it wont work
$newimage=imagecreatetruecolor($width,$height+25);
imagecopy($newimage, $this->parentInstance->getOldImage(), 0, 0, 0, 0, $watermarksize[0], $watermarksize[1]);
imagecopy($newimage, $watermark, $dest_x, $dest_y, 0, 0, $watermarksize[0], $watermarksize[1]);
imagecopy($this->parentInstance->getOldImage(), $newimage, 0, 0, 0, 0, $dest_x, $dest_y);
You need to lookup imagecopymerge() - http://php.net/manual/en/function.imagecopymerge.php
Look at image copy resized if you want to resize an image resource using the GD library.

Categories