Imagecopyresampled Auto-Crop Image - php

I'm using imagecopyresampled to create thumbnails based on a certain width and height. The problem I'm having is that their height is being squished. What I want is for all thumbnail images to be 140x84 and if their aspect ratio does not match that the top and bottom extra portions of the image are cropped to center.
Here is what I have so far, any ideas would be greatly appreciated.
// Create Thumbnail
$imgsize = getimagesize($targetFile);
switch(strtolower(substr($targetFile, -3))){
case "jpg":
$image = imagecreatefromjpeg($targetFile);
break;
case "png":
$image = imagecreatefrompng($targetFile);
break;
case "gif":
$image = imagecreatefromgif($targetFile);
break;
default:
exit;
break;
}
$width = 140; //New width of image
$height = $imgsize[1]/$imgsize[0]*$width; //This maintains proportions
$x_mid = $width/2; //horizontal middle
$y_mid = $height/2; //vertical middle
$src_w = $imgsize[0];
$src_h = $imgsize[1];
$picture = imagecreatetruecolor($width, $height);
imagealphablending($picture, false);
imagesavealpha($picture, true);
$bool = imagecopyresampled($picture, $image, 0, 0, 0, ($y_mid-(84/2)), $width, $height, $src_w, $src_h);
if($bool){
switch(strtolower(substr($targetFile, -3))){
case "jpg":
header("Content-Type: image/jpeg");
$bool2 = imagejpeg($picture,$file_dir."/thumbs/".$imageName,85);
break;
case "png":
header("Content-Type: image/png");
imagepng($picture,$file_dir."/thumbs/".$imageName);
break;
case "gif":
header("Content-Type: image/gif");
imagegif($picture,$file_dir."/thumbs/".$imageName);
break;
}
}
imagedestroy($picture);
imagedestroy($image);

You need to first work out if you're going to re-size your image based on it's height or width. You'd usually work this out depending if your original image is portrait or landscape, and the orientation of your desired image size. You then need to work out the other edge programmatically from your choice.
Once you have, you can simple resample your original image at (0,0) and the over-hanging image data will be truncated.

Related

Resize an image on upload then use the move_uploaded_file()

Is there any way to resize the $_FILES["xfile1"]["tmp_name"] before I send it off to the move_uploaded_file() function? I checked every where but nobody seems to use this function after resizing the image.
ADDED*
// Create image from file
switch(strtolower($_FILES['xfile1']['type']))
{
case 'image/jpeg':
$image = imagecreatefromjpeg($_FILES['xfile1']['tmp_name']);
break;
case 'image/png':
$image = imagecreatefrompng($_FILES['xfile1']['tmp_name']);
break;
case 'image/gif':
$image = imagecreatefromgif($_FILES['xfile1']['tmp_name']);
break;
default:
exit('Unsupported type: '.$_FILES['xfile1']['type']);
}
// Delete original file
#unlink($_FILES['image']['tmp_name']);
// Target dimensions
$max_width = 540;
$max_height = 540;
// Get current dimensions
$old_width = imagesx($image);
$old_height = imagesy($image);
// Calculate the scaling we need to do to fit the image inside our frame
$scale = min($max_width/$old_width, $max_height/$old_height);
// Get the new dimensions
$new_width = ceil($scale*$old_width);
$new_height = ceil($scale*$old_height);
// Create new empty image
$new = imagecreatetruecolor($new_width, $new_height);
// Resample old into new
imagecopyresampled($new, $image,
0, 0, 0, 0,
$new_width, $new_height, $old_width, $old_height);
ob_start();
imagejpeg($new,'saved.jpeg' , 90);
$data = ob_get_clean();
So i have this so far. I have this $data variable which i want to replace with $_FILES["xfile1"]["tmp_name"] in the move_uploaded_file() function. Is that possible?
Thanks in Advance.

Crop resize images on the fly using PHP

I'm building a wallpaper website and therefore i need to be able to resize the original image before downloading. I tried this code to resize the image:
//resize and crop image by center
function resize_crop_image($max_width, $max_height, $source_file, $dst_dir, $quality = 80){
$imgsize = getimagesize($source_file);
$width = $imgsize[0];
$height = $imgsize[1];
$mime = $imgsize['mime'];
switch($mime){
case 'image/gif':
$image_create = "imagecreatefromgif";
$image = "imagegif";
break;
case 'image/png':
$image_create = "imagecreatefrompng";
$image = "imagepng";
$quality = 7;
break;
case 'image/jpeg':
$image_create = "imagecreatefromjpeg";
$image = "imagejpeg";
$quality = 80;
break;
default:
return false;
break;
}
$dst_img = imagecreatetruecolor($max_width, $max_height);
$src_img = $image_create($source_file);
$width_new = $height * $max_width / $max_height;
$height_new = $width * $max_height / $max_width;
//if the new width is greater than the actual width of the image, then the height is too large and the rest cut off, or vice versa
if($width_new > $width){
//cut point by height
$h_point = (($height - $height_new) / 2);
//copy image
imagecopyresampled($dst_img, $src_img, 0, 0, 0, $h_point, $max_width, $max_height, $width, $height_new);
}else{
//cut point by width
$w_point = (($width - $width_new) / 2);
imagecopyresampled($dst_img, $src_img, 0, 0, $w_point, 0, $max_width, $max_height, $width_new, $height);
}
$image($dst_img, $dst_dir, $quality);
if($dst_img)imagedestroy($dst_img);
if($src_img)imagedestroy($src_img);
}
And this will do the resize:
resize_crop_image($width, $height, $image_URL, $save_URL)
This code works fine for me but i want to ONLY send the output to user's browser, since saving thousands of extra images isn't possible. There are libraries i can use, but i don't want to use a third party snippet. Is there a way to alter this code in the way i desire?
Thanks.
For your $image function , do not specify a destination directory (null) and an image stream will be created.
header("Content-type:{$mime}");
That should send the image to the user
You just need to set the proper headers and echo the output. Every PHP request "downloads a file" to the browser, more or less. You just need to specify how the browser handles it. So try something like:
header("Content-Type: $mime");
header("Content-Disposition: attachment; filename=$dst_img");
echo $dst_img;
That should do it for you.

Why is a GIF image losing its transparency with imagegif() even when I set the alpha blending settings?

I am trying to allow the uploading of transparent profile pictures (PNGs and GIFs) on my site because it is sometimes quite annoying for the user to upload a transparent profile picture and the transparent areas become black. The problem is that the transparency is still being lost even after using the imagealpha*() functions.
I do realize that there are other questions about this, but the answers on them aren't working for me.
Here is my code:
// [...]
switch(strtolower($_FILES['picture']['type'])) {
case 'image/jpeg':
$image = imagecreatefromjpeg($_FILES['picture']['tmp_name']);
break;
case 'image/png':
$image = imagecreatefrompng($_FILES['picture']['tmp_name']);
break;
case 'image/gif':
$image = imagecreatefromgif($_FILES['picture']['tmp_name']);
break;
default:
msg('Sorry, but the type of file that you selected is not allowed. We only allow JPEG, PNG, and GIF.','error');
header("Location: /settings/profile");
exit;
}
// Target dimensions
$max_width = 143;
$max_height = 143;
// Get current dimensions
$old_width = imagesx($image);
$old_height = imagesy($image);
// Calculate the scaling we need to do to fit the image inside our frame
$scale = min($max_width/$old_width, $max_height/$old_height);
// Get the new dimensions
$new_width = ceil($scale*$old_width);
$new_height = ceil($scale*$old_height);
// Create new empty image
$new = imagecreatetruecolor($new_width, $new_height);
// Resize old image into new
imagecopyresampled($new, $image, 0, 0, 0, 0, $new_width, $new_height, $old_width, $old_height);
$file_name = 'avatar_'.randString(20).mt_rand(111,999).'.'.str_replace('image/','',$_FILES['picture']['type']);
switch(strtolower($_FILES['picture']['type'])) {
case 'image/jpeg':
$img = imagejpeg($new, 'user/uploads/'.$file_name, 95);
break;
case 'image/png':
imagealphablending($new, false);
imagesavealpha($new, true);
$img = imagepng($new, 'user/uploads/'.$file_name, 95);
break;
case 'image/gif':
imagealphablending($new, false);
imagesavealpha($new, true);
$img = imagegif($new, 'user/uploads/'.$file_name);
break;
}
imagedestroy($image);
imagedestroy($new);
if($img) {
$dbUpdate = mysql_query("UPDATE users SET user_pic = '$file_name' WHERE uid = $userid");
}
if($img && $dbUpdate) {
msg("Your profile picture has been changed successfully.","success");
header("Location: /settings/profile");
exit;
}
// [...]
I tried uploading this GIF just for testing:
But it lost its transparency after it was uploaded:
I am trying to keep the transparency information with it, but it doesn't seem to be working. Am I not doing something right?
Thanks in advance.
Create a transparent color and fill the $new image with that color before the copy. If you don't do that, the background color of the new image will default to black.
$new = imagecreatetruecolor($new_width, $new_height);
$transparent = imagecolorallocatealpha($new, 0, 0, 0, 127);
imagefill($new, 0, 0, $transparent);
imagealphablending($new, true);
You can also check this question

image resize with php?

ive done my research on the net and here as well and i keep on coming up with no answer that can help me:
i have the below code which displays an image from a folder based on a user's location however the image is too big and i need to resize it.
all the scripts that i have tried or read relate to files being uploaded. can anyone push me in the right direction?
thank you.
<?php
print"
<table <td width=\"138\" height=\"73\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">
<tr>
<td align=\"center\" valign=\"middle\"><a href=\"map.php\"><img src=\"" .
esc('img/' . $db_name . '_maps/sm' . $user['location'] . '.png') .
"\" alt=\"Map of systems around {$user['location']}\" /></a></td>
</tr>
</table>
"
?>
My problem arises from the fact that i need to pull the images as:
<img src=\"" .esc('img/' . $db_name . '_maps/sm' . $user['location'] . '.png') . "\" alt=\"Map of systems around {$user['location']}\" /></a>
Wrote a tutorial about this a while ago. Perhaps it can help. It starts with uploading, but most of it is about resizing. Just swap out the usage of the $_FILES array by geting the image type and file name a different way. Here's the code you should need:
// Create image from file
switch(strtolower($_FILES['image']['type']))
{
case 'image/jpeg':
$image = imagecreatefromjpeg($_FILES['image']['tmp_name']);
break;
case 'image/png':
$image = imagecreatefrompng($_FILES['image']['tmp_name']);
break;
case 'image/gif':
$image = imagecreatefromgif($_FILES['image']['tmp_name']);
break;
default:
exit('Unsupported type: '.$_FILES['image']['type']);
}
// Target dimensions
$max_width = 240;
$max_height = 180;
// Get current dimensions
$old_width = imagesx($image);
$old_height = imagesy($image);
// Calculate the scaling we need to do to fit the image inside our frame
$scale = min($max_width/$old_width, $max_height/$old_height);
// Get the new dimensions
$new_width = ceil($scale*$old_width);
$new_height = ceil($scale*$old_height);
// Create new empty image
$new = imagecreatetruecolor($new_width, $new_height);
// Resize old image into new
imagecopyresampled($new, $image,
0, 0, 0, 0,
$new_width, $new_height, $old_width, $old_height);
// Catch the imagedata
ob_start();
imagejpeg($new, NULL, 90);
$data = ob_get_clean();
// Destroy resources
imagedestroy($image);
imagedestroy($new);
// Set new content-type and status code
header("Content-type: image/jpeg", true, 200);
// Output data
echo $data;
If you want to store the image as a file rather than dumping it to the browser, remove the head and echo part at the end and then swap out the NULL parameter in the imagejpeg call with an actual filename. Hope that helps :)
Here's the code in use: http://samples.geekality.net/image-resize/
You make take a look at gd : http://www.php.net/manual/en/function.imagecopyresized.php
You can try this:
$extension = substr( $img_url, -3 );
$extension = strtolower($extension);
switch ($extension) {
case "jpg":
case "jpeg":
$src_im = createimagefromjpeg($img_url);
break;
case "gif":
$src_im = createimagefromgif($img_url);
break;
case "png":
$src_im = createimagefrompng($img_url);
break;
}
// Get size
$size = GetImageSize($img_url);
$src_w = $size[0];
$src_h = $size[1];
// $width has to be fixed to your wanted width
$dst_w = $width;
$dst_h = round(($dst_w / $src_w) * $src_h);
$dst_im = ImageCreateTrueColor($dst_w, $dst_h);
ImageCopyResampled($dst_im, $src_im, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h);
ImageJpeg($dst_im);
ImageDestroy($dst_im);
imageDestroy($src_im);
There a simple to use, open source library called PHP Image Magician that has some nice features and documentation.
It uses 100% GD.
Example of basis usage:
$magicianObj = new imageLib('racecar.jpg');
$magicianObj -> resizeImage(100, 200, 'crop');
$magicianObj -> saveImage('racecar_small.png');
If you need more features convert might be a help.

PHP watermarking

i am using this code to create watermark.
$image = '1.jpg';
$overlay = 'stamp.png';
$opacity = "20";
if (!file_exists($image)) {
die("Image does not exist.");
}
// Set offset from bottom-right corner
$w_offset = 0;
$h_offset = 100;
$extension = strtolower(substr($image, strrpos($image, ".") + 1));
// Load image from file
switch ($extension)
{
case 'jpg':
$background = imagecreatefromjpeg($image);
break;
case 'jpeg':
$background = imagecreatefromjpeg($image);
break;
case 'png':
$background = imagecreatefrompng($image);
break;
case 'gif':
$background = imagecreatefromgif($image);
break;
default:
die("Image is of unsupported type.");
}
// Find base image size
$swidth = imagesx($background);
$sheight = imagesy($background);
// Turn on alpha blending
imagealphablending($background, true);
// Create overlay image
$overlay = imagecreatefrompng($overlay);
// Get the size of overlay
$owidth = imagesx($overlay);
$oheight = imagesy($overlay);
// Overlay watermark
imagecopymerge($background, $overlay, $swidth - $owidth - $w_offset, $sheight - $oheight - $h_offset, 0, 0, $owidth, $oheight, $opacity);
imagejpeg($background,$image);
// Destroy the images
imagedestroy($background);
imagedestroy($overlay);
the png image contains a text with all other region as transparent.
but when i execute this code , it applys the png over jpg, but the transparecy is not maintained of the png. it shows in a box.
how can i acheive that . ie if a png contains transaparent part , it should show the below image in that part....?
replacing imagecopymerge with imagecopy solved the issue. here is the new code
function watermark($image){
$overlay = '../../../photos/photosets/stamp.png';
$opacity = "20";
if (!file_exists($image)) {
die("Image does not exist.");
}
// Set offset from bottom-right corner
$w_offset = 0;
$h_offset = 100;
$extension = strtolower(substr($image, strrpos($image, ".") + 1));
// Load image from file
switch ($extension)
{
case 'jpg':
$background = imagecreatefromjpeg($image);
break;
case 'jpeg':
$background = imagecreatefromjpeg($image);
break;
case 'png':
$background = imagecreatefrompng($image);
break;
case 'gif':
$background = imagecreatefromgif($image);
break;
default:
die("Image is of unsupported type.");
}
// Find base image size
$swidth = imagesx($background);
$sheight = imagesy($background);
// Turn on alpha blending
imagealphablending($background, true);
// Create overlay image
//$overlay = imagecreatefrompng($overlay);
// Get the size of overlay
$owidth = imagesx($overlay);
$oheight = imagesy($overlay);
$photo = imagecreatefromjpeg($image);
$watermark = imagecreatefrompng($overlay);
// This is the key. Without ImageAlphaBlending on, the PNG won't render correctly.
imagealphablending($photo, true);
// Copy the watermark onto the master, $offset px from the bottom right corner.
$offset = 10;
imagecopy($photo, $watermark, imagesx($photo) - imagesx($watermark) - $offset, imagesy($photo) - imagesy($watermark) - $offset, 0, 0, imagesx($watermark), imagesy($watermark));
// Output to the browser
header("Content-Type: image/jpeg");
imagejpeg($photo,$image);
// Overlay watermark
// Destroy the images
imagedestroy($background);
imagedestroy($overlay);
}
The jpg format doesn't support transparency, so conceptually you will have to:
grab the pixels from the larger image (the jpeg) and put them into a buffer
grab the non-transparent pixels from the smaller image (the watermark) and move them into that buffer, applying the alpha along the way
You probably want to let a library do this. I like ImageMagick, especially since it's built in to php... here's an example of how to use it for this purpose from PHP:
// Let's read the images.
$glasses = new Imagick();
if (FALSE === $glasses->readImage($dir . '/glasses.png'))
{
throw new Exception();
}
$face = new Imagick();
if (FALSE === $face->readImage($dir . '/face.jpg'))
{
throw new Exception();
}
// Let's put the glasses on (10 pixels from left, 20 pixels from top of face).
$face->compositeImage($glasses, Imagick::COMPOSITE_DEFAULT, 10, 20);
And here's the link to the PHP manual page for ImageMagick::compositeImage (from which the above example came).
Have you tried using imagecopyresampled()?
http://php.net/manual/en/function.imagecopyresampled.php

Categories