
com.nostra13.universalimageloader.utils.ImageSizeUtils Maven / Gradle / Ivy
/*******************************************************************************
* Copyright 2013 Sergey Tarasevich
*
* 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.nostra13.universalimageloader.utils;
import java.lang.reflect.Field;
import android.graphics.BitmapFactory;
import android.util.DisplayMetrics;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.nostra13.universalimageloader.core.assist.ViewScaleType;
/**
* Provides calculations with image sizes, scales
*
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @since 1.8.3
*/
public final class ImageSizeUtils {
private ImageSizeUtils() {
}
/**
* Defines target size for image. Size is defined by target {@link ImageView view} parameters, configuration
* parameters or device display dimensions.
* Size computing algorithm:
* 1) Get the actual drawn getWidth() and getHeight() of the View. If view haven't drawn yet then go
* to step #2.
* 2) Get layout_width and layout_height. If both of them haven't exact value then go to step #3.
* 3) Get maxWidth and maxHeight. If both of them are not set then go to step #4.
* 4) Get maxImageWidth param (maxImageWidthForMemoryCache) and maxImageHeight param
* (maxImageHeightForMemoryCache). If both of them are not set (equal 0) then go to step #5.
* 5) Get device screen dimensions.
*/
public static ImageSize defineTargetSizeForView(ImageView imageView, int maxImageWidth, int maxImageHeight) {
final DisplayMetrics displayMetrics = imageView.getContext().getResources().getDisplayMetrics();
final LayoutParams params = imageView.getLayoutParams();
int width = params.width == LayoutParams.WRAP_CONTENT ? 0 : imageView.getWidth(); // Get actual image width
if (width <= 0) width = params.width; // Get layout width parameter
if (width <= 0) width = getImageViewFieldValue(imageView, "mMaxWidth"); // Check maxWidth parameter
if (width <= 0) width = maxImageWidth;
if (width <= 0) width = displayMetrics.widthPixels;
int height = params.height == LayoutParams.WRAP_CONTENT ? 0 : imageView.getHeight(); // Get actual image height
if (height <= 0) height = params.height; // Get layout height parameter
if (height <= 0) height = getImageViewFieldValue(imageView, "mMaxHeight"); // Check maxHeight parameter
if (height <= 0) height = maxImageHeight;
if (height <= 0) height = displayMetrics.heightPixels;
return new ImageSize(width, height);
}
private static int getImageViewFieldValue(Object object, String fieldName) {
int value = 0;
try {
Field field = ImageView.class.getDeclaredField(fieldName);
field.setAccessible(true);
int fieldValue = (Integer) field.get(object);
if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
value = fieldValue;
}
} catch (Exception e) {
L.e(e);
}
return value;
}
/**
* Computes sample size for downscaling image size (srcSize) to view size (targetSize). This sample
* size is used during
* {@linkplain BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options)
* decoding image} to bitmap.
*
* Examples:
*
*
* srcSize(100x100), targetSize(10x10), powerOf2Scale = true -> sampleSize = 8
* srcSize(100x100), targetSize(10x10), powerOf2Scale = false -> sampleSize = 10
*
* srcSize(100x100), targetSize(20x40), viewScaleType = FIT_INSIDE -> sampleSize = 5
* srcSize(100x100), targetSize(20x40), viewScaleType = CROP -> sampleSize = 2
*
*
*
* The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded
* bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16
* the number of pixels. Any value <= 1 is treated the same as 1.
*
* @param srcSize Original (image) size
* @param targetSize Target (view) size
* @param viewScaleType {@linkplain ViewScaleType Scale type} for placing image in view
* @param powerOf2Scale true - if sample size be a power of 2 (1, 2, 4, 8, ...)
* @return Computed sample size
*/
public static int computeImageSampleSize(ImageSize srcSize, ImageSize targetSize, ViewScaleType viewScaleType, boolean powerOf2Scale) {
int srcWidth = srcSize.getWidth();
int srcHeight = srcSize.getHeight();
int targetWidth = targetSize.getWidth();
int targetHeight = targetSize.getHeight();
int scale = 1;
int widthScale = srcWidth / targetWidth;
int heightScale = srcHeight / targetHeight;
switch (viewScaleType) {
case FIT_INSIDE:
if (powerOf2Scale) {
while (srcWidth / 2 >= targetWidth || srcHeight / 2 >= targetHeight) { // ||
srcWidth /= 2;
srcHeight /= 2;
scale *= 2;
}
} else {
scale = Math.max(widthScale, heightScale); // max
}
break;
case CROP:
if (powerOf2Scale) {
while (srcWidth / 2 >= targetWidth && srcHeight / 2 >= targetHeight) { // &&
srcWidth /= 2;
srcHeight /= 2;
scale *= 2;
}
} else {
scale = Math.min(widthScale, heightScale); // min
}
break;
}
if (scale < 1) {
scale = 1;
}
return scale;
}
/**
* Computes scale of target size (targetSize) to source size (srcSize).
*
* Examples:
*
*
* srcSize(40x40), targetSize(10x10) -> scale = 0.25
*
* srcSize(10x10), targetSize(20x20), stretch = false -> scale = 1
* srcSize(10x10), targetSize(20x20), stretch = true -> scale = 2
*
* srcSize(100x100), targetSize(20x40), viewScaleType = FIT_INSIDE -> scale = 0.2
* srcSize(100x100), targetSize(20x40), viewScaleType = CROP -> scale = 0.4
*
*
* @param srcSize Source (image) size
* @param targetSize Target (view) size
* @param viewScaleType {@linkplain ViewScaleType Scale type} for placing image in view
* @param stretch Whether source size should be stretched if target size is larger than source size. If false
* then result scale value can't be greater than 1.
* @return Computed scale
*/
public static float computeImageScale(ImageSize srcSize, ImageSize targetSize, ViewScaleType viewScaleType, boolean stretch) {
int srcWidth = srcSize.getWidth();
int srcHeight = srcSize.getHeight();
int targetWidth = targetSize.getWidth();
int targetHeight = targetSize.getHeight();
float widthScale = (float) srcWidth / targetWidth;
float heightScale = (float) srcHeight / targetHeight;
int destWidth;
int destHeight;
if ((viewScaleType == ViewScaleType.FIT_INSIDE && widthScale >= heightScale) || (viewScaleType == ViewScaleType.CROP && widthScale < heightScale)) {
destWidth = targetWidth;
destHeight = (int) (srcHeight / widthScale);
} else {
destWidth = (int) (srcWidth / heightScale);
destHeight = targetHeight;
}
float scale = 1;
if ((!stretch && destWidth < srcWidth && destHeight < srcHeight) || (stretch && destWidth != srcWidth && destHeight != srcHeight)) {
scale = (float) destWidth / srcWidth;
}
return scale;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy