I'm trying to get an image and crop it then resize it to a thumbnail using PHPThumb. I want to crop the left side, right side, top and bottom in similar percentages. For example, crop 30% from left and 30% from right side; crop 40% from top bottomwards and 40% from bottom upwards How can I go about it. All I see in the manual is passing the SX value which I suppose only crops it mathematically from the bottom left(where x=0). I need to be able to crop from both sides towards the centre of the image. I hope you get what I mean.
I am using PHPThumb and not something custom since it has good JPEG compression when resizing, therefore the images have the clarity of the originals.
IMPORTANT EDIT: I have been notified that such a feature is not available in PHPThumb, anybody know of any such thumbnaik generator with the above cropping functions?
You could use Imagemagick -shave ( http://www.imagemagick.org/script/command-line-options.php#shave )but would need to calculate the pixels from the percentages first.
Untested code:
$size = getimagesize($input);
$horizontal = round( ($size[0]x0.3), 0);
$vertical = round( $size[1]x0.4), 0);
$cmd = "$input -shave {$horizontal}x{$vertical}";
exec("convert $cmd output.jpg");
Related
I was trying to perform a crop on a image using imagemagick. It did not give the results I expected.
I decided to set the crop value to 0 to try and find the error.
With a crop value of 0 the image was still being cropped.
Here is the code:
$img = new Imagick();
$img->readImage("{german-grammar.pdf}[17]");
$img->trimImage(10);
$width = $img->getImageWidth();
$height= $img->getImageHeight();
$img->setImagePage($width,$height, 0, 0); //Solution
$img->cropImage($width, $height,0,0); //Original Problem lime
$img->setImagePage(0,0,0,0);
$img->writeImage($ImagesPath.$ImageName);
The input is a PDF file.
I would appreciate if anyone could tell me what I am doing wrong.
Surely a crop value of 0 should not crop at all.
Thanks!
Cymro
I think you need to repage your image immediately after the trimImage() and before the cropImage(). It is generally a good idea to repage an image after any changes to its geometry (such as trimming and resizing) if you want the image to forget that it was once part of a larger image and go forth in the world happy and content with its own new shape and size.
I have pieced together a PHP class to perform various image related functions using GD functions of PHP.
It works great for all image types. Rotate, flip, resize, crop and to a lesser extent, watermark.
All but the latter work perfectly. For example after a few changes, rotated PNG images retained their transparency whereas before they were losing that and the background turning black. Common problem, it appears. But all working now.
Where I'm still getting stuck is watermarking a PNG image with another PNG image. It appears to work fine with JPG and other images. This is the code (simplified):
public function writeWatermarkSimple()
{
$watermarkFile = 'watermark.png';
$watermarkImage = imagecreatefrompng($watermarkFile);
imagealphablending($watermarkImage, false);
imagesavealpha($watermarkImage, true);
$imageFile = 'image.png';
$baseImage = imagecreatefrompng($imageFile);
imagealphablending($baseImage, false);
imagesavealpha($baseImage, true);
$marginH = imagesx($baseImage) - imagesx($watermarkImage);
$marginV = imagesy($baseImage) - imagesy($watermarkImage);
$cut = imagecreatetruecolor(imagesx($watermarkImage), imagesy($watermarkImage));
imagecopy($cut, $baseImage, 0, 0, $marginH, $marginV, imagesx($watermarkImage), imagesy($watermarkImage));
imagecopy($cut, $watermarkImage, 0, 0, 0, 0, imagesx($watermarkImage), imagesy($watermarkImage));
imagecopymerge($baseImage, $cut, $marginH, $marginV, 0, 0, imagesx($watermarkImage), imagesy($watermarkImage), 80);
if (!imagepng($baseImage, 'watermarked_image.png'))
{
return false;
}
return true;
}
This has been pieced together with various guides and advice people have given based on a similar issue. Again, working perfectly with JPG images and PNG watermarks, but not PNG & PNG.
Some example images:
http://i.imgur.com/hHRWinj.png - This is the watermark I'm using.
http://i.imgur.com/6sy8Ncs.png - This is the image I'm applying the watermark to.
http://i.imgur.com/ghovYLm.png - This is the end result.
The bit I find interesting is that any part of the watermark that is overlaid on a non-transparent portion of the image is working fine. Just the rest of it has the black background.
This leads me to believe I'm close, and I hope that the expertise of you fine people may lead me to the solution.
Thanks ever so for reading.
So, I'm not giving up on finding the correct answer to do this using GD. However, I was overjoyed to find that what needed up to 30 lines of code with GD can be achieved using much less with ImageMagick:
$image = new Imagick();
$image->readimage($this->_image);
$watermark = new Imagick();
$watermark->readimage($this->_watermark->_getImage());
$watermark->evaluateImage(Imagick::EVALUATE_DIVIDE, 2, Imagick::CHANNEL_ALPHA);
$image->compositeImage($watermark, imagick::COMPOSITE_OVER, $marginH, $marginV);
So this is before (with GD):
http://i.imgur.com/AlS0TcO.png
And after (with ImageMagick and the code above):
http://i.imgur.com/zBxlC3R.png
If anyone has an answer that is purely GD then I'd be immensely grateful.
Ran into some similar issues recently and while this may not exactly solve your problem, these were some useful discoveries that I made.
In my case, I have an original .jpg image and a watermark .png image. The watermark image has a fully transparent background. I wanted to specify the opacity in my script and have it change the watermark opacity before placing it on top of the origina image. Most posts out there regarding PHP watermarking assume that the original watermark .png file already has the solid watermark portion set to the correct opacity rather than changing it via the script.
gd didn't like a 24 bit .png and caused some goofy issues. Switching to 8 bit resolved that with gd. On the other hand, imagick works very well with a 24 bit .png and the final result seems to be better.
For me, using gd worked just fine if I was opening the original watermark .png and using imagecopymerge() to set the watermark transparency. If however I tried to scale the original watermark .png (which has transparent background) first, then I would get similar results as you with black or white background portion of where watermark image is. See How do I resize pngs with transparency in PHP? for a partial solution by filling the new wm image with transparent rectangle first. For me this still produced an opaque white background on the final result no matter what I tried.
I switched to imagick and was using setImageOpacity() to change the transparency of my watermark .png before applying it on top of my original image and I was still getting the same effect with a black background. Finally read in the PHP doc for setImageOpacity() that if the original .png has any transparent pixels and you try to lower the opacity, those pixels become opaque (black) with the new transparency applied. Instead, need to use the evaluateImage() function. This will instead evaluate each pixel's alpha channel only and divide by the specifid number.
I assume the black / white background issue with gd is likely due to similar ways that it treats alpha channels when scaling / combining as compared to imagick and if you want to do it all in gd you just need to find some similar way to evaluate and manipulate the alpha channel per-pixel because the "easy" ways seem to take an already transparent background and make it opaque.
So, the solution:
Assuming you want to apply your watermark at an opacity of 45% and you're using imagick, then instead of this:
$watermark->setImageOpacity(.45);
do this
$watermark->evaluateImage(Imagick::EVALUATE_DIVIDE, (1/.45), Imagick::CHANNEL_ALPHA);
You need to divide 1 by your opacity to get the demoninator by which the function will divide the alpha channel value for each pixel. In this case, 1/.45 = 2.2222, so then the function will divide the alpha channel of each pixel by 2.2222. This means a solid pixel (alpha of 1) would result in 1/2.2222 or .45 alpha or transparency when finished. Any pixels that were already transparent (alpha 0) would stay transparent because 0 divided by anything is always what? Zero!
After you change the watermark transparency then you can use compositeImage() to merge the watermark onto the original image.
I have the following image ontop of an image that is exactly 424x318
And it is wrapped in a div that is 444x338.
And I have a "cropping tool" (the circle center piece) that is 185x185, BUT can resize to be a minimum of 50x50 and a max of about 300x300 (depending on placement).
The cropping tool has a top "border/margin" of 28 px and a left "border/margin" of 20pixels (these are the measurements that take up the tabs, and purple lines and white stuff. However it can be resized, which would increase the border/margin by the resize percentage (so if the entire thing goes to 1.5, the scale would be *1.5).
The cropping tool is also 185x185 WxH total.
The standard position is the center (which is 66x120).
Okay now that we got all those out of the way, I am having a problem trying to find the center & one point that I pass onto imagemagick to process. I currently have the following
// Get variables
$left = $val->pos['0']; // this is posted from jquery, using position();
$top = $val->pos['1']; // this is posted from jquery, using position();
$scale = $val->scale; // this is posted from jquery, using width/185
$img = $val->image; // background image
$h = $scale*185;
// CENTER OF THE CIRCLE
$c1 = ($h*.5)+$left-20;
$c2 = ($h*.5)+$top-10;
// LEFT SIDE
$c3 = $left+(20*$scale)-10;
$c4 = ($h*.5)+$top-10;
$scalesize = $c1.",".$c2." ".$c3.",".$c4;
// Crop Size WxH+X+Y
$cr1 = $h-(40*$scale)-17;
$cr2 = $h-(40*$scale)-14;
$cr3 = $left-(20*$scale)+28;
$cr4 = $top+(20*$scale)-3;
$cropsize = $cr1."x".$cr2."+".$cr3."+".$cr4;
I then pass it onto imagemagick using
$return = exec('convert -size 424x318 xc:none -fill 'filename' -draw "circle '.$scalesize.'" -crop '.$cropsize.' +repage '.newfilename);
I just cannot for the life of me figure out what I am doing wrong. I keep playing with the ##'s that I am subtracting at the end, and it ends up working for one size, but then when I resize the crop tool it messes it all up... Any help?
Try to do one step at a time:
Ensure that your tool crops in the right place (use this: Crop or mask an image into a circle);
Ensure that resize (only) works fine;
Merge those two parts.
If the margin resizes with the scale, then you must scale your constants accordingly.
Something like this:
// CENTER OF THE CIRCLE
$c1 = ($h*.5)+$left-20 * scalesize; // Apply scale to constant
$c2 = ($h*.5)+$top-10 * scalesize; // Apply scale to constant
I'm writing code this week to dynamically change the color of images. As long as the image is square or rectangle, the code below works perfectly. However, I have an image that has rounded corners (filled with a spot color and the background outside the corners is white.)
Can someone tell me if there's a simple way to color an image that has rounded corners using the imagecolorset function (or any other php method)?
I only want the non white areas of the image to be colored (In case you're wondering, I'm disallowing the color white to be applied to the image).
Note, perhaps a better way to do this would be to use a PNG image that has transparent background (rather than my gif image). If you think that's a better approach, please advise.
Here's the function that I'm working with...
function set_theme_color_header($hex)
{
$info = hexToRGB($hex); //calls a helper function which translates the hex to RGB
$img = imagecreatefromgif('header-template.gif'); //again, this could be a PNG image, but we always start with this image, then create a color copy
$color = imagecolorallocate($img, $info["red"], $info["green"], $info["blue"]);
imagecolorset($img, 0, $info["red"], $info["green"], $info["blue"]);
imagegif($img, 'header.gif'); //only problem is that the imagecolorset function creates a messy fill at the corners
}
GD does not handle gif's very well. I recommend creating a png image with your rounded corners, then use GD's imagefilter($img, IMG_FILTER_COLORIZE, $info["red"], $info["green"], $info["blue"], $alpha) function. Then save the image as a gif.
Alternatively, use php's imagick library to literally draw the image. imagick is about a billion times better than GD. Poorly documented, but...the basic stuff isnnt too hard. See the tut link below.
Search php.net for "imagick" to see all the functions.
imagick tutorial
i really do not not why you are doing this, but maybe have a look at phpTumb (and its demos here).
HEllo,
I am trying to rotate a circular image around the center and then cut off the sides. I see the imagerotate function, but it does not seem to rotate about centre.
Anyone have any suggestions?
Thank you.
Update: Since it is a circle, I want to cut off the edges and keep my circle in the same dimensions.
The documentation says that it does rotate around the center.
Unfortunately it also says that it will scale the image so that it still fits. That means that whatever you do this function will change the size of your internal circular image.
You could (relatively easily) calculate how much scaling down will happen and then prescale the image up appropriately beforehand.
If you have the PHP "ImageMagick" functions available you can use those instead - they apparently don't scale the image.
I faced successfully that problem with the following code
$width_before = imagesx($img1);
$height_before = imagesy($img1);
$img1 = imagerotate($img1, $angle, $mycolor);
//but imagerotate scales, so we clip to the original size
$img2 = #imagecreatetruecolor($width_before, $height_before);
$new_width = imagesx($img1); // whese dimensions are
$new_height = imagesy($img1);// the scaled ones (by imagerotate)
imagecopyresampled(
$img2, $img1,
0, 0,
($new_width-$width_before)/2,
($new_height-$height_before)/2,
$width_before,
$height_before,
$width_before,
$height_before
);
$img1 = $img2;
// now img1 is center rotated and maintains original size
Hope it helps.
Bye
According to the PHP manual imagerotate() page:
The center of rotation is the center
of the image, and the rotated image is
scaled down so that the whole rotated
image fits in the destination image -
the edges are not clipped.
Perhaps the visible center of the image is not the actual center?