Merge images with PHP - 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.

Related

PHP imagecopyresampled() produces image border on one side

I have a resampling script that centers resampled images on a square canvas.
For horizontally-oriented images that are centered vertically on a white background a line is added along the BOTTOM edge of the resampled image.
For vertically-oriented images that are centered horizontally the line appears on the RIGHT edge of the resampled image.
$thumb = imagecreatetruecolor($th_width, $th_height);
imagecopyresampled($thumb, $source, $th_x, $th_y, 0, 0, $th_width, $th_height, $src_width, $src_height);
$bgcolor = imagecolorallocate($thumb, 255, 255, 255);
imagefill($thumb, 0, 0, $bgcolor);
The line is there regardless of background fill, it just shows up most on white.
What causes this? No amount of adjusting parameter values will get rid of it (they just offset the resampled image on the background or distort it).
I am providing my own workaround for this issue.
It appears the image border artifact is a COMBINATION result of 'imagecopyresampled()' AND centering offsets. If I just resample the image as-is THEN center and fill the image, the border is avoided. Here is the workaround:
1) RESAMPLE your image as-is (same aspect ratio) then SAVE to retain changes:
$thumb = imagecreatetruecolor($res_width, $res_height);
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $res_width, $res_height, $src_width, $src_height);
// SAVE new image - set quality to lossless since reusing it:
imagejpeg($thumb, "resampled/output_temp.jpg", 100);
2) Retrieve the temporary image:
$file = "resampled/output_temp.jpg";
$image = file_get_contents($file);
$source = imagecreatefromstring($image);
// Get the RESAMPLED image dimensions
list($src_width, $src_height) = getimagesize($file);
3) NOW apply CENTERING and FILL:
$thumb = imagecreatetruecolor($th_width, $th_height);
// COPY the image
imagecopy($thumb, $source, $th_x, $th_y, 0, 0, $src_width, $src_height);
$bgcolor = imagecolorallocate($thumb, 255, 255, 255);
// Replace default black background - this must be placed AFTER imagecopy()
imagefill($thumb, 0, 0, $bgcolor);
// Save image (uses default quality setting 75)
imagejpeg($thumb, "resampled/" . $newfile);
// Optionally free up memory:
imagedestroy($thumb);
The result is a clean image.
For correcting incomplete imagefill() on the background when centering vertically-oriented images see this post:
imagecopyresampled() results in split color background imagefill()

imagecopyresampled() results in split color background imagefill()

I have a script that takes an image and when resampled centers the short dimension (width or height) on a square coloured background.
This works fine for images with a longer WIDTH but for some reason any image with a longer HEIGHT the result is a split background fill - the correct colour on the left but the default black on the right. If I play with the x-axis offset the background fill only extends to the right as far as the image placement.
The calculated values are as expected for the vertical images so I cannot figure out what is happening here. Note that 'imagecopy()' produces the exact same behaviour.
original image is 155 x 400px
adjusted source dimensions for square aspect ratio = 400 x 400px
resulting thumbnail to be 250 x 250px
Here is the code with static values for one example:
$thumb = imagecreatetruecolor(250, 250);
imagecopyresampled($thumb, $source, 77, 0, 0, 0, 250, 250, 400, 400);
$blue = imagecolorallocate($thumb, 0xDE, 0xE6, 0xF9);
imagefill($thumb, 0, 0, $blue);
Using the same image rotated 90 degrees (400 x 155 px) so it is longer horizontally DOES apply the full background fill:
imagecopyresampled($thumb, $source, 0, 77, 0, 0, 250, 250, 400, 400);
For the vertical image, my coordinate values (77, 0) place the image on the imagecreatetruecolor() canvas centered exactly where I want it but changing any of the other imagecopyresampled() values stretch or squeeze the resampled image or crop it.
Am I overlooking something simple? View the screenshots here:
http://i.stack.imgur.com/5CxHU.jpg (vertical issue) and
http://i.stack.imgur.com/wvhzP.jpg (OK horizontally)
This vertical issue must have something to do with PHP's resampling/imagefill algorithm (?) but here is a workaround that now works for centering all of my vertical images within my square canvas:
1) You need to first pad your image placeholder so the background fill will extend to the right edge in the resampled image by extending the thumbnail height with your x-axis offset (sounds odd but it works)...we will trim this off later:
$thadj_height = $th_height + $th_x;
$thumb = imagecreatetruecolor($th_width, $thadj_height);
2) Resample as usual with the background fill (note that the fill is applied AFTER the resampling statement, odd but just works that way)...remember that $thumb has more height than what $th_width, $th_height will occupy:
imagecopyresampled($thumb, $source, $th_x, $th_y, 0, 0, $th_width, $th_height, $src_width, $src_height);
imagefill($thumb, 0, 0, $bgcolor);
3) Temporarily save the image output so a new function can be applied to it next - set quality to lossless since we'll be reusing it:
imagejpeg($thumb, "resampled/output_temp.jpg", 100);
imagedestroy($thumb);
4) Retrieve the temporary file and grab the new dimensions (overwrite the previous variables):
$file = "resampled/output_temp.jpg";
$image = file_get_contents($file);
$source = imagecreatefromstring($image);
list($src_width, $src_height) = getimagesize($file);
5) Create a new image placeholder, square as originally intended in my case:
$thumb = imagecreatetruecolor($th_width, $th_height);
6) Now copy the temporary padded thumbnail into the square placeholder which will result in cropping off the padding:
imagecopy($thumb, $source, 0, 0, 0, 0, $src_width, $src_height);
header('Content-Type: image/jpeg');
echo imagejpeg($thumb);
imagedestroy($thumb);
Again, none of this is necessary for centering my horizontal images on a square canvas but this is a workaround that will work to eliminate the split fill background.

PHP GD image merge changing my image to black

I have a very frustrating situation. I am using PHP GD for the first time, and it's been a bit of a rollercoaster relationship. Basically, I am trying to merge 2 images, a square one (with a height/width of x) onto a rectangle (with a width of x and a height of y).
The square needs to be centered vertically. But this isn't the issue - I've managed to position it correctly.
Whats happening is, my rectangle is white. My square has a white background, so when the images are merged, it should just look like my asset on a white rectangluar background.
When I merge the image though, GD is for some reason changing my background white rectangle to black - so you can see the white square in the middle, with black "bars" on top and bottom. Can anyone help?
Code is:
//create copy of original image to correct size
imagecopyresized($dst_image, $src_image, 0,0,0,0,$x_width,$x_height,$orig_img_x_width,$orig_img_x_height);
imagejpeg($dst_image, "resized_copy.jpg", 100);
$img = imagecreatetruecolor(1333, 2000);
$white = imagecolorallocate($img, 255, 255, 255);
imagefill ( $img, 0, 0, $white );
imagefilledrectangle($img,0,0,1333,2000, $white);
imagejpeg($img, "rectangle.jpg", 100);
//merge images
$dest2 = imagecreatefromjpeg("rectangle.jpg");
$src2 = imagecreatefromjpeg('resized_copy.jpg');
imagecopymerge($dest2, $src2, 0, 0, 0, -333.5, $x_width, $x_height, 100);
imagejpeg($dest2, "final_image.jpg", 100);
I've tried using imagecopy instead of imagecopymerge, but I get the same result. I'm sure there is a simple explanation, but I cant seem to find it trawling through the php manual.
I've read your question a few times but I'm not convinced I understand exactly what you are trying to achieve so I've made a few assumptions in producing the below code.
For the sake of simplicity I've created a 'square.jpg' test image file like so:
(Note that I've used small image sizes here so I can show them inline.)
// read in the square test image.
$square = imagecreatefromjpeg('square.jpg');
$square_x = imagesx($square); // 100px
$square_y = imagesy($square); // 100px
// create the rectangular image to merge with.
$rectangle = imagecreatetruecolor(100, 200);
$rectangle_x = imagesx($rectangle); // 100px
$rectangle_y = imagesy($rectangle); // 200px
// note that this isn't white, but rather a lovely shade of blue to better
// show the image on the white SO background!
$white = imagecolorallocate($rectangle, 128, 128, 255);
imagefill($rectangle, 0, 0, $white);
// merge the images.
imagecopymerge(
$rectangle,
$square,
0,
($rectangle_y / 2) - ($square_y / 2), // to vertically centre the square.
0,
0,
$square_x,
$square_y,
75 // Just to show the merge clearly; change back to 100 for your usage.
);
imagejpeg($rectangle, 'final_image.jpg', 100);
imagedestroy($rectangle);
imagedestroy($square);
This gives me the following image in final_image.jpg:

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

Merging Images using GD with PHP

i'm working on creating one PNG image from two others.
Image A and B have the same dimensions, they are both 200x400px. The final image the same.
I'm using the GD library with PHP.
So my idea was to create a PNG-24 from my original PNG-8, then use color transparency and finally copy the second image into
this new PNG-24. The problem appears in the first step anyway, when going from PNG-24 to PNG-8 with color transparency:
This is to get the original PNG-8 and it's dimensions:
$png8 = imagecreatefrompng($imageUrl);
$size = getimagesize($imageUrl);
Now i create a new PNG and fill it's background with a green color (not present in the images):
$png24 = imagecreatetruecolor($size[0], $size[1]);
$transparentIndex = imagecolorallocate($png24, 0x66, 0xff, 0x66);
imagefill($png24, 0, 0, $transparentIndex);
This is for making the green color transparent:
imagecolortransparent($png24, $transparentIndex);
Then i copy the png8 into the PNG-24:
imagecopy($png24, $png8, 0, 0, 0, 0, $size[0], $size[1]);
So here's the problem: the original PNG-8 looks good, but it has a green border surrounding the shape within the original image. It's difficult to explain really. Seems like some part of the green background is left in the remaining PNG.
What can i do?
thanks in advance
best regards,
Fernando
I had some problems with png transparency before and was able to solve them with this pattern:
// allocate original image to copy stuff to
$img = imagecreatetruecolor(200, 100);
// create second image
$bg = imagecreatefrompng('bg.png');
// copy image onto it using imagecopyresampled
imagecopyresampled($img, $bg, 0, 0, 0, 0, 200, 100, 200, 100);
imagedestroy($bg);
// create third image
// do same routine
$fg = imagecreatefrompng('fg.png');
imagecopyresampled($img, $fg, 50, 50, 0, 0, 50, 50, 50, 50);
imagedestroy($fg);
// output image
imagepng($img);
imagedestroy($img);
I think the only difference between mine and yours is imagecopy() vs. imagecopyresampled(). I seem to remember having problems with that though it was quite a while ago. You can see an example of an image I use this pattern on here: http://www.ipnow.org/images/1/bggrad/bg4/yes/TRANSIST.TTF/8B0000/custombrowserimage.jpg (I allocate a blank image, copy the background image in, copy the overlay with transparency in)

Categories