最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android開發(fā)之超強圖片工具類BitmapUtil完整實例

 更新時間:2017年11月13日 09:01:47   作者:LovooGod  
這篇文章主要介紹了Android開發(fā)之超強圖片工具類BitmapUtil,結合完整實例形式分析了Android圖片的常用操作技巧,包括圖片的加載、轉換、縮放、計算等相關操作技巧,需要的朋友可以參考下

本文實例講述了Android開發(fā)之超強圖片工具類BitmapUtil。分享給大家供大家參考,具體如下:

說明:為了方便大家使用,本人把大家常用的圖片處理代碼集中到這個類里

使用了LruCache與SoftReference

/**
 * 圖片加載及轉化工具 ----------------------------------------------------------------------- 延伸:一個Bitmap到底占用多大內存?系統(tǒng)給每個應用程序分配多大內存? Bitmap占用的內存為:像素總數
 * * 每個像素占用的內存。在Android中, Bitmap有四種像素類型:ARGB_8888、ARGB_4444、ARGB_565、ALPHA_8, 他們每個像素占用的字節(jié)數分別為4、2、2、1。因此,一個2000*1000的ARGB_8888
 * 類型的Bitmap占用的內存為2000*1000*4=8000000B=8MB。
 * 
 * @author chen.lin
 *
 */
public class BitmapUtil {
 /**
  * 1)軟引用 ,已經不適合緩存圖片信息,加載圖片時會出現重疊的現象
  * 2)Android 3.0 (API Level 11)中,圖片的數據會存儲在本地的內存當中
  * 因而無法用一種可預見的方式將其釋放,這就有潛在的風險造成應用程序的內存溢出并崩潰,
  * 3)因為從 Android 2.3 (API Level 9)開始,垃圾回收器會更傾向于回收持有軟引用或弱引用的對象,
   這讓軟引用和弱引用變得不再可靠。
  * 
  */
 private static Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();
 /**
  * 初始化lrucache,最少使用最先移除,LruCache來緩存圖片,
  * 當存儲Image的大小大于LruCache設定的值,系統(tǒng)自動釋放內存,
  */
 private static LruCache<String, Bitmap> mMemoryCache;
 static {
  final int memory = (int) (Runtime.getRuntime().maxMemory() / 1024);
  final int cacheSize = memory / 8;
  mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
   protected int sizeOf(String key, Bitmap value) {
    // return value.getByteCount() / 1024;
    return value.getHeight() * value.getRowBytes();
   }
  };
 }
 // ---lrucache----------------------------------------------------
 /**
  * 添加圖片到lrucache
  * 
  * @param key
  * @param bitmap
  */
 public synchronized void addBitmapToMemCache(String key, Bitmap bitmap) {
  if (getBitmapFromMemCache(key) == null) {
   if (key != null & bitmap != null) {
    mMemoryCache.put(key, bitmap);
   }
  }
 }
 /**
  * 清除緩存
  */
 public void clearMemCache() {
  if (mMemoryCache != null) {
   if (mMemoryCache.size() > 0) {
    mMemoryCache.evictAll();
   }
   mMemoryCache = null;
  }
 }
 /**
  * 移除緩存
  */
 public synchronized void removeMemCache(String key) {
  if (key != null) {
   if (mMemoryCache != null) {
    Bitmap bm = mMemoryCache.remove(key);
    if (bm != null)
     bm.recycle();
   }
  }
 }
 /**
  * 從lrucache里讀取圖片
  * 
  * @param key
  * @return
  */
 public Bitmap getBitmapFromMemCache(String key) {
  if (key != null) {
   return mMemoryCache.get(key);
  }
  return null;
 }
 /**
  * 加載圖片
  * 
  * @param context
  * @param resId
  * @param imageView
  */
 public void loadBitmap(Context context, int resId, ImageView imageView) {
  final String imageKey = String.valueOf(resId);
  final Bitmap bitmap = getBitmapFromMemCache(imageKey);
  if (bitmap != null) {
   imageView.setImageBitmap(bitmap);
  } else {
   imageView.setImageResource(resId);
   BitmapWorkerTask task = new BitmapWorkerTask(context);
   task.execute(resId);
  }
 }
 /**
  * 任務類
  * 
  * @Project App_View
  * @Package com.android.view.tool
  * @author chenlin
  * @version 1.0
  * @Date 2014年5月10日
  */
 class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
  private Context mContext;
  public BitmapWorkerTask(Context context) {
   mContext = context;
  }
  // 在后臺加載圖片。
  @Override
  protected Bitmap doInBackground(Integer... params) {
   final Bitmap bitmap = decodeSampledBitmapFromResource(mContext.getResources(), params[0], 100, 100);
   addBitmapToMemCache(String.valueOf(params[0]), bitmap);
   return bitmap;
  }
 }
 // --軟引用---------------------------------------------------------
 public static void addBitmapToCache(String path) {
  // 強引用的Bitmap對象
  Bitmap bitmap = BitmapFactory.decodeFile(path);
  // 軟引用的Bitmap對象
  SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);
  // 添加該對象到Map中使其緩存
  imageCache.put(path, softBitmap);
 }
 public static Bitmap getBitmapByPath(String path) {
  // 從緩存中取軟引用的Bitmap對象
  SoftReference<Bitmap> softBitmap = imageCache.get(path);
  // 判斷是否存在軟引用
  if (softBitmap == null) {
   return null;
  }
  // 取出Bitmap對象,如果由于內存不足Bitmap被回收,將取得空
  Bitmap bitmap = softBitmap.get();
  return bitmap;
 }
 public Bitmap loadBitmap(final String imageUrl, final ImageCallBack imageCallBack) {
  SoftReference<Bitmap> reference = imageCache.get(imageUrl);
  if (reference != null) {
   if (reference.get() != null) {
    return reference.get();
   }
  }
  final Handler handler = new Handler() {
   public void handleMessage(final android.os.Message msg) {
    // 加入到緩存中
    Bitmap bitmap = (Bitmap) msg.obj;
    imageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));
    if (imageCallBack != null) {
     imageCallBack.getBitmap(bitmap);
    }
   }
  };
  new Thread() {
   public void run() {
    Message message = handler.obtainMessage();
    message.obj = downloadBitmap(imageUrl);
    handler.sendMessage(message);
   }
  }.start();
  return null;
 }
 public interface ImageCallBack {
  void getBitmap(Bitmap bitmap);
 }
 // ----其它工具----------------------------------------------------------------------------------
 /**
  * 從網上下載圖片
  * 
  * @param imageUrl
  * @return
  */
 private Bitmap downloadBitmap(String imageUrl) {
  Bitmap bitmap = null;
  try {
   bitmap = BitmapFactory.decodeStream(new URL(imageUrl).openStream());
   return bitmap;
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }
 /**
  * drawable 轉bitmap
  * 
  * @param drawable
  * @return
  */
 public static Bitmap drawable2Bitmap(Drawable drawable) {
  Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
    drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
  Canvas canvas = new Canvas(bitmap);
  // canvas.setBitmap(bitmap);
  drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
  drawable.draw(canvas);
  return bitmap;
 }
 /**
  * bitmap 轉 drawable
  * 
  * @param bm
  * @return
  */
 public static Drawable bitmap2Drable(Bitmap bm) {
  return new BitmapDrawable(bm);
 }
 /**
  * 把字節(jié)數組通過BASE64Encoder轉換成字符串
  * 
  * @param image
  * @return
  */
 public static String getBase64(byte[] image) {
  String string = "";
  try {
   BASE64Encoder encoder = new BASE64Encoder();
   string = encoder.encodeBuffer(image).trim();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return string;
 }
 /**
  * 把字節(jié)數據轉換成Drawable
  * 
  * @param imgByte
  *   字節(jié)數據
  * @return
  */
 @SuppressWarnings("deprecation")
 public static Drawable byte2Drawable(byte[] imgByte) {
  Bitmap bitmap;
  if (imgByte != null) {
   bitmap = BitmapFactory.decodeByteArray(imgByte, 0, imgByte.length);
   Drawable drawable = new BitmapDrawable(bitmap);
   return drawable;
  }
  return null;
 }
 /**
  * 把圖片轉換成字節(jié)數組
  * 
  * @param bmp
  * @return
  */
 public static byte[] bitmap2Byte(Bitmap bm) {
  Bitmap outBitmap = Bitmap.createScaledBitmap(bm, 150, bm.getHeight() * 150 / bm.getWidth(), true);
  if (bm != outBitmap) {
   bm.recycle();
   bm = null;
  }
  byte[] compressData = null;
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  try {
   try {
    outBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
   } catch (Exception e) {
    e.printStackTrace();
   }
   compressData = baos.toByteArray();
   baos.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
  return compressData;
 }
 /**
  * 縮放圖片
  * 
  * @param bitmap
  *   原圖片
  * @param newWidth
  * @param newHeight
  * @return
  */
 public static Bitmap setBitmapSize(Bitmap bitmap, int newWidth, int newHeight) {
  int width = bitmap.getWidth();
  int height = bitmap.getHeight();
  float scaleWidth = (newWidth * 1.0f) / width;
  float scaleHeight = (newHeight * 1.0f) / height;
  Matrix matrix = new Matrix();
  matrix.postScale(scaleWidth, scaleHeight);
  return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
 }
 /**
  * 縮放圖片
  * 
  * @param bitmapPath
  *   圖片路徑
  * @return
  */
 public static Bitmap setBitmapSize(String bitmapPath, float newWidth, float newHeight) {
  Bitmap bitmap = BitmapFactory.decodeFile(bitmapPath);
  if (bitmap == null) {
   Logger.i("bitmap", "bitmap------------>發(fā)生未知異常!");
   return null;
  }
  int width = bitmap.getWidth();
  int height = bitmap.getHeight();
  float scaleWidth = newWidth / width;
  float scaleHeight = newHeight / height;
  Matrix matrix = new Matrix();
  matrix.postScale(scaleWidth, scaleHeight);
  return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
 }
 /**
  * 計算圖片的縮放大小 如果==1,表示沒變化,==2,表示寬高都縮小一倍 ----------------------------------------------------------------------------
  * inSampleSize是BitmapFactory.Options類的一個參數,該參數為int型, 他的值指示了在解析圖片為Bitmap時在長寬兩個方向上像素縮小的倍數。inSampleSize的默認值和最小值為1(當小于1時,解碼器將該值當做1來處理),
  * 且在大于1時,該值只能為2的冪(當不為2的冪時,解碼器會取與該值最接近的2的冪)。 例如,當inSampleSize為2時,一個2000*1000的圖片,將被縮小為1000*500,相應地, 它的像素數和內存占用都被縮小為了原來的1/4:
  * 
  * @param options
  * @param reqWidth
  * @param reqHeight
  * @return
  */
 public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
  // 原始圖片的寬高
  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;
   // 在保證解析出的bitmap寬高分別大于目標尺寸寬高的前提下,取可能的inSampleSize的最大值
   while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
    inSampleSize *= 2;
   }
  }
  return inSampleSize;
 }
 /**
  * 根據計算出的inSampleSize生成Bitmap(此時的bitmap是經過縮放的圖片)
  * 
  * @param res
  * @param resId
  * @param reqWidth
  * @param reqHeight
  * @return
  */
 public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
  // 首先設置 inJustDecodeBounds=true 來獲取圖片尺寸
  final BitmapFactory.Options options = new BitmapFactory.Options();
  /**
   * inJustDecodeBounds屬性設置為true,decodeResource()方法就不會生成Bitmap對象,而僅僅是讀取該圖片的尺寸和類型信息:
   */
  options.inJustDecodeBounds = true;
  BitmapFactory.decodeResource(res, resId, options);
  // 計算 inSampleSize 的值
  options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
  // 根據計算出的 inSampleSize 來解碼圖片生成Bitmap
  options.inJustDecodeBounds = false;
  return BitmapFactory.decodeResource(res, resId, options);
 }
 /**
  * 將圖片保存到本地時進行壓縮, 即將圖片從Bitmap形式變?yōu)镕ile形式時進行壓縮, 
  * 特點是: File形式的圖片確實被壓縮了, 但是當你重新讀取壓縮后的file為 Bitmap是,它占用的內存并沒有改變
  * 
  * @param bmp
  * @param file
  */
 public static void compressBmpToFile(Bitmap bmp, File file) {
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  int options = 80;// 個人喜歡從80開始,
  bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
  while (baos.toByteArray().length / 1024 > 100) {
   baos.reset();
   options -= 10;
   bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
  }
  try {
   FileOutputStream fos = new FileOutputStream(file);
   fos.write(baos.toByteArray());
   fos.flush();
   fos.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 /**
  * 將圖片從本地讀到內存時,進行壓縮 ,即圖片從File形式變?yōu)锽itmap形式
  * 特點: 通過設置采樣率, 減少圖片的像素, 達到對內存中的Bitmap進行壓縮
  * @param srcPath
  * @return
  */
 public static Bitmap compressImageFromFile(String srcPath, float pixWidth, float pixHeight) {
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;// 只讀邊,不讀內容
  Bitmap bitmap = BitmapFactory.decodeFile(srcPath, options);
  options.inJustDecodeBounds = false;
  int w = options.outWidth;
  int h = options.outHeight;
  int scale = 1;
  if (w > h && w > pixWidth) {
   scale = (int) (options.outWidth / pixWidth);
  } else if (w < h && h > pixHeight) {
   scale = (int) (options.outHeight / pixHeight);
  }
  if (scale <= 0)
   scale = 1;
  options.inSampleSize = scale;// 設置采樣率
  options.inPreferredConfig = Config.ARGB_8888;// 該模式是默認的,可不設
  options.inPurgeable = true;// 同時設置才會有效
  options.inInputShareable = true;// 。當系統(tǒng)內存不夠時候圖片自動被回收
  bitmap = BitmapFactory.decodeFile(srcPath, options);
  // return compressBmpFromBmp(bitmap);//原來的方法調用了這個方法企圖進行二次壓縮
  // 其實是無效的,大家盡管嘗試
  return bitmap;
 }
 /**
  * 判斷照片的角度
  * @param path
  * @return
  */
 public static int readPictureDegree(String path) { 
  int degree = 0; 
  try { 
   ExifInterface exifInterface = new ExifInterface(path); 
   int orientation = exifInterface.getAttributeInt( 
     ExifInterface.TAG_ORIENTATION, 
     ExifInterface.ORIENTATION_NORMAL); 
   switch (orientation) { 
   case ExifInterface.ORIENTATION_ROTATE_90: 
    degree = 90; 
    break; 
   case ExifInterface.ORIENTATION_ROTATE_180: 
    degree = 180; 
    break; 
   case ExifInterface.ORIENTATION_ROTATE_270: 
    degree = 270; 
    break; 
   } 
  } catch (IOException e) { 
   e.printStackTrace(); 
  } 
  return degree; 
 } 
 /**
  * Android根據設備屏幕尺寸和dpi的不同,給系統(tǒng)分配的單應用程序內存大小也不同,具體如下表
  * 
  * 屏幕尺寸 DPI 應用內存 
  * small / normal / large ldpi / mdpi 16MB 
  * small / normal / large tvdpi / hdpi 32MB 
  * small / normal / large xhdpi 64MB
  * small / normal / large 400dpi 96MB 
  * small / normal / large xxhdpi 128MB 
  * ------------------------------------------------------- 
  * xlarge mdpi 32MB 
  * xlarge tvdpi / hdpi 64MB 
  * xlarge xhdpi 128MB 
  * xlarge 400dpi 192MB 
  * xlarge xxhdpi 256MB
  */
}

更多關于Android相關內容感興趣的讀者可查看本站專題:《Android圖形與圖像處理技巧總結》、《Android開發(fā)入門與進階教程》、《Android調試技巧與常見問題解決方法匯總》、《Android基本組件用法總結》、《Android視圖View技巧總結》、《Android布局layout技巧總結》及《Android控件用法總結

希望本文所述對大家Android程序設計有所幫助。

相關文章

  • Android利用傳感器實現微信搖一搖功能

    Android利用傳感器實現微信搖一搖功能

    這篇文章主要為大家詳細介紹了Android利用傳感器實現微信搖一搖功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android CheckBox中設置padding無效解決辦法

    Android CheckBox中設置padding無效解決辦法

    這篇文章主要介紹了Android CheckBox中設置padding無效解決辦法的相關資料,希望通過本文能幫助到大家,讓大家解決這樣類似的問題,需要的朋友可以參考下
    2017-10-10
  • Android無障礙監(jiān)聽通知的實戰(zhàn)過程

    Android無障礙監(jiān)聽通知的實戰(zhàn)過程

    開發(fā)微動手勢的時候,做了一個通知觸發(fā)的功能,就是在收到某個預設的通知的時候,自動觸發(fā)某個動作,因此需要監(jiān)聽通知消息,這篇文章主要給大家介紹了關于Android無障礙監(jiān)聽通知的相關資料,需要的朋友可以參考下
    2022-07-07
  • Android中 動態(tài)改變對話框值的方法

    Android中 動態(tài)改變對話框值的方法

    Android Dev-Guide 推薦重寫Activity.onCreateDialog()方法來創(chuàng)建Dialog,這樣Dialog就歸屬于這個Activity了。
    2013-04-04
  • ijkPlayer播放器的全自動編譯腳本及最終編譯包

    ijkPlayer播放器的全自動編譯腳本及最終編譯包

    這篇文章主要介紹了ijkPlayer播放器的全自動編譯腳本及最終編譯包,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • MVVMLight項目的綁定及各種使用場景示例分析

    MVVMLight項目的綁定及各種使用場景示例分析

    這篇文章主要為大家介紹了MVVMLight項目中的綁定及綁定的各種使用場景示例源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步除夕快樂
    2022-01-01
  • Android實現圓線按鈕進度效果

    Android實現圓線按鈕進度效果

    這篇文章主要為大家詳細介紹了Android實現圓線按鈕帶進度,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • AndroidStudio重新share代碼和上傳到svn新地址教程

    AndroidStudio重新share代碼和上傳到svn新地址教程

    這篇文章主要介紹了AndroidStudio重新share代碼和上傳到svn新地址教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Android?Gradle模塊依賴替換使用技巧

    Android?Gradle模塊依賴替換使用技巧

    這篇文章主要為大家介紹了Android?Gradle模塊依賴替換使用技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • 實現Android 獲取cache緩存的目錄路徑的方法

    實現Android 獲取cache緩存的目錄路徑的方法

    這篇文章主要介紹了實現Android 獲取cache緩存的目錄路徑的方法的相關資料,這里實現一個靜態(tài)類來實現該功能,希望能幫助到大家,需要的朋友可以參考下
    2017-08-08

最新評論

弋阳县| 延庆县| 江陵县| 平山县| 三江| 资阳市| 武邑县| 三明市| 龙里县| 永福县| 河南省| 同心县| 自贡市| 北安市| 外汇| 广宁县| 莒南县| 乡宁县| 凤冈县| 保康县| 成安县| 利辛县| 台中市| 夏邑县| 石河子市| 星子县| 夏河县| 建湖县| 来凤县| 郁南县| 东乡| 化德县| 珲春市| 缙云县| 潮州市| 彭阳县| 珲春市| 宁国市| 阿拉善右旗| 青神县| 凤凰县|