Thursday, 12 January 2012

Ruby on Rails : Image hiding using Jcrop & ImageMagick


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 hide the portion of the image.
  • The appropriate action in the controller will accept the parameters,and then hide 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 hide .
Here you could see 2 buttons for “ADD” & “SAVE”. I will brief you the actions behind this buttons.Here we are providing a functionality to user that ,he/she can select multiple selections using Jcrop and then we add it to a list called “cord_list”.Here each time user have to click the add button to store the each selection into a “cord_list”, and after that we are pushing the each selction list into another list called “adj_list”.Now it will act like a list of list.
<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 = "add" >ADD</button>
<button id ="save" >SAVE</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 adj_list contains all the selection coordinates that the user wants to hide ,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 adj_list=[];
var cord_list=[];

jQuery(document).ready(function(){
  jQuery("#add").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];

    adj_list.push(cord_list);

  });

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

</script>
ImageMagic Action :
Now we comes to the server side.I have created an action called save in my controller.Here the save action will accept the parameters, and then the magic comes with that snippet of  ImageMagic as shown below.
def save
    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} -region #{cord} -fill white -colorize 100% #{img_path}"
    end
end.

The main keywords that you have to notice in the above snippet,is that "region" ,"fill" & "colorize".The "region" 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 hide."fill" keyword indicates nothing but the color that the user wants to hide with."Colorize" keyword is used to colorize the image by an amount that we 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 put the command to reload the whole page again 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 this, 

No comments:

Post a Comment