content: 
  package com.banrossyn.imageloader.utils;
  
  import android.graphics.BitmapFactory;
  import android.opengl.GLES10;
  
  import com.banrossyn.imageloader.core.assist.ImageSize;
  import com.banrossyn.imageloader.core.assist.ViewScaleType;
  import com.banrossyn.imageloader.core.imageaware.ImageAware;
  
  import javax.microedition.khronos.opengles.GL10;
  
  /**
   * Provides calculations with image sizes, scales
   *
   * @author rossyn (banrossyn[at]gmail[dot]com)
   * @since 1.8.3
   */
  public final class ImageSizeUtils {
  
      private static final int DEFAULT_MAX_BITMAP_DIMENSION = 2048;
  
      private static ImageSize maxBitmapSize;
  
      static {
          int[] maxTextureSize = new int[1];
          GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);
          int maxBitmapDimension = Math.max(maxTextureSize[0], DEFAULT_MAX_BITMAP_DIMENSION);
          maxBitmapSize = new ImageSize(maxBitmapDimension, maxBitmapDimension);
      }
  
      private ImageSizeUtils() {
      }
  
      /**
       * Defines target size for image aware view. Size is defined by target
       * {@link com.banrossyn.imageloader.core.imageaware.ImageAware view} parameters, configuration
       * parameters or device display dimensions.<br />
       */
      public static ImageSize defineTargetSizeForView(ImageAware imageAware, ImageSize maxImageSize) {
          int width = imageAware.getWidth();
          if (width <= 0) {
              width = maxImageSize.getWidth();
          } else {
              width = Math.min(width, maxImageSize.getWidth());
          }
  
          int height = imageAware.getHeight();
          if (height <= 0) {
              height = maxImageSize.getHeight();
          } else {
              height = Math.min(height, maxImageSize.getHeight());
          }
  
          return new ImageSize(width, height);
      }
  
      /**
       * Computes sample size for downscaling image size (<b>srcSize</b>) to view size (<b>targetSize</b>). This sample
       * size is used during
       * {@linkplain BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options)
       * decoding image} to bitmap.<br />
       * <br />
       * <b>Examples:</b><br />
       * <p/>
       * <pre>
       * 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
       * </pre>
       * <p/>
       * <br />
       * 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 <i>true</i> - 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) {
          final int srcWidth = srcSize.getWidth();
          final int srcHeight = srcSize.getHeight();
          final int targetWidth = targetSize.getWidth();
          final int targetHeight = targetSize.getHeight();
  
          int scale = 1;
  
          switch (viewScaleType) {
              case FIT_INSIDE:
                  if (powerOf2Scale) {
                      final int halfWidth = srcWidth / 2;
                      final int halfHeight = srcHeight / 2;
                      while ((halfWidth / scale) > targetWidth || (halfHeight / scale) > targetHeight) { // ||
                          scale *= 2;
                      }
                  } else {
                      scale = Math.max(srcWidth / targetWidth, srcHeight / targetHeight); // max
                  }
                  break;
              case CROP:
                  if (powerOf2Scale) {
                      final int halfWidth = srcWidth / 2;
                      final int halfHeight = srcHeight / 2;
                      while ((halfWidth / scale) > targetWidth && (halfHeight / scale) > targetHeight) { // &&
                          scale *= 2;
                      }
                  } else {
                      scale = Math.min(srcWidth / targetWidth, srcHeight / targetHeight); // min
                  }
                  break;
          }
  
          if (scale < 1) {
              scale = 1;
          }
          scale = considerMaxTextureSize(srcWidth, srcHeight, scale, powerOf2Scale);
  
          return scale;
      }
  
      private static int considerMaxTextureSize(int srcWidth, int srcHeight, int scale, boolean powerOf2) {
          final int maxWidth = maxBitmapSize.getWidth();
          final int maxHeight = maxBitmapSize.getHeight();
          while ((srcWidth / scale) > maxWidth || (srcHeight / scale) > maxHeight) {
              if (powerOf2) {
                  scale *= 2;
              } else {
                  scale++;
              }
          }
          return scale;
      }
  
      /**
       * Computes minimal sample size for downscaling image so result image size won't exceed max acceptable OpenGL
       * texture size.<br />
       * We can't create Bitmap in memory with size exceed max texture size (usually this is 2048x2048) so this method
       * calculate minimal sample size which should be applied to image to fit into these limits.
       *
       * @param srcSize Original image size
       * @return Minimal sample size
       */
      public static int computeMinImageSampleSize(ImageSize srcSize) {
          final int srcWidth = srcSize.getWidth();
          final int srcHeight = srcSize.getHeight();
          final int targetWidth = maxBitmapSize.getWidth();
          final int targetHeight = maxBitmapSize.getHeight();
  
          final int widthScale = (int) Math.ceil((float) srcWidth / targetWidth);
          final int heightScale = (int) Math.ceil((float) srcHeight / targetHeight);
  
          return Math.max(widthScale, heightScale); // max
      }
  
      /**
       * Computes scale of target size (<b>targetSize</b>) to source size (<b>srcSize</b>).<br />
       * <br />
       * <b>Examples:</b><br />
       * <p/>
       * <pre>
       * 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
       * </pre>
       *
       * @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 <b>false</b>
       *                      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) {
          final int srcWidth = srcSize.getWidth();
          final int srcHeight = srcSize.getHeight();
          final int targetWidth = targetSize.getWidth();
          final int targetHeight = targetSize.getHeight();
  
          final float widthScale = (float) srcWidth / targetWidth;
          final float heightScale = (float) srcHeight / targetHeight;
  
          final int destWidth;
          final 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;
      }
  }
  