diff options
Diffstat (limited to 'src/main/java/com/android/volley/toolbox/ImageRequest.java')
-rw-r--r-- | src/main/java/com/android/volley/toolbox/ImageRequest.java | 283 |
1 files changed, 0 insertions, 283 deletions
diff --git a/src/main/java/com/android/volley/toolbox/ImageRequest.java b/src/main/java/com/android/volley/toolbox/ImageRequest.java deleted file mode 100644 index 32b5aa3..0000000 --- a/src/main/java/com/android/volley/toolbox/ImageRequest.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.volley.toolbox; - -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; -import android.widget.ImageView.ScaleType; -import androidx.annotation.GuardedBy; -import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; -import com.android.volley.DefaultRetryPolicy; -import com.android.volley.NetworkResponse; -import com.android.volley.ParseError; -import com.android.volley.Request; -import com.android.volley.Response; -import com.android.volley.VolleyLog; - -/** A canned request for getting an image at a given URL and calling back with a decoded Bitmap. */ -public class ImageRequest extends Request<Bitmap> { - /** Socket timeout in milliseconds for image requests */ - public static final int DEFAULT_IMAGE_TIMEOUT_MS = 1000; - - /** Default number of retries for image requests */ - public static final int DEFAULT_IMAGE_MAX_RETRIES = 2; - - /** Default backoff multiplier for image requests */ - public static final float DEFAULT_IMAGE_BACKOFF_MULT = 2f; - - /** Lock to guard mListener as it is cleared on cancel() and read on delivery. */ - private final Object mLock = new Object(); - - @GuardedBy("mLock") - @Nullable - private Response.Listener<Bitmap> mListener; - - private final Config mDecodeConfig; - private final int mMaxWidth; - private final int mMaxHeight; - private final ScaleType mScaleType; - - /** Decoding lock so that we don't decode more than one image at a time (to avoid OOM's) */ - private static final Object sDecodeLock = new Object(); - - /** - * Creates a new image request, decoding to a maximum specified width and height. If both width - * and height are zero, the image will be decoded to its natural size. If one of the two is - * nonzero, that dimension will be clamped and the other one will be set to preserve the image's - * aspect ratio. If both width and height are nonzero, the image will be decoded to be fit in - * the rectangle of dimensions width x height while keeping its aspect ratio. - * - * @param url URL of the image - * @param listener Listener to receive the decoded bitmap - * @param maxWidth Maximum width to decode this bitmap to, or zero for none - * @param maxHeight Maximum height to decode this bitmap to, or zero for none - * @param scaleType The ImageViews ScaleType used to calculate the needed image size. - * @param decodeConfig Format to decode the bitmap to - * @param errorListener Error listener, or null to ignore errors - */ - public ImageRequest( - String url, - Response.Listener<Bitmap> listener, - int maxWidth, - int maxHeight, - ScaleType scaleType, - Config decodeConfig, - @Nullable Response.ErrorListener errorListener) { - super(Method.GET, url, errorListener); - setRetryPolicy( - new DefaultRetryPolicy( - DEFAULT_IMAGE_TIMEOUT_MS, - DEFAULT_IMAGE_MAX_RETRIES, - DEFAULT_IMAGE_BACKOFF_MULT)); - mListener = listener; - mDecodeConfig = decodeConfig; - mMaxWidth = maxWidth; - mMaxHeight = maxHeight; - mScaleType = scaleType; - } - - /** - * For API compatibility with the pre-ScaleType variant of the constructor. Equivalent to the - * normal constructor with {@code ScaleType.CENTER_INSIDE}. - */ - @Deprecated - public ImageRequest( - String url, - Response.Listener<Bitmap> listener, - int maxWidth, - int maxHeight, - Config decodeConfig, - Response.ErrorListener errorListener) { - this( - url, - listener, - maxWidth, - maxHeight, - ScaleType.CENTER_INSIDE, - decodeConfig, - errorListener); - } - - @Override - public Priority getPriority() { - return Priority.LOW; - } - - /** - * Scales one side of a rectangle to fit aspect ratio. - * - * @param maxPrimary Maximum size of the primary dimension (i.e. width for max width), or zero - * to maintain aspect ratio with secondary dimension - * @param maxSecondary Maximum size of the secondary dimension, or zero to maintain aspect ratio - * with primary dimension - * @param actualPrimary Actual size of the primary dimension - * @param actualSecondary Actual size of the secondary dimension - * @param scaleType The ScaleType used to calculate the needed image size. - */ - private static int getResizedDimension( - int maxPrimary, - int maxSecondary, - int actualPrimary, - int actualSecondary, - ScaleType scaleType) { - - // If no dominant value at all, just return the actual. - if ((maxPrimary == 0) && (maxSecondary == 0)) { - return actualPrimary; - } - - // If ScaleType.FIT_XY fill the whole rectangle, ignore ratio. - if (scaleType == ScaleType.FIT_XY) { - if (maxPrimary == 0) { - return actualPrimary; - } - return maxPrimary; - } - - // If primary is unspecified, scale primary to match secondary's scaling ratio. - if (maxPrimary == 0) { - double ratio = (double) maxSecondary / (double) actualSecondary; - return (int) (actualPrimary * ratio); - } - - if (maxSecondary == 0) { - return maxPrimary; - } - - double ratio = (double) actualSecondary / (double) actualPrimary; - int resized = maxPrimary; - - // If ScaleType.CENTER_CROP fill the whole rectangle, preserve aspect ratio. - if (scaleType == ScaleType.CENTER_CROP) { - if ((resized * ratio) < maxSecondary) { - resized = (int) (maxSecondary / ratio); - } - return resized; - } - - if ((resized * ratio) > maxSecondary) { - resized = (int) (maxSecondary / ratio); - } - return resized; - } - - @Override - protected Response<Bitmap> parseNetworkResponse(NetworkResponse response) { - // Serialize all decode on a global lock to reduce concurrent heap usage. - synchronized (sDecodeLock) { - try { - return doParse(response); - } catch (OutOfMemoryError e) { - VolleyLog.e("Caught OOM for %d byte image, url=%s", response.data.length, getUrl()); - return Response.error(new ParseError(e)); - } - } - } - - /** The real guts of parseNetworkResponse. Broken out for readability. */ - private Response<Bitmap> doParse(NetworkResponse response) { - byte[] data = response.data; - BitmapFactory.Options decodeOptions = new BitmapFactory.Options(); - Bitmap bitmap = null; - if (mMaxWidth == 0 && mMaxHeight == 0) { - decodeOptions.inPreferredConfig = mDecodeConfig; - bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); - } else { - // If we have to resize this image, first get the natural bounds. - decodeOptions.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); - int actualWidth = decodeOptions.outWidth; - int actualHeight = decodeOptions.outHeight; - - // Then compute the dimensions we would ideally like to decode to. - int desiredWidth = - getResizedDimension( - mMaxWidth, mMaxHeight, actualWidth, actualHeight, mScaleType); - int desiredHeight = - getResizedDimension( - mMaxHeight, mMaxWidth, actualHeight, actualWidth, mScaleType); - - // Decode to the nearest power of two scaling factor. - decodeOptions.inJustDecodeBounds = false; - // TODO(ficus): Do we need this or is it okay since API 8 doesn't support it? - // decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED; - decodeOptions.inSampleSize = - findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight); - Bitmap tempBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); - - // If necessary, scale down to the maximal acceptable size. - if (tempBitmap != null - && (tempBitmap.getWidth() > desiredWidth - || tempBitmap.getHeight() > desiredHeight)) { - bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth, desiredHeight, true); - tempBitmap.recycle(); - } else { - bitmap = tempBitmap; - } - } - - if (bitmap == null) { - return Response.error(new ParseError(response)); - } else { - return Response.success(bitmap, HttpHeaderParser.parseCacheHeaders(response)); - } - } - - @Override - public void cancel() { - super.cancel(); - synchronized (mLock) { - mListener = null; - } - } - - @Override - protected void deliverResponse(Bitmap response) { - Response.Listener<Bitmap> listener; - synchronized (mLock) { - listener = mListener; - } - if (listener != null) { - listener.onResponse(response); - } - } - - /** - * Returns the largest power-of-two divisor for use in downscaling a bitmap that will not result - * in the scaling past the desired dimensions. - * - * @param actualWidth Actual width of the bitmap - * @param actualHeight Actual height of the bitmap - * @param desiredWidth Desired width of the bitmap - * @param desiredHeight Desired height of the bitmap - */ - @VisibleForTesting - static int findBestSampleSize( - int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) { - double wr = (double) actualWidth / desiredWidth; - double hr = (double) actualHeight / desiredHeight; - double ratio = Math.min(wr, hr); - float n = 1.0f; - while ((n * 2) <= ratio) { - n *= 2; - } - - return (int) n; - } -} |