From 2007bde3a837c3ae9300b4270793fba030189709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Charmas?= Date: Fri, 19 Sep 2014 15:29:19 +0200 Subject: [PATCH] Added resizing with keeping aspect ratio when dimension is 0. --- .../com/squareup/picasso/BitmapHunter.java | 9 +++-- .../java/com/squareup/picasso/Request.java | 32 ++++++++++------- .../com/squareup/picasso/RequestHandler.java | 18 +++++++--- .../main/java/com/squareup/picasso/Utils.java | 2 +- .../squareup/picasso/BitmapHunterTest.java | 24 +++++++++++++ .../squareup/picasso/RequestCreatorTest.java | 35 ++++++++++++++----- .../squareup/picasso/RequestHandlerTest.java | 14 ++++++++ 7 files changed, 105 insertions(+), 29 deletions(-) diff --git a/picasso/src/main/java/com/squareup/picasso/BitmapHunter.java b/picasso/src/main/java/com/squareup/picasso/BitmapHunter.java index 1b1a8e3a4..8b5f99ba0 100644 --- a/picasso/src/main/java/com/squareup/picasso/BitmapHunter.java +++ b/picasso/src/main/java/com/squareup/picasso/BitmapHunter.java @@ -463,12 +463,15 @@ static Bitmap transformResult(Request data, Bitmap result, int exifRotation) { float heightRatio = targetHeight / (float) inHeight; float scale = widthRatio < heightRatio ? widthRatio : heightRatio; matrix.preScale(scale, scale); - } else if (targetWidth != 0 && targetHeight != 0 // + } else if ((targetWidth != 0 || targetHeight != 0) // && (targetWidth != inWidth || targetHeight != inHeight)) { // If an explicit target size has been specified and they do not match the results bounds, // pre-scale the existing matrix appropriately. - float sx = targetWidth / (float) inWidth; - float sy = targetHeight / (float) inHeight; + // Keep aspect ratio if one dimension is set to 0. + float sx = targetWidth != 0 ? targetWidth / (float) inWidth + : targetHeight / (float) inHeight; + float sy = targetHeight != 0 ? targetHeight / (float) inHeight + : targetWidth / (float) inWidth; matrix.preScale(sx, sy); } } diff --git a/picasso/src/main/java/com/squareup/picasso/Request.java b/picasso/src/main/java/com/squareup/picasso/Request.java index 41557eb46..7d4a24fe7 100644 --- a/picasso/src/main/java/com/squareup/picasso/Request.java +++ b/picasso/src/main/java/com/squareup/picasso/Request.java @@ -157,7 +157,7 @@ String getName() { } public boolean hasSize() { - return targetWidth != 0; + return targetWidth != 0 || targetHeight != 0; } boolean needsTransformation() { @@ -165,7 +165,7 @@ boolean needsTransformation() { } boolean needsMatrixTransform() { - return targetWidth != 0 || rotationDegrees != 0; + return hasSize() || rotationDegrees != 0; } boolean hasCustomTransformations() { @@ -230,7 +230,7 @@ boolean hasImage() { } boolean hasSize() { - return targetWidth != 0; + return targetWidth != 0 || targetHeight != 0; } boolean hasPriority() { @@ -265,13 +265,19 @@ public Builder setResourceId(int resourceId) { return this; } - /** Resize the image to the specified size in pixels. */ + /** + * Resize the image to the specified size in pixels. + * Use 0 as desired dimension to resize keeping aspect ratio. + */ public Builder resize(int targetWidth, int targetHeight) { - if (targetWidth <= 0) { - throw new IllegalArgumentException("Width must be positive number."); + if (targetWidth < 0) { + throw new IllegalArgumentException("Width must be positive number or 0."); + } + if (targetHeight < 0) { + throw new IllegalArgumentException("Height must be positive number or 0."); } - if (targetHeight <= 0) { - throw new IllegalArgumentException("Height must be positive number."); + if (targetHeight == 0 && targetWidth == 0) { + throw new IllegalArgumentException("At least one dimension has to be positive number."); } this.targetWidth = targetWidth; this.targetHeight = targetHeight; @@ -390,11 +396,13 @@ public Request build() { if (centerInside && centerCrop) { throw new IllegalStateException("Center crop and center inside can not be used together."); } - if (centerCrop && targetWidth == 0) { - throw new IllegalStateException("Center crop requires calling resize."); + if (centerCrop && (targetWidth == 0 || targetHeight == 0)) { + throw new IllegalStateException( + "Center crop requires calling resize with positive width and height."); } - if (centerInside && targetWidth == 0) { - throw new IllegalStateException("Center inside requires calling resize."); + if (centerInside && (targetWidth == 0 || targetHeight == 0)) { + throw new IllegalStateException( + "Center inside requires calling resize with positive width and height."); } if (priority == null) { priority = Priority.NORMAL; diff --git a/picasso/src/main/java/com/squareup/picasso/RequestHandler.java b/picasso/src/main/java/com/squareup/picasso/RequestHandler.java index e1108fe1e..4cdb7fcbf 100644 --- a/picasso/src/main/java/com/squareup/picasso/RequestHandler.java +++ b/picasso/src/main/java/com/squareup/picasso/RequestHandler.java @@ -145,11 +145,19 @@ static void calculateInSampleSize(int reqWidth, int reqHeight, int width, int he BitmapFactory.Options options, Request request) { int sampleSize = 1; if (height > reqHeight || width > reqWidth) { - final int heightRatio = (int) Math.floor((float) height / (float) reqHeight); - final int widthRatio = (int) Math.floor((float) width / (float) reqWidth); - sampleSize = request.centerInside - ? Math.max(heightRatio, widthRatio) - : Math.min(heightRatio, widthRatio); + final int heightRatio; + final int widthRatio; + if (reqHeight == 0) { + sampleSize = (int) Math.floor((float) width / (float) reqWidth); + } else if (reqWidth == 0) { + sampleSize = (int) Math.floor((float) height / (float) reqHeight); + } else { + heightRatio = (int) Math.floor((float) height / (float) reqHeight); + widthRatio = (int) Math.floor((float) width / (float) reqWidth); + sampleSize = request.centerInside + ? Math.max(heightRatio, widthRatio) + : Math.min(heightRatio, widthRatio); + } } options.inSampleSize = sampleSize; options.inJustDecodeBounds = false; diff --git a/picasso/src/main/java/com/squareup/picasso/Utils.java b/picasso/src/main/java/com/squareup/picasso/Utils.java index f65662424..176b02d05 100644 --- a/picasso/src/main/java/com/squareup/picasso/Utils.java +++ b/picasso/src/main/java/com/squareup/picasso/Utils.java @@ -181,7 +181,7 @@ static String createKey(Request data, StringBuilder builder) { } builder.append('\n'); } - if (data.targetWidth != 0) { + if (data.hasSize()) { builder.append("resize:").append(data.targetWidth).append('x').append(data.targetHeight); builder.append('\n'); } diff --git a/picasso/src/test/java/com/squareup/picasso/BitmapHunterTest.java b/picasso/src/test/java/com/squareup/picasso/BitmapHunterTest.java index 50fec36c8..e819df826 100644 --- a/picasso/src/test/java/com/squareup/picasso/BitmapHunterTest.java +++ b/picasso/src/test/java/com/squareup/picasso/BitmapHunterTest.java @@ -405,6 +405,30 @@ public class BitmapHunterTest { assertThat(shadowMatrix.getPreOperations()).containsOnly("rotate 90.0"); } + @Test public void keepsAspectRationWhileResizingWhenDesiredWidthIs0() throws Exception { + Request request = new Request.Builder(URI_1).resize(20, 0).build(); + Bitmap source = Bitmap.createBitmap(40, 20, ARGB_8888); + + Bitmap result = transformResult(request, source, 0); + + ShadowBitmap shadowBitmap = shadowOf(result); + Matrix matrix = shadowBitmap.getCreatedFromMatrix(); + ShadowMatrix shadowMatrix = shadowOf(matrix); + assertThat(shadowMatrix.getPreOperations()).containsOnly("scale 0.5 0.5"); + } + + @Test public void keepsAspectRationWhileResizingWhenDesiredHeighIs0() throws Exception { + Request request = new Request.Builder(URI_1).resize(0, 10).build(); + Bitmap source = Bitmap.createBitmap(40, 20, ARGB_8888); + + Bitmap result = transformResult(request, source, 0); + + ShadowBitmap shadowBitmap = shadowOf(result); + Matrix matrix = shadowBitmap.getCreatedFromMatrix(); + ShadowMatrix shadowMatrix = shadowOf(matrix); + assertThat(shadowMatrix.getPreOperations()).containsOnly("scale 0.5 0.5"); + } + @Test public void exifRotationWithManualRotation() throws Exception { Bitmap source = Bitmap.createBitmap(10, 10, ARGB_8888); Request data = new Request.Builder(URI_1).rotate(-45).build(); diff --git a/picasso/src/test/java/com/squareup/picasso/RequestCreatorTest.java b/picasso/src/test/java/com/squareup/picasso/RequestCreatorTest.java index e7d9898d7..520712ee3 100644 --- a/picasso/src/test/java/com/squareup/picasso/RequestCreatorTest.java +++ b/picasso/src/test/java/com/squareup/picasso/RequestCreatorTest.java @@ -514,7 +514,31 @@ public void intoRemoteViewsNotificationWithFitThrows() { } } - @Test public void appWidgetActionWithDefaultPriority() { + @Test + public void intoTargetResizeWith0WithCenterInsideOrCenterCropThrows() { + try { + new RequestCreator(picasso, URI_1, 0).resize(0, 10).centerInside().into(mockTarget()); + fail("Center inside with unknown width should throw exception."); + } catch (IllegalStateException ignored) { + } + try { + new RequestCreator(picasso, URI_1, 0).resize(10, 0).centerInside().into(mockTarget()); + fail("Center inside with unknown height should throw exception."); + } catch (IllegalStateException ignored) { + } + try { + new RequestCreator(picasso, URI_1, 0).resize(0, 10).centerCrop().into(mockTarget()); + fail("Center inside with unknown width should throw exception."); + } catch (IllegalStateException ignored) { + } + try { + new RequestCreator(picasso, URI_1, 0).resize(10, 0).centerCrop().into(mockTarget()); + fail("Center inside with unknown height should throw exception."); + } catch (IllegalStateException ignored) { + } + } + + @Test public void appWidgetActionWithDefaultPriority() throws Exception { new RequestCreator(picasso, URI_1, 0).into(mockRemoteViews(), 0, new int[] { 1, 2, 3 }); verify(picasso).enqueueAndSubmit(actionCaptor.capture()); assertThat(actionCaptor.getValue().getPriority()).isEqualTo(NORMAL); @@ -578,13 +602,8 @@ public void intoRemoteViewsNotificationWithFitThrows() { } catch (IllegalArgumentException ignored) { } try { - new RequestCreator().resize(0, 10); - fail("Zero width should throw exception."); - } catch (IllegalArgumentException ignored) { - } - try { - new RequestCreator().resize(10, 0); - fail("Zero height should throw exception."); + new RequestCreator().resize(0, 0); + fail("Zero dimensions should throw exception."); } catch (IllegalArgumentException ignored) { } } diff --git a/picasso/src/test/java/com/squareup/picasso/RequestHandlerTest.java b/picasso/src/test/java/com/squareup/picasso/RequestHandlerTest.java index 44c45ba37..a0087632c 100644 --- a/picasso/src/test/java/com/squareup/picasso/RequestHandlerTest.java +++ b/picasso/src/test/java/com/squareup/picasso/RequestHandlerTest.java @@ -73,6 +73,20 @@ public class RequestHandlerTest { assertThat(options.inSampleSize).isEqualTo(4); } + @Test public void calculateInSampleSizeKeepAspectRatioWithWidth() { + final BitmapFactory.Options options = new BitmapFactory.Options(); + Request data = new Request.Builder(URI_1).resize(400, 0).build(); + calculateInSampleSize(data.targetWidth, data.targetHeight, 800, 200, options, data); + assertThat(options.inSampleSize).isEqualTo(2); + } + + @Test public void calculateInSampleSizeKeepAspectRatioWithHeight() { + final BitmapFactory.Options options = new BitmapFactory.Options(); + Request data = new Request.Builder(URI_1).resize(0, 100).build(); + calculateInSampleSize(data.targetWidth, data.targetHeight, 800, 200, options, data); + assertThat(options.inSampleSize).isEqualTo(2); + } + @Test public void nullBitmapOptionsIfNoResizing() { // No resize must return no bitmap options final Request noResize = new Request.Builder(URI_1).build();