Monday, 23 January 2012

Ruby on Rails :Cropping images in runtime using Jcrop & ImageMagick

In the previous post i have mentioned about integrating the Jcrop functionality with ImageMagick to hide the selected coordinates  of  the image using a specific color.But here i  am describing on the core feature of Jcrop i.e cropping the image in runtime with the selected coordinates.Here also , we are using ImageMagick in server side to accomplish the whole process.

You all know that Jcrop is a powerful image cropping engine for jQuery. It’s been designed so developers can easily integrate an advanced image cropping functionality directly into any web-based application without sacrificing their time ,flexibility and performance.
ImageMagick is a software suite to create, edit, compose, or convert bitmap images. It can read and write images in a variety of fomats (over 100) like   DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PhotoCD, PNG, Postscript, SVG, and TIFF. We can use ImageMagick to resize, flip, mirror, rotate, distort, shear and transform images, adjust image colors, apply various special effects, or draw text, lines, polygons, ellipses and Bézier curves. ImageMagick have a power full command line tool known as “Convert”. Convert has around 265  options for manipulating images .
So now we are going to integrate this two with Rails ,i wont go in depth of how to create the whole process.
In summery :
  • User choose an image and uploads to a server using paperclip.
  • Wep app shows the images to user and allows him/her to select the desired piece of selection of the image to hide using Jcrop.
  • Using an Ajax post request ,we are sending the parameters (X-cord,Y-cord,Height,Width) to the sever which responsible to crop the portion of the image.
  • The appropriate action in the controller will accept the parameters,and then crop the parameters by using a piece of Image-magic code.

Jcrop Action :
In the client side ,where we are showing the uploaded image to the user.Here we have to add the Jcrop functionality to select the coordinates of the selection that the user want to crop .
Here you could see a button for “CROP” . I will brief you the actions behind this button.The CROP button will captures the desired parameters of the  selection on the click event ,and then add it to a list called "crop_list".when the user clicks the button the coordinates will push to the crop_list and then sending the coordinates as a parameter by using an AJAX post request to the desired URL which accepting the parameters.
<img src=" // your image source" id="target" />

<form id="coords"
class="coords"
onsubmit="return false;"
action="http://example.com/post.php">
<div>
<input type="hidden" size="4" id="x1" name="x1" />
<input type="hidden" size="4" id="y1" name="y1" />
<input type="hidden" size="4" id="x2" name="x2" />
<input type="hidden" size="4" id="y2" name="y2" />
<input type="hidden" size="4" id="w" name="w" />
<input type="hidden" size="4" id="h" name="h" />

</div>
<button id = "crop" >CROP</button>


</form>
<div style="clear:both;display: block;height: 5px;" ></div>
 <div id="outer">
  <div class="jcExample">
   <div class="article">
    <div id="interface" style="margin: 1em 0;"></div>

  </div>
 </div>
</div>
</div>



</style>

<script type="text/javascript">
jQuery(function($){

$('#target').Jcrop({
onChange: showCoords,
onSelect: showCoords,
onRelease: clearCoords
});

});
function showCoords(c)
{
$('#x1').val(c.x);
$('#y1').val(c.y);
$('#x2').val(c.x2);
$('#y2').val(c.y2);
$('#w').val(c.w);
$('#h').val(c.h);
};

function clearCoords()
{
$('#coords input').val('');
$('#h').css({color:'red'});
window.setTimeout(function(){
$('#h').css({color:'inherit'});
},500);
};

</script>
Now the crop_list contains all the selected coordinates that the user wants to crop ,and then we are sending all these coordinates to a server using Ajax post request with the selected coordinates as parameters .
<script type="text/javascript">

var crop_list=[];
var cord_list=[];

jQuery(document).ready(function(){
  jQuery("#crop").click(function(){

    var X1 = jQuery("#x1").val();
    var Y1 = jQuery("#y1").val();
    var X2 = jQuery("#x2").val();
    var Y2 = jQuery("#y2").val();
    var W = jQuery("#w").val();
    var H = jQuery("#h").val();

    cord_list= [W,H,X1,Y1];

    crop_list.push(cord_list);

 
    var val = crop_list;
    jQuery.ajax({
      type: "POST",
      url: "/image/crop",
      data: {"cordinates": val},
      complete: function () {
      window.location.reload(true);
      }});
   }):
});

</script>
ImageMagick Action :
Now we comes to the server side.I have created an action called "crop" in my rails application's controller.Here the "crop" action will accept the parameters, and then the magic comes with that snippet of  ImageMagic as shown below.
def crop
    cordinates = params["cordinates"]
    image_path = "# specify your image path "
    coordinates.each do |item|
       coordinate = item[1]
       cord = coordinate[0].to_s + 'x' + coordinate[1].to_s + '+' + coordinate[2].to_s + '+' +        coordinate[3].to_s

       system "convert #{img_path} -crop #{cord} #{img_path}"
    end
end.

The main keyword that you have to notice in the above snippet is "crop".The "cord" variable is nothing but the coordinates that we are sending via an ajax post request to the server.The coordinates are nothing but "Height","Width","X-cord","Y-cord".Here we are accepting that coordinates using params key word and assigning it to a variable .Then we have to specify the image_path of the desired image that you wants to crop."crop" keyword will do the cropping function by an amount that we are specified.

Here we are iterating the loop and executing the command number of times equal to the number of selection."System" is the command in ruby to execute shell commands from the script.After executing the above script we will get the modified picture and then as a response we can send it to a client.But here in the Ajax post request i just coded the command to reload the whole page again as response to affect the changes in the client side.Now the client will see the new image with the applied changes.

I have hosted this application in Heroku. Check out the below link, 

No comments:

Post a Comment