Scaling a watermark to fit parent image - php

My photo sizes vary, they are either landscape, portrait or square, and I need to make a watermark the best fit for each photo - so I need to resize just the width of the watermark (without Imagick), as it's a long rectangle shape, so height doesn't matter.
I found the PHP function, imagecopyresized, but I'll be honest, I can't work out what parameters are needed for my situation, even after looking at PHP documentation! I'm also not sure if after using imagecopyresized, the rest of my function will work where it gets the watermark width and height.
Can somebody help me get over the finish line. This is how far I got, all it needs is the right parameters added to the imagecopyresized part:
<?php
header('content-type: image/jpeg');
$image = imagecreatefromjpeg('https://.....jpg');
$imageSize = getimagesize('https://.....jpg');
$newWatermarkWidth = $imageSize[0]-50; // width of image minus 50px
$watermark = imagecreatefrompng('watermark.png');
// resize watermark to newWatermarkWidth here with imagecopyresize
$watermark = imagecopyresized(?,?,?,?);
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$dest_x = ($imageSize[0]/2) - ($watermark_width/2) ;
$dest_y = ($imageSize[1]/2) - ($watermark_height/2);
imagecopy($image, $watermark, round($dest_x,0), round($dest_y,0), 0, 0, $watermark_width, $watermark_height);
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
?>
THIS IS WHAT I ENDED WITH & WORKS PERFECTLY
A script that adjusts the width of a watermark to fit across the whole parent image, centered and proportional.
<?php
header('content-type: image/jpeg');
$image = imagecreatefromjpeg('http://mydomain.com/myPhoto.jpg');
$imageSize = getimagesize('http://mydomain.com/myPhoto.jpg');
$watermark = imagecreatefrompng('http://mydomain.com/myWatermark.png');
$watermark_o_width = imagesx($watermark);
$watermark_o_height = imagesy($watermark);
$newWatermarkWidth = $imageSize[0]-20;
$newWatermarkHeight = $watermark_o_height * $newWatermarkWidth / $watermark_o_width;
imagecopyresized($image, $watermark, $imageSize[0]/2 - $newWatermarkWidth/2, $imageSize[1]/2 - $newWatermarkHeight/2, 0, 0, $newWatermarkWidth, $newWatermarkHeight, imagesx($watermark), imagesy($watermark));
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);

This resizes the watermark and copies directly to the image.
You don't need the existing imagecopy line anymore.
$success = imagecopyresized($image, // Destination image
$watermark, // Source image
$imageSize[0]/2 - $newWatermarkWidth/2, // Destination X
$imageSize[1]/2 - imagesy($watermark)/2, // Destination Y
0, // Source X
0, // Source Y
$newWatermarkWidth, // Destination W
imagesy($watermark), // Destination H
imagesx($watermark), // Source W
imagesy($watermark)); // Source H

Related

PHP imagecopy function changing stamp size according to the main image height and width

I'm trying to add a watermark (logo) to each image upload to the website.
So, I used imagecopy PHP function to add a watermark (a png image) to the main image (a jpg image) but the problem is the logo size is changing according to the main image size (height and width), That's mean if I upload a 4000x2000 image the logo with be somthing like 100x100 and if the main image size is 1000x500 the stamp will be bigger than the real size (546x537).
Image Samples:
https://crkemlak.com/appimg/199f8486d7d77007771f2f450dffca4d.jpeg
https://crkemlak.com/appimg/d6f9fd02999eced76eac9a6995df904f.jpeg
https://crkemlak.com/img/stamp.png
I used this code to add the watermark to the image:
$im = imagecreatefromjpeg('../appimg/'.$filenamerand);
$originalWidth= imagesx($im);
$originalHeight = imagesy($im);
$stamp = imagecreatefrompng('../img/stamp.png');
$marge_right = 10;
$marge_bottom = 10;
$sx = imagesx($stamp);
$sy = imagesy($stamp);
imagecopy($im, $stamp, ($originalWidth-$sx)/2, ($originalHeight-$sy)/2, 0, 0, imagesx($stamp), imagesy($stamp));
I need your help please to fix this problem, I need to make the watermark is in it's real size in any size of the main jpg image
Thanks
I used imagecopyresized so that the watermark could be scaled to look the same on any input image irregardless of its size. Possibly better ways to do it. Im not sure how good the quality is when scaling images with transparent backgrounds. Here it is on git
$watermark = imagecreatefrompng('watermark.png');
$image = imagecreatefromjpeg('main-image.jpg');
$wm_x = imagesx($watermark);
$wm_y = imagesy($watermark);
$img_x = imagesx($image);
$img_y = imagesy($image);
// calculate watermark size
$wm_scale = 19; // set size in relation to image
$wm_w = $img_x/$wm_scale;
$wm_aspect = $wm_y/$wm_x;
$wm_h = (int) ($wm_aspect * $wm_w);
// calculate margin
$margin_scale = 6; // set margin in relation to new watermark size
$margin_right = $wm_w/$margin_scale;
$margin_bottom = $wm_h/$margin_scale;
// calculate watermark destination
$dst_x = $img_x - $wm_w - $margin_right;
$dst_y = $img_y - $wm_h - $margin_bottom;
imagecopyresized ($image, $watermark, $dst_x, $dst_y, 0, 0, $wm_w, $wm_h, $wm_x, $wm_y);
// Output and free memory
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);

PHP - Watermark PNG Transparency/Alpha

I know this has been covered PLENTY of times but I keep trying different scripts and modifying the one I have, and I still can't get my PNG-24 watermark.png to be transparent over the top of my parent image.
This is what I have currently:
<?
header('content-type: image/jpeg');
$watermark = imagecreatefrompng('watermark.png');
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$image = imagecreatefromjpeg($imageURL);
$image = imagecreatetruecolor($watermark_width, $watermark_height);
$size = getimagesize($imageURL);
imagealphablending($image, false);
imagesavealpha($image, true);
$dest_x = $size[0] - $watermark_width - 5;
$dest_y = $size[1] - $watermark_height - 5;
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
?>
I've just read another SO question and one of the answers advised that it won't be transparent if you don't add these two lines:
imagealphablending($image, false);
imagesavealpha($image, true);
I added them and still not. I tried setting headers and output to PNG instead but still no luck. I loaded the watermark in my browser (raw) and it's definitely transparent but just not on the image. Surely this can't be that difficult? Any ideas what I'm doing wrong?
It's not an issue with the application code, it's with the watermark image (PNG) itself.
A lot of watermark examples/tutorials say to use a PNG-24 watermark, but according to a blog I've just read, they say that imagecopymerge does not deal with PNG-24 files very well, therefore, use PNG-8 and some special 'Save for Web' settings. I did this and it works fine now.
Here is the relevant section about PNG types from this blog:
The watermark image should be in one of the following recommended
formats:
PNG-8 (recommended)
Colors: 256 or less
Transparency: On/Off
GIF
Colors: 256 or less
Transparency: On/Off
JPEG
Colors: True color
Transparency: n/a
The imagecopymerge function does not properly handle the PNG-24
images; it is therefore not recommended.
If you are using Adobe Photoshop to create watermark images, it is
recommended that you use "Save for Web" command with the following
settings:
File Format: PNG-8, non-interlaced
Color Reduction: Selective, 256 colors
Dithering: Diffusion, 88%
Transparency: On, Matte: None
Transparency Dither: Diffusion Transparency Dither, 100%
And for other's benefits, this is the watermark code I have that works:
<?
$masterURL = 'mydomain.com/myImage.jpg';
header('content-type: image/jpeg');
$watermark = imagecreatefrompng('watermark.png');
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$image = imagecreatetruecolor($watermark_width, $watermark_height);
$image = imagecreatefromjpeg($masterURL);
$size = getimagesize($masterURL);
$dest_x = $size[0] - $watermark_width - 5;
$dest_y = $size[1] - $watermark_height - 5;
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
?>
After a bit more reading (this comment on the same article), I found out that you CAN use PNG-24 watermarks but with imagecopy instead of imagecopymerge. You can replace this line:
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);
with this one:
imagecopy($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);
Using imagecopymerge with PNG-8 watermarks is quite good for 'on-the-fly' watermarking, as the watermark file is tiny. If you do watermarking 'behind-the-scenes', it doesn't really matter about file size and you can get much better quality from the PNG-24 watermark, using imagecopy.
I hope this helps the confused watermarkers out there.

PHP Merge 2 Images (Insert Face To An Image)

I need your help
I have two images,
1. http://i.imgur.com/pyWGk.jpg (face image, type: jpeg)
2. http://i.imgur.com/LYk07.png (frame image, with hole in face, type: png)
I want insert face image into frame image
I tried this script
<?php
$image = imagecreatefromjpeg('face.jpg');
$frame = imagecreatefrompng('ironman.png');
$iw = imagesx($image);
$ih = imagesy($image);
$fw = imagesx($frame);
$fh = imagesy($frame);
imagealphablending($frame, true);
imagesavealpha($frame, true);
imagecopy($image, $frame, 0, 0, 0, 0, $fw, $fh);
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
imagedestroy($frame);
?>
The problem are:
Resolution of result image doesn't same with resolution of frame image, and
How to change position of face image, so the face image can right on hole in frame image
You can scale images to get the same resolutions. Here's the sample code for scaling:
function scale($scale){
//you can get image width and height from image info
$width = $image_width * $scale / 100;
$height = $image_height * $scale / 100;
$scaled_image = imagecreatetruecolor($width, $height);
imagecopyresampled($scaled_image, $old_image, 0, 0, 0, 0, $width, $height, $image_width, $image_height);
}
To change position of face image you can set parameters you want in imagecopy function. You'll need to set dst_x and dst_y.

Add text watermark to image watermark code

I am using an image watermark code that works great but I also need to add a text watermark to it.
Here is the code in full:
<?php
$main_img = "Porsche_911_996_Carrera_4S.jpg"; // main big photo / picture
$watermark_img = "watermark.gif"; // use GIF or PNG, JPEG has no tranparency support
$padding = 3; // distance to border in pixels for watermark image
$opacity = 100; // image opacity for transparent watermark
$watermark = imagecreatefromgif($watermark_img); // create watermark
$image = imagecreatefromjpeg($main_img); // create main graphic
if(!$image || !$watermark) die("Error: main image or watermark could not be loaded!");
$watermark_size = getimagesize($watermark_img);
$watermark_width = $watermark_size[0];
$watermark_height = $watermark_size[1];
$image_size = getimagesize($main_img);
$dest_x = $image_size[0] - $watermark_width - $padding;
$dest_y = $image_size[1] - $watermark_height - $padding;
// copy watermark on main image
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, $opacity);
// print image to screen
header("content-type: image/jpeg");
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
?>
You can use imagestring() there are other image text function so checkout the manual for GD
imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);

centering image resource in new, larger image (PHP/imagecopy)

I'm trying to build a function that takes a PHP image resource and places it in the center of a new image of predetermined size. I do not want to scale the image; rather I want to place it as-is in the center of an enlarged "canvas."
$img is a valid image resource - if I return it I receive the correct original (unprocessed) image. $canvas_w and $canvas_h are the width and height of the desired new canvas. It's creating the correct size canvas, but the contents of the file are unexpectedly solid black when I return the desired "corrected" image resource ($newimg).
// what file?
$file = 'smile.jpg';
// load the image
$img = imagecreatefromjpeg($file);
// resize canvas (not the source data)
$newimg = imageCorrect($img, false, 1024, 768);
// insert image
header("Content-Type: image/jpeg");
imagejpeg($newimg);
exit;
function imageCorrect($image, $background = false, $canvas_w, $canvas_h) {
if (!$background) {
$background = imagecolorallocate($image, 255, 255, 255);
}
$img_h = imagesy($image);
$img_w = imagesx($image);
// create new image (canvas) of proper aspect ratio
$img = imagecreatetruecolor($canvas_w, $canvas_h);
// fill the background
imagefill($img, 0, 0, $background);
// offset values (center the original image to new canvas)
$xoffset = ($canvas_w - $img_w) / 2;
$yoffset = ($canvas_h - $img_h) / 2;
// copy
imagecopy($img, $image, $xoffset, $yoffset, $canvas_w, $canvas_h, $img_w, $img_h);
// destroy old image cursor
//imagedestroy($image);
return $img; // returns a black original file area properly sized/filled
//return $image; // works to return the unprocessed file
}
Any hints or obvious errors here? Thanks for any suggestions.
In place of imagecopy(), this seemed to work:
imagecopymerge($img, $image, $xoffset, $yoffset, 0,0, $img_w, $img_h, 100);

Categories