Skip to content

Commit

Permalink
Added resize Mode.BEST_FIT_BOTH to the Scalr engine, ref rkalla#94.
Browse files Browse the repository at this point in the history
  • Loading branch information
elygre committed Jan 31, 2014
1 parent 2d891c9 commit e792fb5
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 5 deletions.
29 changes: 24 additions & 5 deletions src/main/java/org/imgscalr/Scalr.java
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,12 @@ public static enum Mode {
* how it makes the image look, that is what this mode is for.
*/
FIT_EXACT,
/**
* Used to indicate that the scaling implementation should calculate
* dimensions for the largest image that fit within the bounding box,
* without cropping or distortion, retaining the original proportions.
*/
BEST_FIT_BOTH,
/**
* Used to indicate that the scaling implementation should calculate
* dimensions for the resultant image that best-fit within the given
Expand Down Expand Up @@ -1615,7 +1621,24 @@ public static BufferedImage resize(BufferedImage src, Method scalingMethod,
* just specify the dimensions they would like the image to roughly fit
* within and it will do the right thing without mangling the result.
*/
if (resizeMode != Mode.FIT_EXACT) {
if (resizeMode == Mode.FIT_EXACT) {
if (DEBUG)
log(1,
"Resize Mode FIT_EXACT used, no width/height checking or re-calculation will be done.");
} else if (resizeMode == Mode.BEST_FIT_BOTH) {
float requestedHeightScaling = ((float) targetHeight / (float) currentHeight);
float requestedWidthScaling = ((float) targetWidth / (float) currentWidth);
float actualScaling = Math.min(requestedHeightScaling, requestedWidthScaling);

targetHeight = Math.round((float) currentHeight * actualScaling);
targetWidth = Math.round((float) currentWidth * actualScaling);

if (targetHeight == currentHeight && targetWidth == currentWidth)
return src;

if (DEBUG)
log(1, "Auto-Corrected width and height based on scalingRatio %d.", actualScaling);
} else {
if ((ratio <= 1 && resizeMode == Mode.AUTOMATIC)
|| (resizeMode == Mode.FIT_TO_WIDTH)) {
// First make sure we need to do any work in the first place
Expand Down Expand Up @@ -1655,10 +1678,6 @@ public static BufferedImage resize(BufferedImage src, Method scalingMethod,
"Auto-Corrected targetWidth [from=%d to=%d] to honor image proportions.",
originalTargetWidth, targetWidth);
}
} else {
if (DEBUG)
log(1,
"Resize Mode FIT_EXACT used, no width/height checking or re-calculation will be done.");
}

// If AUTOMATIC was specified, determine the real scaling method.
Expand Down
52 changes: 52 additions & 0 deletions src/test/java/org/imgscalr/ScalrResizeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,56 @@ public void testResizeFitExact() {
Assert.assertEquals(i2.getWidth(), 500);
Assert.assertEquals(i2.getHeight(), 250);
}

@Test
public void testResizeAutoVsFitBoth() {
// FitBoth will not allow the minor axis to grow beyond the specified box. The four commented
// tests show how this interacts

// For landscape images, AUTO will let targetWidth decide scaling, even if targetHeight is violated
BufferedImage landscape = new BufferedImage(500, 250, BufferedImage.TYPE_INT_RGB);
testResizeAutoVsBoth(landscape, 500, 250, 500, 250, 500, 250);
testResizeAutoVsBoth(landscape, 500, 500, 500, 250, 500, 250);

testResizeAutoVsBoth(landscape, 800, 300, 800, 400, 600, 300); // FitBoth restricts y to 300, and adjusts x
testResizeAutoVsBoth(landscape, 800, 400, 800, 400, 800, 400);
testResizeAutoVsBoth(landscape, 800, 500, 800, 400, 800, 400);

testResizeAutoVsBoth(landscape, 250, 150, 250, 125, 250, 125);
testResizeAutoVsBoth(landscape, 250, 125, 250, 125, 250, 125);
testResizeAutoVsBoth(landscape, 250, 100, 250, 125, 200, 100); // FitBoth imposes smaller y, and adjusts x

// For portrait images, AUTO will let targetHeight decide scaling, even if targetWidth is violated
BufferedImage portrait = new BufferedImage(250, 500, BufferedImage.TYPE_INT_RGB);
testResizeAutoVsBoth(portrait, 250, 500, 250, 500, 250, 500);
testResizeAutoVsBoth(portrait, 500, 500, 250, 500, 250, 500);

testResizeAutoVsBoth(portrait, 300, 800, 400, 800, 300, 600); // FitBoth restricts x to 800, and adjusts y
testResizeAutoVsBoth(portrait, 400, 800, 400, 800, 400, 800);
testResizeAutoVsBoth(portrait, 500, 800, 400, 800, 400, 800);

testResizeAutoVsBoth(portrait, 150, 250, 125, 250, 125, 250);
testResizeAutoVsBoth(portrait, 125, 250, 125, 250, 125, 250);
testResizeAutoVsBoth(portrait, 100, 250, 125, 250, 100, 200); // FitBoth imposes smaller xj, and adjusts y

// Squares are treated as a landscape
BufferedImage square = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
testResizeAutoVsBoth(square, 500, 500, 500, 500, 500, 500);
testResizeAutoVsBoth(square, 800, 800, 800, 800, 800, 800);
testResizeAutoVsBoth(square, 400, 400, 400, 400, 400, 400);
testResizeAutoVsBoth(square, 800, 600, 800, 800, 600, 600); // FixBoth restricts both dimensions

}

// resize to (w,h) using AUTO and FIT_BOTH modes, then compare auto (w,h) and fitBoth (w,h)
private void testResizeAutoVsBoth (BufferedImage i, int targetWidth, int targetHeight, int autoWidth, int autoHeight, int fitBothWidth, int fitBothHeight) {
BufferedImage auto = Scalr.resize(i, Mode.AUTOMATIC, targetWidth, targetHeight);
BufferedImage fitBoth = Scalr.resize(i, Mode.BEST_FIT_BOTH, targetWidth, targetHeight);

Assert.assertEquals (autoWidth, auto.getWidth());
Assert.assertEquals(autoHeight, auto.getHeight());

Assert.assertEquals(fitBothWidth, fitBoth.getWidth());
Assert.assertEquals(fitBothHeight, fitBoth.getHeight());
}
}

0 comments on commit e792fb5

Please sign in to comment.