Rounded corners with Paperclip

Posted on · · Tags: paperclip

When applying a new design to one of our projects, we were in a need of a Paperclip style with rounded corners. Luckily for us we had Paperclip’s :convert_options and strong ImageMagick-fu.

After trying out some different CSS hacks, and jQuery plugins for getting the rounded corner effects we wanted, we turned to Paperclip. Since this particular style of a photo was only to be used at one place in the new design, we could apply the rounded corners directly to the image.

I googled around a bit and found a fork of Paperclip by shadow11 with some changes that never made it into the official Paperclip repository. His approach was to add the rounded corner code into Paperclip itself, and provide a argument to has_attached called rounded. IMO that’s probably nice-to-have if you do a lot of rounded corners on your attachments, but probably not something most people need. So I went ahead and copy-pasted out the juicy parts from his commit.

Firstly, we need to make sure that the style we are applying rounded corners to is a PNG file, since that’s the only file-format we have on the web that’s capable of transparancy (which we’ll use for the rounded corners effect). So my initial User model (borrowed from the Paperclip example) looks like this:

class User < ActiveRecord::Base
  has_attached_file :avatar,
    :styles => { :medium => ["300x300>", :png],
                          :thumb =>  "100x100>" }
end

So, in order to get some corners stripped of this new PNG style, we need to utilize Paperclip’s convert_options, which allows us to give extra parameters to the ImageMagick convert command that Paperclip uses for resizing. The extra flags that does this job is as follows (I’m no ImageMagick pro-user, but a good copy-paster, and it actually works):

\( +clone  -threshold -1 -draw 'fill black polygon 0,0 0,5 5,0 fill white circle 5,5 5,0' \( +clone -flip \) -compose Multiply -composite \( +clone -flop \) -compose Multiply -composite \) +matte -compose CopyOpacity -composite

This adds a 5 pixel rounding to all four corners of our image, replacing the old ones with a transparent background.

In order to get this into my Avatar, all I had to do was to include this code in the hash being sent to has_attached (THE Paperclip command). While testing, I actually Proc’ed the convert_options and ended up with the code below, but that’s really not necessary, you probably want to roll your own something on this part. But here’s the full User model that’s working:


class User < ActiveRecord::Base
  has_attached_file :avatar,
                    :styles => { :medium => ["300x300>", :png],
                                 :thumb => "100x100>" },
                    :convert_options => {:medium => Proc.new{self.convert_options}}
 
  def self.convert_options
    trans = ""
    px = 20
    trans << " \\( +clone  -threshold -1 "
    trans << "-draw 'fill black polygon 0,0 0,#{px} #{px},0 fill white circle #{px},#{px} #{px},0' "
    trans << "\\( +clone -flip \\) -compose Multiply -composite "
    trans << "\\( +clone -flop \\) -compose Multiply -composite "
    trans << "\\) +matte -compose CopyOpacity -composite "
  end
end

And that’s all. The medium style of my attached Avatar is now rounded with nice 20px corners. Looking forward to implement this (in a cleaner way) on the project tomorrow.

blog comments powered by Disqus