I am having this problem that my cropped image is not cropped in the center of the scaled image. I have now tried for some hours without success.
Any help on the calculation and position would be appreciated.
This is the part of the code that returns my values
// image dimensions
$obj->sw = $p_aImageInfo[0];
$obj->sh = $p_aImageInfo[1];
//thumbnail sizes
$obj->tsw = 100;
$obj->tsh = 200;
$obj->yOff = 0;
$obj->xOff = 0;
if($obj->sw < $obj->sh) {
$obj->scale = $obj->tsw / $obj->sw;
$obj->yOff = $obj->sh/2 - $obj->tsw/$obj->scale/2;
} else {
$obj->scale = $obj->tsh / $obj->sh;
$obj->xOff = $obj->sw/2 - $obj->tsh/$obj->scale/2;
}
This the code that makes a new image
// Create the resized image destination
$croppedImage = imagecreatetruecolor($l_oCropInfo->tsw, $l_oCropInfo->tsh);
imagealphablending($croppedImage, false);
imagesavealpha($croppedImage,true);
$transparent = imagecolorallocatealpha($croppedImage, 255, 255, 255, 127);
imagefilledrectangle($croppedImage, 0, 0, $l_oCropInfo->tsw, $l_oCropInfo->tsh, $transparent);
// Copy from image source, resize it, and paste to image destination
imagecopyresampled($croppedImage, $im, 0, 0, $l_oCropInfo->xOff,
$l_oCropInfo->yOff,
$l_oCropInfo->tsw,
$l_oCropInfo->tsh,
$l_oCropInfo->tsw / $l_oCropInfo->scale,
$l_oCropInfo->tsh / $l_oCropInfo->scale);
And the result of the image created and the one that needs to be created.
Ok small mistake now it works
Change
$obj->yOff = $obj->sh/2 - $obj->tsw/$obj->scale/2;
$obj->xOff = $obj->sw/2 - $obj->tsh/$obj->scale/2;
to
$obj->yOff = $obj->sh/2 - $obj->tsh/$obj->scale/2;
$obj->xOff = ($obj->sw/2 - $obj->tsw/$obj->scale/2);
Related
I want to cut out part of the photo without stretch it.
Something like the photo I posted, cut out the red part and get photo number 2
With a width of 150px and height of 100px and cuting from top left of photo
enter image description here
I tried to do it with this code but it didn't work.
This codes separates part of the image, but does not do so from the top left of the image.
function resizejpeg($dir, $newdir, $img, $max_w, $max_h, $th_w, $th_h)
{
// set destination directory
if (!$newdir) $newdir = $dir;
// get original images width and height
list($or_w, $or_h, $or_t) = getimagesize($dir.$img);
// make sure image is a jpeg
if ($or_t == 2) {
// obtain the image's ratio
$ratio = ($or_h / $or_w);
// original image
$or_image = imagecreatefromjpeg($dir.$img);
// resize image?
if ($or_w > $max_w || $or_h > $max_h) {
// resize by height, then width (height dominant)
if ($max_h < $max_w) {
$rs_h = $max_h;
$rs_w = $rs_h / $ratio;
}
// resize by width, then height (width dominant)
else {
$rs_w = $max_w;
$rs_h = $ratio * $rs_w;
}
// copy old image to new image
$rs_image = imagecreatetruecolor($rs_w, $rs_h);
imagecopyresampled($rs_image, $or_image, 0, 0, 0, 0, $rs_w, $rs_h, $or_w, $or_h);
}
// image requires no resizing
else {
$rs_w = $or_w;
$rs_h = $or_h;
$rs_image = $or_image;
}
// generate resized image
imagejpeg($rs_image, $newdir.$img, 100);
$th_image = imagecreatetruecolor($th_w, $th_h);
// cut out a rectangle from the resized image and store in thumbnail
$new_w = (($rs_w / 2) - ($th_w / 2));
$new_h = (($rs_h / 2) - ($th_h / 2));
imagecopyresized($th_image, $rs_image, 0, 0, $new_w, $new_h, $rs_w, $rs_h, $rs_w, $rs_h);
// generate thumbnail
imagejpeg($th_image, $newdir.'thumb_'.$img, 100);
return true;
}
// Image type was not jpeg!
else {
return false;
}
}
$dir = './';
$img = '1.jpg';
$size = getimagesize($img);
$width = $size[0];
$height = $size[1];
resizejpeg($dir, '', $img, $width, $height, 150, 100);
I didn't understand correctly what you mean, but based on your description you are trying to get the image no 2 which means you are trying to crop an image. If that your mean, maybe this code will help
function crop($image_path, $output_path, $x, $y, $width, $height) {
// load image
$image = imagecreatefromjpeg($image_path);
// crop the image
$cropped_image = imagecrop($image, [
'x' => $x,
'y' => $y,
'width' => $width,
'height' => $height
]
);
// save it
imagejpeg($cropped_image, $output_path);
}
you can use it like this
// input image path
$image = "img.jpg";
// output image path
$output = "crop_img.jpg";
// crop it from (0,0)
crop($image, $output, 0, 0, 150, 100);
in my project i just do image watermarking or image combine it's working fine and code for that.
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<?php
if(isset($_POST['submit']))
{
// Give the Complete Path of the folder where you want to save the image
$folder="uploads/";
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], "$folder".$_FILES["fileToUpload"]["name"]);
$file='uploads/'.$_FILES["fileToUpload"]["name"];
$uploadimage=$folder.$_FILES["fileToUpload"]["name"];
$newname= time();
$ext = pathinfo($_FILES["fileToUpload"]["name"], PATHINFO_EXTENSION);
// Set the thumbnail name
$thumbnail = $folder.$newname.".".$ext;
$imgname=$newname.".".$ext;
// Load the mian image
if ($ext=="png" || $ext=="PNG") {
$source = imagecreatefrompng($uploadimage);
}
else if ($ext=="gif" || $ext=="GIF") {
$source = imagecreatefromgif($uploadimage);
}
else if ($ext=="bmp" || $ext=="BMP") {
$source = imagecreatefrombmp($uploadimage);
}
else{
$source = imagecreatefromjpeg($uploadimage);
}
// load the image you want to you want to be watermarked
$watermark = imagecreatefrompng('uploads/logo1.png');
// get the width and height of the watermark image
$water_width = imagesx($source)/2;
$water_height = imagesy($watermark);
// get the width and height of the main image image
$main_width = imagesx($source);
$main_height = imagesy($source);
$im_middle_w = $main_width/2;
$im_middle_h = $main_height/2;
// Set the dimension of the area you want to place your watermark we use 0
// from x-axis and 0 from y-axis
$dime_x = $im_middle_w - $water_width/2;
$dime_y = $im_middle_h - $water_height/2;
// copy both the images
imagecopy($source, $watermark, $dime_x, $dime_y, 0, 0, $water_width, $water_height);
// Final processing Creating The Image
imagejpeg($source, $thumbnail, 100);
unlink($file);
}
?>
<img src='uploads/<?php echo $imgname;?>'>
</body>
</html>
but problem with setting $water_width and i want set as half of my source image. but when i have source image of less width or more width compare to $water_width it's set it like that. see image when source image width is more.
and when width is less.
so my problem is how to set $water_width as half of source image width?
by Alex your answer it's came up like this.
This will resize watermark to half-width of original image and put it in the centre:
// load the image you want to you want to be watermarked
$watermark = imagecreatefrompng('uploads/logo1.png');
// get the width and height of the watermark image
$water_width = imagesx($watermark);
$water_height = imagesy($watermark);
// get the width and height of the main image image
$main_width = imagesx($source);
$main_height = imagesy($source);
// resize watermark to half-width of the image
$new_height = round($water_height * $main_width / $water_width / 2);
$new_width = round($main_width / 2);
$new_watermark = imagecreatetruecolor($new_width, $new_height);
// keep transparent background
imagealphablending( $new_watermark, false );
imagesavealpha( $new_watermark, true );
imagecopyresampled($new_watermark, $watermark, 0, 0, 0, 0, $new_width, $new_height, $water_width, $water_height);
// Set the dimension of the area you want to place your watermark we use 0
// from x-axis and 0 from y-axis
$dime_x = round(($main_width - $new_width)/2);
$dime_y = round(($main_height - $new_height)/2);
// copy both the images
imagecopy($source, $new_watermark, $dime_x, $dime_y, 0, 0, $new_width, $new_height);
// Final processing Creating The Image
imagejpeg($source, $thumbnail, 100);
imagedestroy($source);
imagedestroy($watermark);
imagedestroy($new_watermark);
You can try imagettftext method, if you don't want any such high perfection in transparency. You can have try of this code. You have to save a font file in your directory, here I used arial.ttf.
$im = imagecreatefrompng("png.png"); //create image data
$font = 'arial.ttf'; //font file name
$randomString = "example.com"; //string need to be shown
$main_width = imagesx($im); //finding width and height
$main_height = imagesy($im);
$posx= $main_width/2; //finding center
$posy = $main_height/2;
$color = imagecolorallocate($im, 200, 200, 200); //Creating color
$size = ($main_width/25)+1; //determine size of font. +1 to avoid 0
$temp = $size*5;
$posx = $posx-$temp; //adjust to average center
imagettftext($im,$size,0, $posx, $posy, $color, $font , $randomString); //apply a text
You have to adjust posx and posy for your text position. Size also can be adjusted with some logics.
$color = imagecolorallocate($im, 0, 0, 0);= black
and $color = imagecolorallocate($im, 255, 255, 255); = white.
You have to adjust this for your required text color.
I am experiencing an issue where I am allowing the user to resize images in a container and then need to create a resulting image that is the size of the container but with the image scaled and adjusted as per the users choices.
So for example say the container is 400 x 200 and the user wants to be able to put in a logo that is 600 x 100 they may wish to shrink the logo so it fits and leave space at the top and bottom. I need to be able to save that as an image that is 400x200 with the appropriate gaps at the top and bottom.
What I have found though is that if the image content (the logo in this example) extends beyond BOTH the top and the right of the container everything is fine OR if it DOESNT extend beyond either it is fine but if it extends beyond one and not the other then I get black fill- or something like that- see examples below...
Below are some examples of the results and this is the code I am using...
$cropped = wp_imagecreatetruecolor( $frame_w, $frame_h);
$backgroundColor = imagecolorallocatealpha($cropped, 0, 0, 0, 127);
//imageantialias( $cropped, true );
//if $img_y or $img_x are negative we need to apply the value to $img_x and $img_y
//if $img_y or $img_x are positive we need to apply the value to $dest_x and $dest_y
$dest_x = strstr($img_x,'-') ? 0 : abs($img_x);//if neg is true = 0 else offset inside
$dest_y = strstr($img_y,'-') ? 0 : abs($img_y);
$img_x = strstr($img_x,'-') ? abs($img_x) : 0;//if neg is true offset outside else 0
$img_y = strstr($img_y,'-') ? abs($img_y) : 0;
$img_w = $img_w > $frame_w ? $frame_w : $img_w;
$img_h = $img_h > $frame_h ? $frame_h : $img_h;
imagecopy( $cropped, $resized, $dest_x, $dest_y, $img_x, $img_y, $img_w, $img_h);
//imagecopymerge( $cropped, $resized, $dest_x, $dest_y, $img_x, $img_y, $img_w, $img_h,100);
//imagecopyresampled( $cropped, $resized, $dest_x, $dest_y, $img_x, $img_y, $frame_w, $frame_h, $img_w, $img_h );
imagefill($cropped, 0, 0, $backgroundColor);//putting this after the copy makes any black borders transparent again unless $resized does not extend beyond both dimensions
Examples
Image does not extend beyond top or beyond right (fine)
Image extends beyond bottom but not right (not fine)
Image extends beyond both (fine)
Image extends beyond right but not bottom (not fine)
Image Extends beyond neither (fine)
I have been literally tearing my hair out trying to fix this and tried every possible combination of imagesavealpha, imagecopymerged, imagecolorallocatealpha, imagealphablending etc I can think of but nothing seems to fix this...
So is this a bug/limitation of GD? Or can someone out there come to my rescue!
I don't know if this will help you, but I had an issue with this earlier today. The box expands but the area was black. Here's my code (which fixes it):
<?php
function createImage($text)
{
// Adds an extra space to fill underline
$text = " $text";
// Adds one line at the end
$text .= "\n";
// Wrap the text to fit the image
$text = wordwrap($text, 40, "\n");
// Count new lines
$newlines = substr_count($text, "\n");
// Count how long to expand
if($newlines == 0)
{
$height = 30;
}
else
{
$height = 30*$newlines-$newlines*5;
}
putenv('GDFONTPATH=' . realpath('.'));
header('Content-Type: image/png');
// Adding underline
$e = explode('<', $text);
for($i=0;$i<count($e);$i++)
{
$e[$i] = implode('̲', str_split($e[$i]));
}
// Creating image
$text = implode(' ', $e);
$im = imagecreatetruecolor(315, $height);
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
$purple = imagecolorallocate($im, 97, 26, 139);
imagefilledrectangle($im, 0, 0, 399, $height, $white);
$font = 'arialbd.ttf';
imagettftext($im, 11, 0, 10, 20, $purple, $font, $text);
imagepng($im);
imagedestroy($im);
}
createImage("asbdasddsa");
?>
i think this will happen only for PNG check with other formats
I'm not sure if this is an actual answer since it is basically 'Use ImageMagick' but anyway for those for whom ImageMagick is an option the code below might help them achieve the same thing as I was trying to above... Basically ImageMagick seems far superior to GD, no borders around rotated images, no hassles with transparency, no onwanted black fill, clearer resizing if you are enlarging...
$img_x = -50; //left offset of the image within the frame
$img_y = 50; //top offset of the image within the frame
$img_w = 400; //width of the image to be put in the frame
$img_h = 200; // height of the image to be put in the frame
$angle = 45; //rotation to be applied to the image before it is put into the frame
$frame_w = 300; //width of the frame the image is going into
$frame_h = 300; //height of the frame the image is going into
$img_path = 'path/to/image/file.jpg';
$image = new Imagick( $img_path );
$size = $image->getImageGeometry();
$orig_w = $size['width']; $orig_h = $size['height'];
$image->scaleImage( $img_w, $img_h );
//rotate if necessary
if($angle)
{
$image->rotateImage( new ImagickPixel('none'), $angle );
$size = $image->getImageGeometry();
$img_w = $size['width']; $img_h = $size['height'];
}
//composite into frame
//in imagemagick we create an image that is the size of the frame and make it transparent
$frame = new Imagick();
$frame->newImage($frame_w, $frame_h, new ImagickPixel("none"));
//then we composite the image itself into this with the respective offset values
$frame->compositeImage( $image, Imagick::COMPOSITE_DEFAULT, $img_x, $img_y );
//save it
$destfilename = "{$dir}/{$name}-{$img_suffix}.{$ext}";
$frame->writeImage($destfilename);
$frame->clear();
$frame->destroy();
$image->clear();
$image->destroy();
The above code produces this...yay!
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);
I'm creating a simple php sprite image generator, I was able to calculate the possible width and height of the sprite image, but I'm stuck at creating the transparent canvas and put the images into it.
Now let's say the width of the sprite image is 200x500px (i'm creating vertical sprite). And the images to put in the sprite image is in an array like so:
array('logo.png','delete.png','open.png');
How you gonna put those images into the sprite?
$path = '/img/';
$imgs = array('logo.png','delete.png','save.png');//images needed to be put in the sprite
$canvasWidth= 0;
$canvasHeight = 0;
//calculate the posible canvas width and height
foreach($imgs as $val)
{
$info = getimagesize($path.basename($val));
$width=$info[0];
$height=$info[1];
$canvasHeight +=$height;
if($canvasWidth < $width){
$canvasWidth = $width;
}
}
// create our canvas
$img = imagecreatetruecolor($canvasWidth, $canvasHeight);
$background = imagecolorallocatealpha($img, 255, 255, 255, 127);
imagefill($img, 0, 0, $background);
imagealphablending($img, false);
imagesavealpha($img, true);
// start placing our icons from the top down.
$pos = 0;
foreach($imgs as $val){
$tmp = imagecreatefrompng($path.basename($val));
$w=imagesx($tmp);
$h=imagesy($tmp);
imagecopy($img, $tmp, 0, $pos, 0, 0, $w, $h);
$pos += $h;
imagedestroy($tmp);
}
// create our final output image.
imagepng($img, $path.'sprite.png');