MiniMagick, and processing thumbnails...

I have a requirement that can't be that outrageous....

I want to be able to upload an image, and have multiple thumbnails be created for each. Then, I want to post process each image (the main image plus the thumbnails) to add borders. The trick is that the borders need to be different for each image. I thought I could use the after_resize handler, but when I try to add a border to the passed image, the other images are also affected by this call. It seems to work like this:

- create the main image - call after_resize - (DO MY STUFF)

This modified image is now the basis for the thumbnails. Therefore, the after_resize gets called with an image that already has a border attached. I think this is wrong...

I've ended up doing this after the main photo model has been saved:

[ @photo.public_filename, @photo.public_filename( :thumb ), @photo.public_filename( :medium ), @photo.public_filename( :large )].each do |path|           path = "#{RAILS_ROOT}/public/#{path}"           file = MiniMagick::Image.from_file( path )           file.combine_options do |i|             i.gravity 'center'             i.bordercolor 'black'             i.border 1             i.bordercolor 'white'             i.border 10           end           file.write( path )         end

Ick Ick Ick.

Can anyone offer a better way of adding custom borders to each image?

Would it be possible to do this strictly via CSS? Adding a special class to the image as it comes out and just applying the needed border? You could do the border as a background on a div that surrounds the image if the border is graphical rather than solid or dashed. It would make for alot less server side work, and the border would be cached after the first load saving you some bandwidth in the process.

Would it be possible to do this strictly via CSS? Adding a special class to the image as it comes out and just applying the needed border?

+ 1

I agree, it would be better to do this with CSS. However, I'm having a heck of a time trying to get the right incantation. The issue I ran into that basically drove me nuts was that the div surrounding the image was expanding to the width of the container div, making the border too large. I would work if I didn't specify a specific size for the container div, but then the images wouldn't line up into columns, which looked pretty awful.

Anyone have any sample CSS that would work in this situation? I'll take another crack at it today, but some practical examples would be nice. :slight_smile:

Send me the HTML but here are some simple examples:

<div class="borderImg"> <img src="bob" /> </div>

.borderImg IMG {border:2px solid #000000;}

OR

<img src="bob" class="borderImg" /> IMG.borderImg {border:2px solid #000000;}

OR

<div class="borderImg"> <img src="bob" /> </div>

.borderImg {background:url(bobBorder) top left no-repeat #FFFFFF;padding:2px;}

(Leave padding so you can see the border around the IMG then you won't need any height and width on the div)

If you are having problems with divs - you can try a span instead - divs are block level and always expand width-wise to the size of their container, spans are inline elements. You can also place a float:left or float:right on the div to make it inline, but you would then need to add an addition div below the element to clear the float -

<div class="borderImg"> <img src="bob" /> </div> <div class="spacer">&nbsp;</div> .borderImg {background:url(bobBorder) top left no-repeat #FFFFFF;padding:2px;float:left;} .spacer {clear:both;height:0px;line-height:0px;font-size:0px;}

hopefully that helps.

<div class="content"><img src="image.jpg"></div>

So in the CSS it could be something like:

.content img {   border:1px solid #ccc;   padding:3px;   margin:6px;   background-color:#f9f9f9; }

Ah! I hadn't thought of using the background to create the border. That's exactly what I was looking for. Here's what I ended up with, with a little prototype to center the images in their respective boxes:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:// www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <script src='prototype.js'></script> <style type='text/css'>   body {     background-color: black;   }   .content {     height: 250px;     width: 250px;     float: left;     border: 1px solid red; /* for illustrative purposes */   }   .content img   {     border:10px solid white;     padding:1px;     background-color:black;   } </style> <script type='text/javascript'>   window.onload = function() {       $$( '.content img' ).each( function( image ) {           if( image.tagName == "IMG" ) {             marginLeft = ( ( image.up().getWidth() - image.getWidth() - 6 ) / 2 ) + 'px'           marginTop = ( ( image.up().getHeight() - image.getHeight() - 6 ) / 2 ) + 'px'             image.setStyle( { 'marginLeft' : marginLeft, 'marginTop' : marginTop } );           }       } );   } </script> </head> <body>   <div class='content'><img src='landscape.jpg'/></div>   <div class='content'><img src='landscape.jpg'/></div>   <div class='content'><img src='portrait.jpg'/></div>   <div class='content'><img src='landscape.jpg'/></div> </body> </html>

Works exactly as I wanted.

Thanks guys!