Android Open Source - Android-Universal-Image-Loader Base Image Decoder






From Project

Back to project page Android-Universal-Image-Loader.

License

The source code is released under:

Apache License

If you think the Android project Android-Universal-Image-Loader listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*******************************************************************************
 * Copyright 2011-2014 Sergey Tarasevich
 *//from w  ww.j  a  v a 2 s  . c  om
 * 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.core.decode;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Matrix;
import android.media.ExifInterface;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.nostra13.universalimageloader.core.download.ImageDownloader.Scheme;
import com.nostra13.universalimageloader.utils.ImageSizeUtils;
import com.nostra13.universalimageloader.utils.IoUtils;
import com.nostra13.universalimageloader.utils.L;

import java.io.IOException;
import java.io.InputStream;

/**
 * Decodes images to {@link Bitmap}, scales them to needed size
 *
 * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
 * @see ImageDecodingInfo
 * @since 1.8.3
 */
public class BaseImageDecoder implements ImageDecoder {

  protected static final String LOG_SUBSAMPLE_IMAGE = "Subsample original image (%1$s) to %2$s (scale = %3$d) [%4$s]";
  protected static final String LOG_SCALE_IMAGE = "Scale subsampled image (%1$s) to %2$s (scale = %3$.5f) [%4$s]";
  protected static final String LOG_ROTATE_IMAGE = "Rotate image on %1$d\u00B0 [%2$s]";
  protected static final String LOG_FLIP_IMAGE = "Flip image horizontally [%s]";
  protected static final String ERROR_NO_IMAGE_STREAM = "No stream for image [%s]";
  protected static final String ERROR_CANT_DECODE_IMAGE = "Image can't be decoded [%s]";

  protected final boolean loggingEnabled;

  /**
   * @param loggingEnabled Whether debug logs will be written to LogCat. Usually should match {@link
   *                       com.nostra13.universalimageloader.core.ImageLoaderConfiguration.Builder#writeDebugLogs()
   *                       ImageLoaderConfiguration.writeDebugLogs()}
   */
  public BaseImageDecoder(boolean loggingEnabled) {
    this.loggingEnabled = loggingEnabled;
  }

  /**
   * Decodes image from URI into {@link Bitmap}. Image is scaled close to incoming {@linkplain ImageSize target size}
   * during decoding (depend on incoming parameters).
   *
   * @param decodingInfo Needed data for decoding image
   * @return Decoded bitmap
   * @throws IOException                   if some I/O exception occurs during image reading
   * @throws UnsupportedOperationException if image URI has unsupported scheme(protocol)
   */
  @Override
  public Bitmap decode(ImageDecodingInfo decodingInfo) throws IOException {
    Bitmap decodedBitmap;
    ImageFileInfo imageInfo;

    InputStream imageStream = getImageStream(decodingInfo);
    if (imageStream == null) {
      L.e(ERROR_NO_IMAGE_STREAM, decodingInfo.getImageKey());
      return null;
    }
    try {
      imageInfo = defineImageSizeAndRotation(imageStream, decodingInfo);
      imageStream = resetStream(imageStream, decodingInfo);
      Options decodingOptions = prepareDecodingOptions(imageInfo.imageSize, decodingInfo);
      decodedBitmap = BitmapFactory.decodeStream(imageStream, null, decodingOptions);
    } finally {
      IoUtils.closeSilently(imageStream);
    }

    if (decodedBitmap == null) {
      L.e(ERROR_CANT_DECODE_IMAGE, decodingInfo.getImageKey());
    } else {
      decodedBitmap = considerExactScaleAndOrientatiton(decodedBitmap, decodingInfo, imageInfo.exif.rotation,
          imageInfo.exif.flipHorizontal);
    }
    return decodedBitmap;
  }

  protected InputStream getImageStream(ImageDecodingInfo decodingInfo) throws IOException {
    return decodingInfo.getDownloader().getStream(decodingInfo.getImageUri(), decodingInfo.getExtraForDownloader());
  }

  protected ImageFileInfo defineImageSizeAndRotation(InputStream imageStream, ImageDecodingInfo decodingInfo)
      throws IOException {
    Options options = new Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(imageStream, null, options);

    ExifInfo exif;
    String imageUri = decodingInfo.getImageUri();
    if (decodingInfo.shouldConsiderExifParams() && canDefineExifParams(imageUri, options.outMimeType)) {
      exif = defineExifOrientation(imageUri);
    } else {
      exif = new ExifInfo();
    }
    return new ImageFileInfo(new ImageSize(options.outWidth, options.outHeight, exif.rotation), exif);
  }

  private boolean canDefineExifParams(String imageUri, String mimeType) {
    return "image/jpeg".equalsIgnoreCase(mimeType) && (Scheme.ofUri(imageUri) == Scheme.FILE);
  }

  protected ExifInfo defineExifOrientation(String imageUri) {
    int rotation = 0;
    boolean flip = false;
    try {
      ExifInterface exif = new ExifInterface(Scheme.FILE.crop(imageUri));
      int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
      switch (exifOrientation) {
        case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
          flip = true;
        case ExifInterface.ORIENTATION_NORMAL:
          rotation = 0;
          break;
        case ExifInterface.ORIENTATION_TRANSVERSE:
          flip = true;
        case ExifInterface.ORIENTATION_ROTATE_90:
          rotation = 90;
          break;
        case ExifInterface.ORIENTATION_FLIP_VERTICAL:
          flip = true;
        case ExifInterface.ORIENTATION_ROTATE_180:
          rotation = 180;
          break;
        case ExifInterface.ORIENTATION_TRANSPOSE:
          flip = true;
        case ExifInterface.ORIENTATION_ROTATE_270:
          rotation = 270;
          break;
      }
    } catch (IOException e) {
      L.w("Can't read EXIF tags from file [%s]", imageUri);
    }
    return new ExifInfo(rotation, flip);
  }

  protected Options prepareDecodingOptions(ImageSize imageSize, ImageDecodingInfo decodingInfo) {
    ImageScaleType scaleType = decodingInfo.getImageScaleType();
    int scale;
    if (scaleType == ImageScaleType.NONE) {
      scale = 1;
    } else if (scaleType == ImageScaleType.NONE_SAFE) {
      scale = ImageSizeUtils.computeMinImageSampleSize(imageSize);
    } else {
      ImageSize targetSize = decodingInfo.getTargetSize();
      boolean powerOf2 = scaleType == ImageScaleType.IN_SAMPLE_POWER_OF_2;
      scale = ImageSizeUtils.computeImageSampleSize(imageSize, targetSize, decodingInfo.getViewScaleType(), powerOf2);
    }
    if (scale > 1 && loggingEnabled) {
      L.d(LOG_SUBSAMPLE_IMAGE, imageSize, imageSize.scaleDown(scale), scale, decodingInfo.getImageKey());
    }

    Options decodingOptions = decodingInfo.getDecodingOptions();
    decodingOptions.inSampleSize = scale;
    return decodingOptions;
  }

  protected InputStream resetStream(InputStream imageStream, ImageDecodingInfo decodingInfo) throws IOException {
    try {
      imageStream.reset();
    } catch (IOException e) {
      IoUtils.closeSilently(imageStream);
      imageStream = getImageStream(decodingInfo);
    }
    return imageStream;
  }

  protected Bitmap considerExactScaleAndOrientatiton(Bitmap subsampledBitmap, ImageDecodingInfo decodingInfo,
      int rotation, boolean flipHorizontal) {
    Matrix m = new Matrix();
    // Scale to exact size if need
    ImageScaleType scaleType = decodingInfo.getImageScaleType();
    if (scaleType == ImageScaleType.EXACTLY || scaleType == ImageScaleType.EXACTLY_STRETCHED) {
      ImageSize srcSize = new ImageSize(subsampledBitmap.getWidth(), subsampledBitmap.getHeight(), rotation);
      float scale = ImageSizeUtils.computeImageScale(srcSize, decodingInfo.getTargetSize(), decodingInfo
          .getViewScaleType(), scaleType == ImageScaleType.EXACTLY_STRETCHED);
      if (Float.compare(scale, 1f) != 0) {
        m.setScale(scale, scale);

        if (loggingEnabled) {
          L.d(LOG_SCALE_IMAGE, srcSize, srcSize.scale(scale), scale, decodingInfo.getImageKey());
        }
      }
    }
    // Flip bitmap if need
    if (flipHorizontal) {
      m.postScale(-1, 1);

      if (loggingEnabled) L.d(LOG_FLIP_IMAGE, decodingInfo.getImageKey());
    }
    // Rotate bitmap if need
    if (rotation != 0) {
      m.postRotate(rotation);

      if (loggingEnabled) L.d(LOG_ROTATE_IMAGE, rotation, decodingInfo.getImageKey());
    }

    Bitmap finalBitmap = Bitmap.createBitmap(subsampledBitmap, 0, 0, subsampledBitmap.getWidth(), subsampledBitmap
        .getHeight(), m, true);
    if (finalBitmap != subsampledBitmap) {
      subsampledBitmap.recycle();
    }
    return finalBitmap;
  }

  protected static class ExifInfo {

    public final int rotation;
    public final boolean flipHorizontal;

    protected ExifInfo() {
      this.rotation = 0;
      this.flipHorizontal = false;
    }

    protected ExifInfo(int rotation, boolean flipHorizontal) {
      this.rotation = rotation;
      this.flipHorizontal = flipHorizontal;
    }
  }

  protected static class ImageFileInfo {

    public final ImageSize imageSize;
    public final ExifInfo exif;

    protected ImageFileInfo(ImageSize imageSize, ExifInfo exif) {
      this.imageSize = imageSize;
      this.exif = exif;
    }
  }
}




Java Source Code List

com.nostra13.universalimageloader.cache.disc.DiskCache.java
com.nostra13.universalimageloader.cache.disc.impl.BaseDiskCache.java
com.nostra13.universalimageloader.cache.disc.impl.LimitedAgeDiskCache.java
com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache.java
com.nostra13.universalimageloader.cache.disc.impl.ext.DiskLruCache.java
com.nostra13.universalimageloader.cache.disc.impl.ext.LruDiskCache.java
com.nostra13.universalimageloader.cache.disc.impl.ext.StrictLineReader.java
com.nostra13.universalimageloader.cache.disc.impl.ext.Util.java
com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator.java
com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator.java
com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator.java
com.nostra13.universalimageloader.cache.memory.BaseMemoryCache.java
com.nostra13.universalimageloader.cache.memory.LimitedMemoryCache.java
com.nostra13.universalimageloader.cache.memory.MemoryCache.java
com.nostra13.universalimageloader.cache.memory.impl.FIFOLimitedMemoryCache.java
com.nostra13.universalimageloader.cache.memory.impl.FuzzyKeyMemoryCache.java
com.nostra13.universalimageloader.cache.memory.impl.LRULimitedMemoryCache.java
com.nostra13.universalimageloader.cache.memory.impl.LargestLimitedMemoryCache.java
com.nostra13.universalimageloader.cache.memory.impl.LimitedAgeMemoryCache.java
com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache.java
com.nostra13.universalimageloader.cache.memory.impl.UsingFreqLimitedMemoryCache.java
com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache.java
com.nostra13.universalimageloader.core.DefaultConfigurationFactory.java
com.nostra13.universalimageloader.core.DisplayBitmapTask.java
com.nostra13.universalimageloader.core.DisplayImageOptions.java
com.nostra13.universalimageloader.core.ImageLoaderConfiguration.java
com.nostra13.universalimageloader.core.ImageLoaderEngine.java
com.nostra13.universalimageloader.core.ImageLoader.java
com.nostra13.universalimageloader.core.ImageLoadingInfo.java
com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.java
com.nostra13.universalimageloader.core.ProcessAndDisplayImageTask.java
com.nostra13.universalimageloader.core.assist.ContentLengthInputStream.java
com.nostra13.universalimageloader.core.assist.FailReason.java
com.nostra13.universalimageloader.core.assist.FlushedInputStream.java
com.nostra13.universalimageloader.core.assist.ImageScaleType.java
com.nostra13.universalimageloader.core.assist.ImageSize.java
com.nostra13.universalimageloader.core.assist.LoadedFrom.java
com.nostra13.universalimageloader.core.assist.QueueProcessingType.java
com.nostra13.universalimageloader.core.assist.ViewScaleType.java
com.nostra13.universalimageloader.core.assist.deque.BlockingDeque.java
com.nostra13.universalimageloader.core.assist.deque.Deque.java
com.nostra13.universalimageloader.core.assist.deque.LIFOLinkedBlockingDeque.java
com.nostra13.universalimageloader.core.assist.deque.LinkedBlockingDeque.java
com.nostra13.universalimageloader.core.decode.BaseImageDecoder.java
com.nostra13.universalimageloader.core.decode.ImageDecoder.java
com.nostra13.universalimageloader.core.decode.ImageDecodingInfo.java
com.nostra13.universalimageloader.core.display.BitmapDisplayer.java
com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer.java
com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer.java
com.nostra13.universalimageloader.core.display.RoundedVignetteBitmapDisplayer.java
com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer.java
com.nostra13.universalimageloader.core.download.BaseImageDownloader.java
com.nostra13.universalimageloader.core.download.ImageDownloader.java
com.nostra13.universalimageloader.core.imageaware.ImageAware.java
com.nostra13.universalimageloader.core.imageaware.ImageViewAware.java
com.nostra13.universalimageloader.core.imageaware.NonViewAware.java
com.nostra13.universalimageloader.core.imageaware.ViewAware.java
com.nostra13.universalimageloader.core.listener.ImageLoadingListener.java
com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener.java
com.nostra13.universalimageloader.core.listener.PauseOnScrollListener.java
com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener.java
com.nostra13.universalimageloader.core.process.BitmapProcessor.java
com.nostra13.universalimageloader.sample.Constants.java
com.nostra13.universalimageloader.sample.UILApplication.java
com.nostra13.universalimageloader.sample.activity.ComplexImageActivity.java
com.nostra13.universalimageloader.sample.activity.HomeActivity.java
com.nostra13.universalimageloader.sample.activity.SimpleImageActivity.java
com.nostra13.universalimageloader.sample.fragment.AbsListViewBaseFragment.java
com.nostra13.universalimageloader.sample.fragment.BaseFragment.java
com.nostra13.universalimageloader.sample.fragment.ImageGalleryFragment.java
com.nostra13.universalimageloader.sample.fragment.ImageGridFragment.java
com.nostra13.universalimageloader.sample.fragment.ImageListFragment.java
com.nostra13.universalimageloader.sample.fragment.ImagePagerFragment.java
com.nostra13.universalimageloader.sample.widget.UILWidgetProvider.java
com.nostra13.universalimageloader.utils.DiskCacheUtils.java
com.nostra13.universalimageloader.utils.ImageSizeUtils.java
com.nostra13.universalimageloader.utils.IoUtils.java
com.nostra13.universalimageloader.utils.L.java
com.nostra13.universalimageloader.utils.MemoryCacheUtils.java
com.nostra13.universalimageloader.utils.StorageUtils.java