Cropping to the center of an image

This post is more than 2 years old.

This week a user sent in what I thought was a rather simple request. He needed to find the center of an image. That's pretty trivial math, so I fired back with the following:

<cfset image = "/Users/ray/Pictures/star-wars-stormtroopers-breakfast-cereal.jpg"> <cfset myImg = imageNew(image)> <cfset centerX = myimg.width/2> <cfset centerY = myimg.height/2>

Basically, your center is the point defined at half your width and half your height. However, I misunderstood his initial request. He wanted to take an image and crop it to a smaller size. But he wanted the crop to "center" around, well, the center. Let me explain with an example that demonstrates how just finding the center isn't enough. We will begin with our source image - which is not mine and I cannot find the credit.

Pretty snazzy, right? Now let's look at code that finds the center, and then crops at that point:

<cfset image = "/Users/ray/Pictures/star-wars-stormtroopers-breakfast-cereal.jpg"> <cfset myImg = imageNew(image)>

<cfimage action="writeToBrowser" source="#myimg#"> <p/>

<cfset centerX = myimg.width/2> <cfset centerY = myimg.height/2>

<cfset imageCrop(myImg, centerX, centerY, 300, 200)>

<cfimage action="writeToBrowser" source="#myImg#">

You can see my math in there (ok, it's division, and it's simple, but it's still math!) and the imageCrop that works with the center. However, this creates a crop that is displayed. It's from the lower right hand size of the image.

In order to correct this, we need to make a slight tweak to our code. Our math formula becomes:

x=width of image/2 - desiredwidth/2
y=height of image/2 - desiredheight/2

Here is the corrected code:

<cfset image = "/Users/ray/Pictures/star-wars-stormtroopers-breakfast-cereal.jpg"> <cfset myImg = imageNew(image)>

<cfset imageCrop(myImg, (myimg.width/2) - (300/2), (myimg.height/2) - (200/2), 300, 200)> <cfimage action="writeToBrowser" source="#myImg#">

Which produces the following:

Better, right?

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Christopher David Kowalski posted on 2/4/2010 at 4:26 AM

I inspired a blog entry, how exciting!

Thanks again for helping me out with this request.

PS: Caught a typo with the word "simpe".

Comment 2 by Jonathan Gailing posted on 2/4/2010 at 4:47 AM

I was so distracted by the greatness of the photo I forgot to read... *scroll up*

Comment 3 by Raymond Camden posted on 2/4/2010 at 6:18 AM

Typo fixed - thanks!

Comment 4 by Brian Lang posted on 2/4/2010 at 9:29 AM

Pretty simple stuff. I remember doing this kind of thing years ago in Visual Basic 6. But I did learn about doing it in ColdFusion which is really exciting! Now I just need to convince the powers that be that we need to upgrade to CF8 or even better to CF9 so I can do this kind of stuff again.

Comment 5 by Patrick Heppler posted on 2/5/2010 at 3:29 PM

@ Ray or just use the AspectCrop() from imageUtils.cfc ;)

Comment 6 by Raymond Camden posted on 2/5/2010 at 5:54 PM

Heh, I had meant to check that. ;) You sure it does that though - I thought it was a bit different.

Comment 7 by Gareth posted on 3/12/2010 at 3:03 AM

Hi, I have tried to implement this code by get the following error:

"Crop The rectangular crop area must not be outside the image."

What if I am dynamically calling in an image as part of a repeat region where the images will all have different sizes?

Here is my code:

<cfif qShowSearch.showImage1 NEQ "">
<div class="no_img">
<a href="show.cfm?showID=#qShowSearch.showID#">

<cfset image = "images/show_images/#qShowSearch.ShowImage1#">
<cfset myImg = imageNew(image)>

<cfset imageCrop(myImg, (myimg.width/2) - (300/2), (myimg.height/2) - (200/2), 300, 200)>
<cfimage action="writeToBrowser" source="#myImg#">
</a>
</div>
</cfif>

Comment 8 by Raymond Camden posted on 3/12/2010 at 3:05 AM

So I'm guessing your image is smaller than the desired crop (300/200). If so, you need to come up with a formula that scales the desired crop, OR, I'd simply not crop. If my image is smaller than/equal to 300/200, I wouldn't bother cropping.

Comment 9 by Christopher David Kowalski posted on 3/12/2010 at 3:06 AM

Gareth,

Haven't reviewed your code to see if this really is the issue, but in my implementation I didn't hardcode the height/width values of the image that's getting cropped, I let CFIMAGE determine the shortest side, then crop by that value instead.

Comment 10 by Gareth posted on 3/12/2010 at 3:31 AM

Thanks Guys, so what would be appropriate coding for a cfid statement not to crop if the image if it falls below a certain width.

For my own application I am trying o create a thumbnail that is to a fixed width and height of 100px, hence the centre crop that will visually look better, as in such apps like Facebook.

Thanks in advance.

Comment 11 by Christopher David Kowalski posted on 3/12/2010 at 3:35 AM

Gareth,

Maybe Ray can whip up a quick example for you, but just use CFIMAGE to determine the height and width of the image. Then, whatever value is smaller, crop the image by that...

So, say you have a tall image, 500 pixels tall, 200 pixels wide.

CFIMAGE will tell you the shortest side is 200. Thus, on your imageCrop you would use the "200" value for height/width.

Comment 12 by Raymond Camden posted on 3/12/2010 at 3:55 AM

I don't I'd add anything else to what Christopher said.

Comment 13 by Dave Collazo posted on 6/1/2010 at 2:29 AM

I'm trying to submit a form which will submit itself without user input. A different form supplies an image file to be resized and cropped. The page that receives the image uploads the file and resizes it. In order to then use imageCrop, I want to define a form which contains the cf_imageCropper tag and sends itself the code which will do the imageCrop. Cflocation doesn't work since it doesn't submit the form. Any suggestions would be appreciated.
Dave

Comment 14 by Raymond Camden posted on 6/1/2010 at 2:37 AM

If the form includes a file upload, you can't auto submit it afaik. That's a security risk. Not sure what cf_imageCropper is so I can't comment on that.

Comment 15 by Matthew Clemente posted on 7/1/2011 at 11:54 PM

Ray, just wanted to say thanks.

I Googled "coldfusion crop to center of image", this was the first result, and I got it working in five minutes.

Comment 16 by Raymond Camden posted on 7/2/2011 at 1:46 AM

Glad to help!