loo.no

Home, sweet home

Rounded corners with Paperclip

10. August 2009

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:

1
2
3
4
5
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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.


99e0b39c091e10d9c7d4452a34ca52dc

Simone Carletti commented about 12 hours later (August 11, 2009 11:16)

I didn’t know it was possible to obtain such this kind of image transformations with Paperclip before reading this post. That’s a really nice example of :convert_options advanced usage.

Thanks!

3c86162f474a9c78753f34cde8828eeb

Ken-guru commented about 14 hours later (August 11, 2009 12:48)

Easy and concise, I like it.
Just used it now in a project and it made a world of difference.

7255ce34f45920257de1237b7ade2c1e

Lars commented about 15 hours later (August 11, 2009 13:43)

Here’s the result of the above processing:

29669becb5984e87c669222cc9d3c6fb

Dave Giunta commented about 17 hours later (August 11, 2009 15:36)

That’s definitely some crazy ImageMagick-fu! Nice work! In other news, that is one pimp-daddy bathroom!

039547def8be2e50f7dc4a1beb9fecaa

Jeff Casimir commented about 19 hours later (August 11, 2009 17:49)

I like it, but I don’t get it. Trying to make sense of why you have to draw a black polygon first, then a white circle second. I guess it has to do with the flip/flopping and Multiply compositions — you know why people hate on the complexities of ImageMagick.

0211880ce079559b1247cb1aa718185b

Meno commented 17 days later (August 28, 2009 13:40)

Looks like i’m not as good in copy pasting than you. If i try this with my installation it fails. I got ImageMagick 6.5.3-Q8 for windows and paperclip 2.3.
Is it possible, that it’s just not working with my versions?

7255ce34f45920257de1237b7ade2c1e

Lars commented 21 days later (September 01, 2009 15:15)

I’m running at Ubuntu with ImageMagick 6.4.5-Q16 and Paperclip 2.2.9 – if you pastie a dump of your error, I could have a look. Might be some difference with either ImageMagick or Paperclip on Windows too?

45cb3184d6842f7b22f477a5418681da

Bookis commented about 1 month later (September 18, 2009 22:39)

I had quite a lot of trouble getting this method to work for png’s with transparency already in them. Although the solution is pretty simple I thought I would paste it for anyone else who knows nothing about ImageMagick:

def self.convert_options trans = "" px = 16 trans << "\\( +clone -alpha extract " 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 << "\\) -composite \\) +matte -compose CopyOpacity -composite " end

Thanks for the this rounding corners method. It’s awesome.

866ac1bc8d7f861b24f7b7b5d961d77e

Joost commented 5 months later (January 18, 2010 16:18)

Nice work, but I have a question. Why are the files so big? Like the example above here. The image is 240kb big. Is it some setting in imagemagick? Anyone have a solution for this. thx a lot!

E363a6bfb503b839d24660039798c706

Ctaloc commented 5 months later (February 01, 2010 02:15)

Nice dud, ty.


Write a comment