content: /*
   *    Copyright (C) 2016 Amit Shekhar
   *    Copyright (C) 2011 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.glidebitmappool.internal;
  
  import android.annotation.TargetApi;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.os.Build;
  
  import java.util.ArrayDeque;
  import java.util.Queue;
  
  /**
   * Created by amitshekhar on 17/06/16.
   */
  public class Util {
  
      private Util() {
          // Utility class.
      }
  
      @TargetApi(Build.VERSION_CODES.KITKAT)
      public static int getBitmapByteSize(Bitmap bitmap) {
          // The return value of getAllocationByteCount silently changes for recycled bitmaps from the
          // internal buffer size to row bytes * height. To avoid random inconsistencies in caches, we
          // instead assert here.
          if (bitmap.isRecycled()) {
              throw new IllegalStateException("Cannot obtain size for recycled Bitmap: " + bitmap
                      + "[" + bitmap.getWidth() + "x" + bitmap.getHeight() + "] " + bitmap.getConfig());
          }
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
              // Workaround for KitKat initial release NPE in Bitmap, fixed in MR1. See issue #148.
              try {
                  return bitmap.getAllocationByteCount();
              } catch (NullPointerException e) {
                  // Do nothing.
              }
          }
          return bitmap.getHeight() * bitmap.getRowBytes();
      }
  
      public static int getBitmapByteSize(int width, int height, Bitmap.Config config) {
          return width * height * getBytesPerPixel(config);
      }
  
      private static int getBytesPerPixel(Bitmap.Config config) {
          // A bitmap by decoding a gif has null "config" in certain environments.
          if (config == null) {
              config = Bitmap.Config.ARGB_8888;
          }
  
          int bytesPerPixel;
          switch (config) {
              case ALPHA_8:
                  bytesPerPixel = 1;
                  break;
              case RGB_565:
              case ARGB_4444:
                  bytesPerPixel = 2;
                  break;
              case ARGB_8888:
              default:
                  bytesPerPixel = 4;
                  break;
          }
          return bytesPerPixel;
      }
  
      public static <T> Queue<T> createQueue(int size) {
          return new ArrayDeque<>(size);
      }
  
      public static boolean bothNullOrEqual(Object a, Object b) {
          return a == null ? b == null : a.equals(b);
      }
  
      public static boolean canUseForInBitmap(
              Bitmap candidate, BitmapFactory.Options targetOptions) {
  
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
              // From Android 4.4 (KitKat) onward we can re-use if the byte size of
              // the new bitmap is smaller than the reusable bitmap candidate
              // allocation byte count.
              int width = targetOptions.outWidth / targetOptions.inSampleSize;
              int height = targetOptions.outHeight / targetOptions.inSampleSize;
              int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
  
              try {
                  return byteCount <= candidate.getAllocationByteCount();
              } catch (NullPointerException e) {
                  return byteCount <= candidate.getHeight() * candidate.getRowBytes();
              }
          }
          // On earlier versions, the dimensions must match exactly and the inSampleSize must be 1
          return candidate.getWidth() == targetOptions.outWidth
                  && candidate.getHeight() == targetOptions.outHeight
                  && targetOptions.inSampleSize == 1;
      }
  
  
      public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
          // Raw height and width of image
          final int height = options.outHeight;
          final int width = options.outWidth;
          int inSampleSize = 1;
  
          if (height > reqHeight || width > reqWidth) {
  
              final int halfHeight = height / 2;
              final int halfWidth = width / 2;
  
              // Calculate the largest inSampleSize value that is a power of 2 and keeps both
              // height and width larger than the requested height and width.
              while ((halfHeight / inSampleSize) > reqHeight
                      && (halfWidth / inSampleSize) > reqWidth) {
                  inSampleSize *= 2;
              }
          }
  
          return inSampleSize;
      }
  
  }
  