Watermarking an image with php - php

My website (coded in html and php in entirety) includes a feature which allows certain users to upload pictures. The picture is resized and watermarked using this code:
function watermarkpic($filename) {
ini_set('max_input_time', 300);
require 'config.php';
$watermark = imagecreatefrompng('watermarknew.png');
$watermarkwidth = imagesx($watermark);
$watermarkheight = imagesy($watermark);
if(preg_match('/[.](jpg)$/', $filename)) {
$originalimage = imagecreatefromjpeg($path_to_image_directory . $filename);
} else if (preg_match('/[.](gif)$/', $filename)) {
$originalimage = imagecreatefromgif($path_to_image_directory . $filename);
} else if (preg_match('/[.](png)$/', $filename)) {
$originalimage = imagecreatefrompng($path_to_image_directory . $filename);
}
$originalwidth = imagesx($originalimage);
$originalheight = imagesy($originalimage);
$maxsize = 800;
$imgratio = $originalwidth / $originalheight;
if($imgratio > 1) {
$finalwidth = $maxsize;
$finalheight = $maxsize / $imgratio;
}
else {
$finalheight = $maxsize;
$finalwidth = $maxsize * $imgratio;
}
$finalimage = imagecreatetruecolor($finalwidth,$finalheight);
imagecopyresampled($finalimage, $originalimage, 0,0,0,0,$finalwidth,$finalheight,$originalwidth,$originalheight);
imagecopymerge($finalimage, $watermark, 0, 0, 0, 0, $watermarkwidth, $watermarkheight, 100);
//now move the file where it needs to go
if(!file_exists($path_to_medimage_directory)) {
if(!mkdir($path_to_medimage_directory)) {
die("There was a problem. Please try again!");
}
}
imagejpeg($finalimage, $path_to_medimage_directory . $filename);
}
The issue is that the watermark has a transparent background, but it shows up as having a black background on the image. I have seen stuff about alpha blending, etc. but I do not really know what this is. I want to understand what I am doing, as well as fix the problem so that the watermark is transparent as it should be. The real picture should fill the space.
Thanks in advance.

Scott, there are a lot of things that can be going on here.
You need to make sure you saved your PNG using alpha transparency not indexed. Indexed transparency basically says "This color(maybe black) will be displayed as transparent throughout the image." When read by a browser or image editor, it may be transparent, but especially if you're merging it with a JPG, the transparency won't be honored. If you want to understand more, try http://www.idux.com/2011/02/27/what-are-index-and-alpha-transparency/
Make sure you are getting the correct dimensions for both images. See Transparent PNG over JPG in PHP to make sure you're not running into the same issue.
If you are still running into issues, you may want to check here: http://php.net/manual/en/image.examples.merged-watermark.php as it shows how to change the opacity of an image. It may be close to what you are trying to accomplish or might jog another thought.

http://php.net/manual/en/function.imagecopymerge.php:
<?php
$src = imagecreatefromstring(file_get_contents('watermark.png'));
$dest = imagecreatefromstring(file_get_contents('Unmarked/indian_elephant_chasing_bird.jpg'));
// Set the brush
imagesetbrush($dest, $src);
// Draw a couple of brushes, each overlaying each
imageline($dest,
imagesx($src)/2,
imagesy($src)/2,
imagesx($src)/2 ,
imagesy($src)/2,
IMG_COLOR_BRUSHED);
header('Content-Type: image/png');
imagepng($dest);
?>

So I figured it out; instead of using imagecopymerge() I used imagecopy() and it worked fine.
I saw somewhere that there may be a bug with imagecopymerge()that causes this in PHP5.

Related

PHP: how to use getimgasize() after the image is resized using getimageresized after upload?

using the example given at http://www.php.net/manual/en/function.imagecopyresized.php ... how to get image sizes afterward using getimagesize() function?
CODE:
<?php
if(isset($_FILES['images'])){
//TEST1:
$img = resize_this_image_now($_FILES['images']['tmp_name']);
//TEST2:
$img = resize_this_image_now($_FILES['images']['name']);/// This Drastically failed.
$new_image = getimagesize($img);
var_dump($new_image[0]);// I guessed this should have printed out the WIDTH_OF_THE_IMAGE... but, it prints some NON_READABLE stuffs (why?)
}
// The PHP.NET CODE in a Function
function resize_this_image_now($filename){
// File and new size
// $filename = 'test.jpg';
$percent = 0.5;
// Content type
header('Content-Type: image/jpeg');
// Get new sizes
list($width, $height) = getimagesize($filename);
$newwidth = $width * $percent;
$newheight = $height * $percent;
// Load
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($filename);
// Resize
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// Output
return imagejpeg($thumb);
}
?>
All I want is to get the Size of the Image.... also, is it possible to do something like:
$_FILES['images']['tmp_name'] = $the_newly_resized_image_returned_from_the_PHP_dot_NET_code'; .... So that the ['images']['tmp_name'] will now have as source this new image??
Any suggestion is highly appreciated...
I decided to spend sometime examining you question. What I found out is that, I don't think you'd need to return the resized image through imagejpeg() the way you did. You might also need to add a imagedestroy(), after you call imagejpeg() in you function, to destroy the temporary memory used.
You need to first fully Upload the Image before resizing it. If you'd like, you could send the image in a temporary storage while you do whatever you want to it so that Php does not have to deal with it in a 'tmp_name' format...Then You can destroy the image later on.
Once the image is fully uploaded, things become easier. The codes might look something like:
if(isset($_FILES['images'])){
//may be some random numbers to accompany it.
$rand = floor((mt_rand()+rand()+mt_rand())/3);
//Send it to the temporary folder you have had to create.
if(move_uploaded_file(
$_FILES['images']['tmp_name'],'temporary_storage/image_'.$rand.'.jpg')){
//Then run the `resize` function from here.
$image_resized = resize_this_image_now('temporary_storage/image_'.$rand.'.jpg');
//Now You can get the size if you wish.
list($width,$height) = getimagesize('temporary_storage/image_'.$rand.'.jpg');
// Out put
echo "W:".$width."<br>H:".$height;
//After you use it as desired, you can now destroy it using unlink or so.
unlink('temporary_storage/image_'.$rand.'.jpg');
}else{
echo "Upload Error goes here";
}
}
Note this answer is produced after several trials and errors... Please use this strategy wisely.
Hope it helps.

PHP Uploading a Large image and resizing with proportion like Photoshop

A quick brief. We currently have to make small, medium and large images based on product images we have on our site. Not being a wiz on PHP I thought I would still try to automate this nightmare.
The image we upload and dimension of the thumb is below
800 width x 1400 width LARGE
300 width x 525 width THUMB
The problem with my PHP script is that it just resizes with scaling to proportion. I want to it to be able to scale down like in Photoshop, you just click shift and the image scales. I am trying to use imagecopyresized but with little luck.
<?php
// PHP UPLOAD SCRIPT
// VALIDATION OF FORM
if($_FILES['user_image']['type'] == "image/jpeg" && $_FILES['user_image']['size'] < 3000000)
{
// VARS
$target_folder = 'images/';
$upload_image = $target_folder.basename($_FILES['user_image']['name']);
// UPLOAD FUNCTION
if(move_uploaded_file($_FILES['user_image']['tmp_name'], $upload_image))
{
// VARS FOR FILE NAMES
$thumbnail = $target_folder."medium_x.jpg";
$actual = $target_folder."large_x.jpg";
// THUMBNAIL SIZE
list($width, $height) = getimagesize($upload_image);
$newwidth = "300";
$newheight = "525";
// VARS FOR CALL BACK
$thumb = imagecreatetruecolor($newwidth, $newheight);
$source = imagecreatefromjpeg($upload_image);
// RESIZE WITH PROPORTION LIKE PHOTOSHOP HOLDING SHIFT
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
// MAKE NEW FILES
imagejpeg($thumb, $thumbnail, 100);
// FILE RENAMES
rename($upload_image, $actual);
{
// SUCCESS MESSAGES
?>
<p>
Image Successfully uploaded!<br />
Actual image: <?=$actual;?><br />
Thumbnail image: <?=$thumbnail;?><br />
<h1>Large</h1>
<img src="<?=$actual;?>"/><br /><br />
<h1>Medium</h1>
<img src="<?=$thumbnail;?>"/><br /><br />
</p>
<?
}
// FAILED MESSAGES
}
else
{
echo 'Upload failed.';
}
}
else
{
// NOT A JPEG
echo 'Not a JPEG';
}
// END OF SCRIPT
?>
How can I resize properly without having a stretched image? Is it possible?
The easiest way to achieve this without buckets of PHP code is with Image Magick. See examples and sample command line here: http://www.imagemagick.org/Usage/resize/#fill
(can call from PHP using exec() or similar)
Edit: Implementation as follows:
if($_FILES['user_image']['type'] == "image/jpeg" && $_FILES['user_image']['size'] < 3000000)
{
// VARS
$target_folder = 'images/';
$upload_image = $target_folder.basename($_FILES['user_image']['name']);
$thumbnail = $target_folder."medium_x.jpg";
$actual = $target_folder."large_x.jpg";
$newwidth = "300";
$newheight = "525";
if(move_uploaded_file($_FILES['user_image']['tmp_name'], $upload_image))
{
exec('convert '.$upload_image.' -resize '.$newwidth.'x'.$newheight.'^ '.$thumbnail);
rename($upload_image, $actual);
}
}
...
etc
You could optimise the way you handle the upload but I didn't want too totally change the structure of your code as I don't know what surrounds it. But basically, you push the image to ImageMagick's convert, and it will work it's magic.
If you want to crop as well as scale, the exec command would be:
exec('convert '.$upload_image.' -resize '.$newwidth.'x'.$newheight.'^ -gravity center -extent '.$newwidth.'x'.$newheight.' '.$thumbnail);
Look at this code snippet. Does what you need. Basically used to maintain ratio when creating the thumb.
http://snipplr.com/view/753/

Photo color loss after watermarking

Having a few teething problems watermarking a photo. It all works fine apart from the watermarked photo's colors become duller than they should be - very noticeable in-fact.
I'm using imagecopyresized to do my watermarking, as this specifically allows me to use PNG-24 watermarks, the others do not. I know the colors are usually OK, as I have just used readfile($url) as a test, and the photos are perfect.
Here is my script:
<?php
// get parent and watermark images & sizes
$image = imagecreatefromjpeg($url);
$imageSize = getimagesize($url);
$watermark = imagecreatefrompng('watermark.png');
$watermark_o_width = imagesx($watermark);
$watermark_o_height = imagesy($watermark);
// calculate new watermark width and position
if ($imageSize[0] > $imageSize[1] || $imageSize[0] == $imageSize[1]) {
$leftPercent = 23;
} else {
$leftPercent = 7;
}
$leftPixels = ($imageSize[0]/100)*$leftPercent;
$newWatermarkWidth = $imageSize[0]-$leftPixels;
$newWatermarkHeight = $watermark_o_height * ($newWatermarkWidth / $watermark_o_width);
// place watermark on parent image, centered and scaled
imagecopyresized(
$image,
$watermark,
$imageSize[0]/2 - $newWatermarkWidth/2,
$imageSize[1]/2 - $newWatermarkHeight/2,
0,
0,
$newWatermarkWidth,
$newWatermarkHeight,
imagesx($watermark),
imagesy($watermark)
);
// print
imagejpeg($image);
// destroy
imagedestroy($image);
imagedestroy($watermark);
?>
How can I stop this from happening? I'm reading about imagecreatetruecolor, does that solve the issue? I'm Googling "imagecreatetruecolor color loss photos" and variations but nobody really talks about this issue. If I do need this function, where would I add that to this script?
This has totally thrown a spanner in the works for me and would love for somebody to tell me where to stick it (not literally).
Here is an example of the color loss. The preview image should be exactly the same colors as the thumbnail. The thumbnails are created using readfile() whereas the previews are created using imagecreatefromjpeg and imagecopresized.
This example code works fine, by using the same characteristics as your images:
Original JPG: dark background; beautiful girl; red dress.
Watermark PNG: transparent background; text; gray color.
<?php
// Path the the requested file (clean up the value if needed)
$path = $url;
// Load image
$image = imagecreatefromjpeg($path);
$w = imagesx($image);
$h = imagesy($image);
// Load watermark
$watermark = imagecreatefrompng('watermark.png');
$ww = imagesx($watermark);
$wh = imagesy($watermark);
// Merge watermark upon the original image (center center)
imagecopy($image, $watermark, (($w/2)-($ww/2)), (($h/2)-($wh/2)), 0, 0, $ww, $wh);
// Output the image to the browser
header('Content-type: image/jpeg');
imagejpeg($image);
// destroy both images
imagedestroy($image);
imagedestroy($watermark);
// kill script
exit();
?>
Left: Output Image | Right: Original Image
Note:
The output image was compressed several times until: Original -> PHP Output -> GIMP -> Here.
After much testing, I came to the conclusion that PHP's GD Image does not support color profiles on the images that are being watermarked. I am now using Imagick and the colors are perfect.

Black result image problem on BMP image resize using PHP

I have a PHP script to re size image file as below;
$file = "test.bmp";
$ext = pathinfo($file, PATHINFO_EXTENSION);
$info = pathinfo($file);
$file_name = basename($file,'.'.$info['extension']);
$thumbname = "thumb/".$file_name.".".$ext;
$maxh = 200;
$maxw = 200;
$quality = 100;
list($width,$height)=getimagesize($file);
$src = imagecreatefromwbmp($file);
$tmp = imagecreatetruecolor($maxw,$maxh);
imagecopyresampled($tmp,$src,0,0,0,0,200,200,$width,$height);
imagejpeg($tmp,$thumbname,$quality);
imagedestroy($tmp);
The script is suppose to resize a Windows bitmap image to 200x200 thumbnail. But instead, I am getting a black 200x200 image. I am using PHP with Apache in Windows PC. How can I fix this?
.bmp and wbmp are VERY, VERY different file types.
Note the content-type headers:
Content-Type: image/x-xbitmap
Content-Type: image/vnd.wap.wbmp
Calling imagecreatefromwbmp($file) where $file is a .bmp will fail every time.
See this thread for info on how to load a .bmp file. It's not pretty.
As pointed out in PHP imagecopyresampled() docs:
Note:
There is a problem due to palette image limitations (255+1 colors). Resampling or filtering an image commonly needs more colors than 255, a kind of approximation is used to calculate the new resampled pixel and its color. With a palette image we try to allocate a new color, if that failed, we choose the closest (in theory) computed color. This is not always the closest visual color. That may produce a weird result, like blank (or visually blank) images. To skip this problem, please use a truecolor image as a destination image, such as one created by imagecreatetruecolor().
To see if it's the case you can use imageistruecolor() and copy the contents to a new truecolor image before "copyresampling" it:
if( !imageistruecolor($src) ){
$newim = imagecreatetruecolor( $width, $height );
imagecopy( $newim, $src, 0, 0, 0, 0, $width, $height );
imagedestroy($src);
$src = $newim;
}
There is a new opensource project on Github that allows reading and saving of BMP files (and other file formats) in PHP.
The project is called PHP Image Magician.
<?php
//Create New 'Thumbnail' Image
$newImageWidth = 200;
$newImageHeight = 200;
$newImage = imagecreatetruecolor($newImageWidth, $newImageHeight);
$newImageFile = 'output.jpg';
$newImageQuality = 100;
//Load old Image(bmp, jpg, gif, png, etc)
$oldImageFile = "test.jpg";
//Specific function
$oldImage = imagecreatefromjpeg($oldImageFile);
//Non-Specific function
//$oldImageContent = file_get_contents($oldImageFile);
//$oldImage = imagecreatefromstring($oldImageContent);
//Get old Image's details
$oldImageWidth = imagesx($oldImage);
$oldImageHeight = imagesy($oldImage);
//Copy to new Image
imagecopyresampled($newImage, $oldImage, 0, 0, 0, 0, $newImageWidth, $newImageHeight, $oldImageWidth, $oldImageHeight);
//Output to file
imagejpeg($newImage, $newImageFile, $newImageQuality);

PHP image resize script?

Okay I'm really new to PHP I found the following script below. But I dont know how to use it I was wondering where do I put the link to the image for example images/photo.jpg inorder to get me started in learning this script thanks.
Here is the code.
<?php
function resizeImage($originalImage,$toWidth,$toHeight){
// Get the original geometry and calculate scales
list($width, $height) = getimagesize($originalImage);
$xscale=$width/$toWidth;
$yscale=$height/$toHeight;
// Recalculate new size with default ratio
if ($yscale>$xscale){
$new_width = round($width * (1/$yscale));
$new_height = round($height * (1/$yscale));
}
else {
$new_width = round($width * (1/$xscale));
$new_height = round($height * (1/$xscale));
}
// Resize the original image
$imageResized = imagecreatetruecolor($new_width, $new_height);
$imageTmp = imagecreatefromjpeg ($originalImage);
imagecopyresampled($imageResized, $imageTmp, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
return $imageResized;
}
?>
There are a couple of potential gotchas here, so I'll give you a few of the potential issues you can run into:
You need to give the full path to the image so that it can be read. I use the following script for this:
function getRoot(){
$cwd = getcwd();
$splitCwd = explode("/", $cwd);
$root = "";
for($count=0; $count<count($splitCwd)-1;$count++){
$root .= '/' . $splitCwd[$count];
}
$root = $root . '/';
return $root;
}
Then you can pass in (getRoot() . $image, ...)
Create a switch that will check the file type (see my answer here). This will allow you to resize more than just jpegs, and output more than just jpegs, which is good when transparency may be involved.
There possible could be a final parameter or two, which is output filename. That way, you can make thumbnails while leaving the original image intact. In that case, you would do the imagejpeg (or imagepng, etc), and pass it the new name parameter if it is set.
You'd pass the link to the original JPEG as the first parameter in the function, which would be set as $originalImage.
So when calling the function, you'd use:
resizeImage("images/photo.jpg",800,600);
The two numbers would be your width/height values.
Instead of the return line you must add
header('Content-type: image/jpeg');
imagejpeg($imageResized);
Or check http://www.php.net/manual/en/function.imagejpeg.php and the Example #2 Saving a JPEG image

Categories