content: package org.android.share.utils;
  
  import android.content.res.Resources;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.graphics.Matrix;
  import android.graphics.drawable.BitmapDrawable;
  import android.graphics.drawable.Drawable;
  import android.os.Build;
  
  import java.io.ByteArrayOutputStream;
  
  /**
   * 方便使用bitmap的工具类，提供了bitmap转换，缩略等实用的方法.
   * @author Jack Tony
   * @date 2015/4/25
   * @see "http://www.cnblogs.com/tianzhijiexian/p/4273997.html"
   * @see "http://www.cnblogs.com/tianzhijiexian/p/4263897.html"
   */
  public class BitmapUtil {
  
      /**
       * Byte[]转Bitmap
       */
      public static Bitmap bytes2Bitmap(byte[] data) {
          return BitmapFactory.decodeByteArray(data, 0, data.length);
      }
  
      /**
       * Bitmap转Byte[]
       */
      public static byte[] bitmap2Bytes(Bitmap bitmap) {
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
          return baos.toByteArray();
      }
  
      /**
       * Bitmap转Drawable
       */
      public static Drawable bitmap2Drawable(Bitmap bitmap) {
          return new BitmapDrawable(bitmap);
      }
  
      /**
       * Drawable转Bitmap
       */
      public static Bitmap drawable2Bitmap(Drawable drawable) {
          BitmapDrawable bd = (BitmapDrawable) drawable;
          return bd.getBitmap();
      }
  
      /**
       * 旋转图像
       */
      public static Bitmap rotateBitmap(Bitmap bmp, int degrees) {
          if (degrees != 0) {
              Matrix matrix = new Matrix();
              matrix.postRotate(degrees);
              return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
          }
          return bmp;
      }
  
  
      /**
       * 得到bitmap的大小
       */
      public static int getBitmapSize(Bitmap bitmap) {
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {    //API 19
              return bitmap.getAllocationByteCount();
          }
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {//API 12
              return bitmap.getByteCount();
          }
          // 在低版本中用一行的字节x高度
          return bitmap.getRowBytes() * bitmap.getHeight();                //earlier version
      }
  
      private static int mDesiredWidth;
  
      private static int mDesiredHeight;
  
      /**
       * 从Resources中加载图片
       */
      public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
          BitmapFactory.Options options = new BitmapFactory.Options();
          // 设置成了true,不占用内存，只获取bitmap宽高
          options.inJustDecodeBounds = true;
          // 初始化options对象
          BitmapFactory.decodeResource(res, resId, options);
          // 得到计算好的options，目标宽、目标高
          options = getBestOptions(options, reqWidth, reqHeight);
          Bitmap src = BitmapFactory.decodeResource(res, resId, options); // 载入一个稍大的缩略图
          return createScaleBitmap(src, mDesiredWidth, mDesiredHeight); // 进一步得到目标大小的缩略图
      }
  
      /**
       * 从SD卡上加载图片
       */
      public static Bitmap decodeSampledBitmapFromFile(String pathName, int reqWidth, int reqHeight) {
          BitmapFactory.Options options = new BitmapFactory.Options();
          options.inJustDecodeBounds = true;
          BitmapFactory.decodeFile(pathName, options);
          options = getBestOptions(options, reqWidth, reqHeight);
          Bitmap src = BitmapFactory.decodeFile(pathName, options);
          return createScaleBitmap(src, mDesiredWidth, mDesiredHeight);
      }
  
      /**
       * 计算目标宽度，目标高度，inSampleSize
       *
       * @return BitmapFactory.Options对象
       */
      private static BitmapFactory.Options getBestOptions(BitmapFactory.Options options, int reqWidth, int reqHeight) {
          // 读取图片长宽
          int actualWidth = options.outWidth;
          int actualHeight = options.outHeight;
          // Then compute the dimensions we would ideally like to decode to.
          mDesiredWidth = getResizedDimension(reqWidth, reqHeight, actualWidth, actualHeight);
          mDesiredHeight = getResizedDimension(reqHeight, reqWidth, actualHeight, actualWidth);
          // 根据现在得到计算inSampleSize
          options.inSampleSize = calculateBestInSampleSize(actualWidth, actualHeight, mDesiredWidth, mDesiredHeight);
          // 使用获取到的inSampleSize值再次解析图片
          options.inJustDecodeBounds = false;
          return options;
      }
  
      /**
       * Scales one side of a rectangle to fit aspect ratio. 最终得到重新测量的尺寸
       *
       * @param maxPrimary      Maximum size of the primary dimension (i.e. width for max
       *                        width), or zero to maintain aspect ratio with secondary
       *                        dimension
       * @param maxSecondary    Maximum size of the secondary dimension, or zero to maintain
       *                        aspect ratio with primary dimension
       * @param actualPrimary   Actual size of the primary dimension
       * @param actualSecondary Actual size of the secondary dimension
       */
      private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, int actualSecondary) {
          double ratio = (double) actualSecondary / (double) actualPrimary;
          int resized = maxPrimary;
          if (resized * ratio > maxSecondary) {
              resized = (int) (maxSecondary / ratio);
          }
          return resized;
      }
  
      /**
       * Returns the largest power-of-two divisor for use in downscaling a bitmap
       * that will not result in the scaling past the desired dimensions.
       *
       * @param actualWidth   Actual width of the bitmap
       * @param actualHeight  Actual height of the bitmap
       * @param desiredWidth  Desired width of the bitmap
       * @param desiredHeight Desired height of the bitmap
       */
      // Visible for testing.
      private static int calculateBestInSampleSize(int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
          double wr = (double) actualWidth / desiredWidth;
          double hr = (double) actualHeight / desiredHeight;
          double ratio = Math.min(wr, hr);
          float inSampleSize = 1.0f;
          while ((inSampleSize * 2) <= ratio) {
              inSampleSize *= 2;
          }
  
          return (int) inSampleSize;
      }
  
      /**
       * 通过传入的bitmap，进行压缩，得到符合标准的bitmap
       */
      private static Bitmap createScaleBitmap(Bitmap tempBitmap, int desiredWidth, int desiredHeight) {
          // If necessary, scale down to the maximal acceptable size.
          if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth || tempBitmap.getHeight() > desiredHeight)) {
              // 如果是放大图片，filter决定是否平滑，如果是缩小图片，filter无影响
              Bitmap bitmap = Bitmap.createScaledBitmap(tempBitmap, desiredWidth, desiredHeight, true);
              tempBitmap.recycle(); // 释放Bitmap的native像素数组
              return bitmap;
          } else {
              return tempBitmap; // 如果没有缩放，那么不回收
          }
      }
  
  
  }
  