Search code examples
imagemagick

Image Magick: insert image in another image: preserving aspect ratio with minimum instead of maximum size


I'm using the answer to this question:

Insert one image into another using convert

However, I am not in control over the aspect ratio of the input image, so it does not exactly fit in the destination (whose size is also variable, but I am in control of that).

By default, ImageMagic makes the image smaller:

  • Let's say I want to put the image into a 300x200 destination (because I can choose that one).
  • This works if I get a 600x400 image.
  • X But if I get a 250x200 image (or equivalently 500x400), then there are bars on the left and right.
  • X And if I get a 300x250 image (or equivalently 600x500), then there are bars on the top and bottom.

I see when this might be desirable, but I want the destination being fully covered.

  • So if I get a 250x200 image as input, I want it to be scaled to 300x400.
  • And if I get a 300x250 image as input, I want it to be scaled to 375x300.

Put differently:

  • When maintaining aspect ratio, ImageMagic makes sure that no dimension is larger than the intended size.
  • I want to make sure that no dimension is smaller than the intended size.

Solution

  • I was simply asking if ImageMagick has a possibility to preserve aspect ratio by overflowing instead of the default underflowing, but apparently it does not.

    So the answer is no, it's not possible (out of the box, so I have to write a script to do the calculations).

    .canvas {
    width:300px;
    height:300px;
    outline:2px solid black;
    position:relative;
    text-align:center;
    }
    
    
    .destination{
    outline:2px inset #0ff;
    background-color:#8ff;
    position:absolute;
    left:100px;
    top:100px;
    height:100px;
    width:100px;
    }
    
    .inner-image{
    outline:2px outset #f00;
    background-color:#f88;
    position:absolute;
    }
    
    .same-ar {
    left:0;top:0;height:200px;width:200px;
    }
    
    .same-ar:hover {
    left:100px;top:100px;
    height:100px;width:100px;
    z-index:1;
    }
    
    .portrait, .portrait-scaled {
    left:0;top:0;height:300px;width:200px;
    }
    
    .portrait:hover {
    left:117px;top:100px;
    height:100px;width:calc(100px * 200 / 300);
    z-index:1;
    }
    
    .portrait-scaled:hover {
    left:100px;top:75px;
    height:calc(100px * 300 / 200);width:100px;
    z-index:1;
    }
    
    .landscape, .landscape-scaled {
    left:0;top:0;height:200px;width:300px;
    }
    
    .landscape:hover {
    left:100px;top:117px;
    height:calc(100px * 200 / 300);width:100px;
    z-index:1;
    }
    
    .landscape-scaled:hover {
    left:75px;top:100px;
    height:100px;width:calc(100px * 300 / 200);
    z-index:1;
    }
    <p>1. This is the target image into which to insert:</p>
    <div class="canvas">
    <div class="destination">
    Want to insert the other image in this region.
    </div>
    </div>
    
    <p>2. This is the happy case of an image with the same aspect ratio:</p>
    
    <div class="canvas">
    <div class="inner-image same-ar">
    (hover for scaling)
    </div>
    <div class="destination">
    </div>
    </div>
    
    <p>3.a The aspect ratio of this image is narrower, so ImageMagick produces the result visible on hover - leaving an "underflow" where the background image is still visible:</p>
    
    <div class="canvas">
    <div class="inner-image portrait">
    (hover for scaling)
    </div>
    <div class="destination">
    </div>
    </div>
    
    <p>3.b So instead of using the blue target area coordinates in the ImageMagick command, its height and y need to be adjusted, changing the hover result:</p>
    
    <div class="canvas">
    <div class="inner-image portrait-scaled">
    (hover for scaling)
    </div>
    <div class="destination">
    </div>
    </div>
    
    <p>4.a The aspect ratio of this image is wider, so ImageMagick produces the result visible on hover - leaving an "underflow" where the background image is still visible::</p>
    
    <div class="canvas">
    <div class="inner-image landscape">
    (hover for scaling)
    </div>
    <div class="destination">
    </div>
    </div>
    
    <p>4.b So instead of using the blue target area coordinates in the ImageMagick command, its width and x need to be adjusted, changing the hover result:</p>
    
    <div class="canvas">
    <div class="inner-image landscape-scaled">
    (hover for scaling)
    </div>
    <div class="destination">
    </div>
    </div>