Commit 08a8d884 authored by Brandon Wylie's avatar Brandon Wylie Committed by Commit Bot

[IC] Scale images before storing them in memory and returning

Scaling/cropping images we get for Feed, yields a roughly 5x
decrease in memory usage.

Image size before: 1064160 bytes
Image size after:  188356  bytes

Bug: 910192
Change-Id: I7b4347c9e34f6f8680886bb2c0dd14f5b4346ebe
Reviewed-on: https://chromium-review.googlesource.com/c/1357608
Commit-Queue: Brandon Wylie <wylieb@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Reviewed-by: default avatarSky Malice <skym@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613372}
parent 9a69fc89
......@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.cached_image_fetcher;
import android.graphics.Bitmap;
import android.media.ThumbnailUtils;
import org.chromium.base.Callback;
import org.chromium.base.DiscardableReferencePool;
......@@ -63,6 +64,7 @@ public class InMemoryCachedImageFetcher implements CachedImageFetcher {
}
mCachedImageFetcher.fetchImage(url, width, height, (Bitmap bitmap) -> {
bitmap = tryToResizeImage(bitmap, width, height);
storeBitmap(bitmap, url, width, height);
callback.onResult(bitmap);
});
......@@ -140,6 +142,32 @@ public class InMemoryCachedImageFetcher implements CachedImageFetcher {
return Math.min(maxCacheUsage, preferredCacheSize);
}
/**
* Try to resize the given image if the conditions are met.
*
* @param bitmap The input bitmap, will be recycled if scaled.
* @param width The desired width of the output.
* @param height The desired height of the output.
*
* @return The resized image, or the original image if the conditions aren't met.
*/
@VisibleForTesting
Bitmap tryToResizeImage(Bitmap bitmap, int width, int height) {
if (width != 0 && height != 0 && bitmap.getWidth() != width
&& bitmap.getHeight() != height) {
/* The resizing rules are the as follows:
(1) The image will be scaled up (if smaller) in a way that maximizes the area of the
source bitmap that's in the destination bitmap.
(2) A crop is made in the middle of the bitmap for the given size (width, height).
The x/y are placed appropriately (conceptually just think of it as a properly sized
chunk taken from the middle). */
return ThumbnailUtils.extractThumbnail(
bitmap, width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
} else {
return bitmap;
}
}
/** Test constructor. */
@VisibleForTesting
InMemoryCachedImageFetcher(BitmapCache bitmapCache, CachedImageFetcher cachedImageFetcher) {
......
......@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.cached_image_fetcher;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
......@@ -36,6 +38,7 @@ import org.chromium.chrome.browser.BitmapCache;
/**
* Unit tests for InMemoryCachedImageFetcher.
*/
@SuppressWarnings("unchecked")
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class InMemoryCachedImageFetcherTest {
......@@ -68,6 +71,8 @@ public class InMemoryCachedImageFetcherTest {
MockitoAnnotations.initMocks(this);
mReferencePool = new DiscardableReferencePool();
mBitmapCache = new BitmapCache(mReferencePool, DEFAULT_CACHE_SIZE);
mInMemoryCachedImageFetcher =
spy(new InMemoryCachedImageFetcher(mBitmapCache, mCachedImageFetcherImpl));
}
@After
......@@ -93,9 +98,12 @@ public class InMemoryCachedImageFetcherTest {
.fetchImage(eq(URL), mWidthCaptor.capture(), mHeightCaptor.capture(),
mCallbackCaptor.capture());
// clang-format on
doReturn(bitmap)
.when(mInMemoryCachedImageFetcher)
.tryToResizeImage(eq(bitmap), eq(WIDTH_PX), eq(HEIGHT_PX));
}
@SuppressWarnings("unchecked")
@Test
@SmallTest
public void testFetchImageCachesFirstCall() throws Exception {
......@@ -126,6 +134,27 @@ public class InMemoryCachedImageFetcherTest {
.fetchImage(eq(URL), eq(WIDTH_PX), eq(HEIGHT_PX), any());
}
@Test
@SmallTest
public void testResize() throws Exception {
Bitmap result =
mInMemoryCachedImageFetcher.tryToResizeImage(mBitmap, WIDTH_PX / 2, HEIGHT_PX / 2);
assertNotEquals(result, mBitmap);
}
@Test
@SmallTest
public void testResizeBailsOutIfSizeIsZero() throws Exception {
Bitmap result = mInMemoryCachedImageFetcher.tryToResizeImage(mBitmap, 0, HEIGHT_PX);
assertEquals(result, mBitmap);
result = mInMemoryCachedImageFetcher.tryToResizeImage(mBitmap, WIDTH_PX, 0);
assertEquals(result, mBitmap);
result = mInMemoryCachedImageFetcher.tryToResizeImage(mBitmap, 0, 0);
assertEquals(result, mBitmap);
}
@Test
@SmallTest
public void testFetchImageDoesNotCacheAfterDestroy() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment