Search code examples
imagemagickjavafx-2image-manipulationgraphicsmagickim4java

GraphicsMagick crop: shows what will be cropped


I'm working on a photo application and I need some advice how should I solve the following with Graphics/ImageMagick.

  1. Given a photo with resolution: 2048x1536
  2. Given a specified resolution: 1864x1228
  3. Resize the image and fill the specified resolution with the image (now it's 1864x1398)
  4. Highlight the area of the original image will be cropped (to 1864x1228)

I have a working solution which resizes and crops the image properly:

IMOperation resizeOp = new IMOperation();
resizeOp.addImage();
resizeOp.resize(MAX_WIDTH, MAX_HEIGHT, "^");
resizeOp.gravity("center"); //centered image with crop the top/bottom parts
resizeOp.crop(MAX_WIDTH, MAX_HEIGHT, 0, 0);
resizeOp.addImage();

ConvertCmd cmd = new ConvertCmd(true);
cmd.run(resizeOp, fileName, outputFileName); //cropped, center filled image (1864x1228)

The question is how should I do the following: show the full image instead of the cropped version and highlight the area of the image will be cropped. I'd prefer with red border around the cropped image and show with the cropped parts with alpha layer.

I have an idea which I don't like very much: generate an image from the original with alpha layer and put the cropped image on it with red border. It doesn't seem to be the optimal solution :) My other idea is to do this with javafx imageviews, but it seems suboptimal as well.

Notes:

  • I'm using im4java with GM. I accept a command line solution too (and I'll figure out and post it in im4java ;)
  • We can restrict the conversation about horizontal images only, I can figure out the vertical operations

Any comments would be highly appreciated.


Solution

  • The oneliner imagemagick convert (remove the line breaks):

        convert ( in.jpg -resize 1864x1228^ -fill white -colorize 50% )
                ( in.jpg -resize 1864x1228^ -gravity center -crop 1864x1228+0+0 )
                -gravity center -composite out.jpg
    

    In bash, you have to escape the () characters with \!

    I solved it in im4java with sub operations:

        IMOperation op = new IMOperation();
    
        op.openOperation();
        op.addImage(); //input image
        op.resize(MAX_WIDTH, MAX_HEIGHT, "^");
        op.fill("white");
        op.colorize(50);
        op.closeOperation();
    
        op.openOperation();
        op.addImage(); //input image
        op.resize(MAX_WIDTH, MAX_HEIGHT, "^");
        op.gravity(GRAVITY_OPT_CENTER); //centered image with crop the top/bottom parts
        op.crop(MAX_WIDTH, MAX_HEIGHT, 0, 0);
        op.closeOperation();
    
        op.gravity(GRAVITY_OPT_CENTER);
        op.composite();
        op.addImage(); // output image
    

    Notes:

    • It still doesn't contain red border (I can't add border only to the second image).
    • I decided to use "fade to white" effect, instead of playing with alpha channel.

    Example: