Transparent Rounded Corners for the Masses

Ok, so a late night of coding here… I should have been in bed like 2+ hours ago, but its all worth it because I've got it working: fully transparent rounded corners on your images. Just hit "more" to see the code.

The Code

<cffunction name="ImageRoundedCorners" output="false" returntype="any">
    <cfargument name="image" type="any" required="true" />
    <cfargument name="archeight" type="numeric" required="false" default="0" />
    <cfargument name="arcwidth" type="numeric" required="false" default="0" />
    
    <cfset var local = StructNew() />
    
    <!--- Initialize java classes --->
    <cfset local.BufferedImage = CreateObject("java", "java.awt.image.BufferedImage") />
    <cfset local.RoundRectangle2D = CreateObject("java", "java.awt.geom.RoundRectangle2D$Float") />
    
    <!--- Get Information to pull width and height --->
    <cfset local.info = ImageInfo(arguments.image) />
    
    <!--- Create a new transparent image the correct size --->
    <cfset local.newImage = local.BufferedImage.init(
        local.info.width,
        local.info.height,
        local.BufferedImage.TYPE_INT_ARGB
    ) /
>

    
    <!--- Create the rounded corner clipping mask --->
    <cfset local.clippingMask = local.RoundRectangle2D.init(
        JavaCast("float", 0),
        JavaCast("float", 0),
        JavaCast("float", local.info.width),
        JavaCast("float", local.info.height),
        JavaCast("float", arguments.archeight),
        JavaCast("float", arguments.arcwidth)            
    ) /
>

    
    <!--- Get the graphics object --->
    <cfset local.graphics = local.newImage.createGraphics() />
    
    <!--- Set the clipping mask --->
    <cfset local.graphics.clip(local.clippingMask) />
    
    <!--- Draw the original image over the old one --->
    <cfset local.graphics.drawImage(
        ImageGetBufferedImage(arguments.image),
        0,
        0,
        JavaCast("null", "")        
    ) /
>


    <!--- Convert the image and return it --->
    <cfreturn ImageNew(local.newImage) />
</cffunction>

The Usage


<cfset myImage = ImageNew("warbird.jpg") />
<cfset myImage = ImageRoundedCorners(myImage, 25, 25) />
<cfimage action="writetobrowser" source="#myImage#" />

Its that easy.

Romulan warbird with rounded corners

Update

Yeah, the code that has been pointed out over at cfSearching definitely blows mine out of the water... I didn't think I was the first, but man, that post must have been hiding all of the times I searched for similar solutions. Rather then reinventing the wheel, I'll just point you to go get the code from over there :)

 

Comments

Azadi Saryev's Gravatar Way cool, man! This is awesome!
You should definitely ping Ray Camden & Ben Nadel so they include this in their ImageUtils.cfc

Azadi
Azadi Saryev's Gravatar there must be a way to set antialiasing on local.clippingMask or local.graphics... that shold get rid of the jaggy edges on the corners?
i looked up java.awt.RenderingHints documentation, but my knowledge of Java is so limited i could not make it work... maybe you could give that a try? i _think_ the result will look better...

Azadi
Andrew Penhorwood's Gravatar Here is an example of the same thing. I found this a few months back.

http://cfsearching.blogspot.com/2007/12/creating-p...
Azadi Saryev's Gravatar yep, just found it, too... much better corners, btw...

Azadi
Jon Hartmann's Gravatar @Azadi, thanks, and I'll get Ray and Ben the code once I've cleaned it up more. You're on the right track with using the RenderingHints to set anti-aliasing on.

@Andrew interesting example! I'd not see that particular example, but it looks like he went up the exact same path I did. I'd wanted to do this when CF8 came out, but it wasn't until Ray Camden told me that you could use the $ notation to access the nested classes that it became a possibility (as a not, I'd been told by Adobe reps that the inability to instantiate a nested class was a bug, because even they didn't know about $).

I'm not sure why the other code has better corners, since he doesn't mention using RenderingHints. Perhaps its due to his use of a RoundRectangle2D$Double vs my RoundRectangle2D$Float.
Comments are not allowed for this entry.
Jon Hartmann, July 2011

I'm Jon Hartmann and I'm a Javascript fanatic, UX/UI evangelist and former ColdFusion master. I blog about mysterious error messages, user interface design questions, and all things baffling and irksome about programming for the web.

Learn more about me on LinkedIn.