PageRenderTime 37ms CodeModel.GetById 12ms app.highlight 6ms RepoModel.GetById 18ms app.codeStats 0ms

/UniversalImageLoader/src/com/nostra13/universalimageloader/core/ImageDecoder.java

https://github.com/rashedulkabir/Android-Universal-Image-Loader
Java | 177 lines | 104 code | 15 blank | 58 comment | 10 complexity | 3daded2b9671a29be5d8fbfb95813f26 MD5 | raw file
  1package com.nostra13.universalimageloader.core;
  2
  3import java.io.IOException;
  4import java.io.InputStream;
  5import java.net.URI;
  6
  7import android.graphics.Bitmap;
  8import android.graphics.BitmapFactory;
  9import android.graphics.BitmapFactory.Options;
 10import android.graphics.Matrix;
 11import android.widget.ImageView.ScaleType;
 12
 13import com.nostra13.universalimageloader.core.assist.ImageScaleType;
 14import com.nostra13.universalimageloader.core.assist.ImageSize;
 15import com.nostra13.universalimageloader.core.download.ImageDownloader;
 16
 17/**
 18 * Decodes images to {@link Bitmap}
 19 * 
 20 * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
 21 * 
 22 * @see ImageScaleType
 23 * @see ImageDownloader
 24 */
 25class ImageDecoder {
 26
 27	private final URI imageUri;
 28	private final ImageDownloader imageDownloader;
 29
 30	/**
 31	 * @param imageUri
 32	 *            Image URI (<b>i.e.:</b> "http://site.com/image.png", "file:///mnt/sdcard/image.png")
 33	 * @param imageDownloader
 34	 *            Image downloader
 35	 * 
 36	 */
 37	ImageDecoder(URI imageUri, ImageDownloader imageDownloader) {
 38		this.imageUri = imageUri;
 39		this.imageDownloader = imageDownloader;
 40	}
 41
 42	/**
 43	 * Decodes image from URI into {@link Bitmap}. Image is scaled close to incoming {@link ImageSize image size} during
 44	 * decoding (depend on incoming image scale type).
 45	 * 
 46	 * @param targetSize
 47	 *            Image size to scale to during decoding
 48	 * @param scaleType
 49	 *            {@link ImageScaleType Image scale type}
 50	 * 
 51	 * @return Decoded bitmap
 52	 * @throws IOException
 53	 */
 54	public Bitmap decode(ImageSize targetSize, ImageScaleType scaleType) throws IOException {
 55		return decode(targetSize, scaleType, ScaleType.CENTER_INSIDE, null);
 56	}
 57
 58	/**
 59	 * Decodes image from URI into {@link Bitmap}. Image is scaled close to incoming {@link ImageSize image size} during
 60	 * decoding (depend on incoming image scale type).
 61	 * 
 62	 * @param targetSize
 63	 *            Image size to scale to during decoding
 64	 * @param scaleType
 65	 *            {@link ImageScaleType Image scale type}
 66	 * @param viewScaleType
 67	 *            {@link ScaleType ImageView scale type}
 68	 * 
 69	 * @return Decoded bitmap
 70	 * @throws IOException
 71	 */
 72	public Bitmap decode(ImageSize targetSize, ImageScaleType scaleType, ScaleType viewScaleType) throws IOException {
 73		return decode(targetSize, scaleType, viewScaleType, null);
 74	}
 75
 76	/**
 77	 * Decodes image from URI into {@link Bitmap}. Image is scaled close to incoming {@link ImageSize image size} during
 78	 * decoding (depend on incoming image scale type).
 79	 * 
 80	 * @param targetSize
 81	 *            Image size to scale to during decoding
 82	 * @param scaleType
 83	 *            {@link ImageScaleType Image scale type}
 84	 * @param viewScaleType
 85	 *            {@link ScaleType ImageView scale type}
 86	 * @param transformMatrix
 87	 *            Optional matrix to be applied to the decoded image pixels
 88	 * 
 89	 * @return Decoded bitmap
 90	 * @throws IOException
 91	 */
 92	public Bitmap decode(ImageSize targetSize, ImageScaleType scaleType, ScaleType viewScaleType, Matrix transformMatrix) throws IOException {
 93		Options decodeOptions = getBitmapOptionsForImageDecoding(targetSize, scaleType, viewScaleType);
 94		InputStream imageStream = imageDownloader.getStream(imageUri);
 95		try {
 96			Bitmap bmp = BitmapFactory.decodeStream(imageStream, null, decodeOptions);
 97			if (transformMatrix != null) {
 98				Bitmap transformedBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), transformMatrix, true);
 99				bmp.recycle();
100				bmp = transformedBmp;
101			}
102			return bmp;
103		} finally {
104			imageStream.close();
105		}
106	}
107
108	private Options getBitmapOptionsForImageDecoding(ImageSize targetSize, ImageScaleType scaleType, ScaleType viewScaleType) throws IOException {
109		Options options = new Options();
110		options.inSampleSize = computeImageScale(targetSize, scaleType, viewScaleType);
111		return options;
112	}
113
114	private int computeImageScale(ImageSize targetSize, ImageScaleType scaleType, ScaleType viewScaleType) throws IOException {
115		int targetWidth = targetSize.getWidth();
116		int targetHeight = targetSize.getHeight();
117
118		// decode image size
119		Options options = new Options();
120		options.inJustDecodeBounds = true;
121		InputStream imageStream = imageDownloader.getStream(imageUri);
122		try {
123			BitmapFactory.decodeStream(imageStream, null, options);
124		} finally {
125			imageStream.close();
126		}
127
128		int scale = 1;
129		int imageWidth = options.outWidth;
130		int imageHeight = options.outHeight;
131		int widthScale = imageWidth / targetWidth;
132		int heightScale = imageWidth / targetHeight;
133		switch (viewScaleType) {
134			case FIT_XY:
135			case FIT_START:
136			case FIT_END:
137			case CENTER_INSIDE:
138				switch (scaleType) {
139					default:
140					case POWER_OF_2:
141						while (imageWidth / 2 >= targetWidth || imageHeight / 2 >= targetHeight) { // ||
142							imageWidth /= 2;
143							imageHeight /= 2;
144							scale *= 2;
145						}
146						break;
147					case EXACT:
148						scale = Math.max(widthScale, heightScale); // max
149						break;
150				}
151				break;
152			case MATRIX:
153			case CENTER:
154			case CENTER_CROP:
155			default:
156				switch (scaleType) {
157					default:
158					case POWER_OF_2:
159						while (imageWidth / 2 >= targetWidth && imageHeight / 2 >= targetHeight) { // &&
160							imageWidth /= 2;
161							imageHeight /= 2;
162							scale *= 2;
163						}
164						break;
165					case EXACT:
166						scale = Math.min(widthScale, heightScale); // min
167						break;
168				}
169		}
170
171		if (scale < 1) {
172			scale = 1;
173		}
174
175		return scale;
176	}
177}