Android整理好的圖片壓縮工具類
Android設備的內存有限,對于大圖片,必須進行壓縮后再進行顯示,否則會出現(xiàn)內存溢出:OOM;
處理策略:
1.使用縮略圖(Thumbnails);
Android系統(tǒng)會給檢測到的圖片創(chuàng)建縮略圖;可以操作Media內容提供者中的Image對圖片進行操作;
2.手動壓縮:
- (1)根據(jù)圖片和屏幕尺寸,等比壓縮,完美顯示;
- (2)降低圖片質量,壓縮圖片大小;
以下是自己整理的小工具類(對于按比例縮放后,在此并未再進行質量縮放,此時圖片大小有可能超出我們期望的限制;假如我們有嚴格的大小限制需求,可先進行按比例縮放后,判斷此時圖片大小是否超出限制;如果超出限制,對其再進行質量縮放即可。建議使用按比例縮放,按質量縮放很有可能導致圖片失真。)
</pre><p><pre name="code" class="java">package com.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.media.ExifInterface;
/**
* 圖片壓縮工具類
* @author 丶Life_
*/
public class ImageCompressUtil {
/**
* 通過降低圖片的質量來壓縮圖片
* @param bmp
* 要壓縮的圖片位圖對象
* @param maxSize
* 壓縮后圖片大小的最大值,單位KB
* @return 壓縮后的圖片位圖對象
*/
public static Bitmap compressByQuality(Bitmap bitmap, int maxSize) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
bitmap.compress(CompressFormat.JPEG, quality, baos);
System.out.println("圖片壓縮前大?。? + baos.toByteArray().length + "byte");
boolean isCompressed = false;
while (baos.toByteArray().length / 1024 > maxSize) {
quality -= 10;
baos.reset();
bitmap.compress(CompressFormat.JPEG, quality, baos);
System.out.println("質量壓縮到原來的" + quality + "%時大小為:"
+ baos.toByteArray().length + "byte");
isCompressed = true;
}
System.out.println("圖片壓縮后大小:" + baos.toByteArray().length + "byte");
if (isCompressed) {
Bitmap compressedBitmap = BitmapFactory.decodeByteArray(
baos.toByteArray(), 0, baos.toByteArray().length);
recycleBitmap(bitmap);
return compressedBitmap;
} else {
return bitmap;
}
}
/**
* 傳入圖片url,通過壓縮圖片的尺寸來壓縮圖片大小
* @param pathName 圖片的完整路徑
* @param targetWidth 縮放的目標寬度
* @param targetHeight 縮放的目標高度
* @return 縮放后的圖片
*/
public static Bitmap compressBySize(String pathName, int targetWidth,
int targetHeight) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;// 不去真的解析圖片,只是獲取圖片的頭部信息,包含寬高等;
Bitmap bitmap = BitmapFactory.decodeFile(pathName, opts);
// 得到圖片的寬度、高度;
int imgWidth = opts.outWidth;
int imgHeight = opts.outHeight;
// 分別計算圖片寬度、高度與目標寬度、高度的比例;取大于等于該比例的最小整數(shù);
int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth);
int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight);
if (widthRatio > 1 || heightRatio > 1) {
if (widthRatio > heightRatio) {
opts.inSampleSize = widthRatio;
} else {
opts.inSampleSize = heightRatio;
}
}
// 設置好縮放比例后,加載圖片進內容;
opts.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(pathName, opts);
return bitmap;
}
/**
* 傳入bitmap,通過壓縮圖片的尺寸來壓縮圖片大小
* @param bitmap 要壓縮圖片
* @param targetWidth 縮放的目標寬度
* @param targetHeight 縮放的目標高度
* @return 縮放后的圖片
*/
public static Bitmap compressBySize(Bitmap bitmap, int targetWidth,
int targetHeight) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 100, baos);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
bitmap = BitmapFactory.decodeByteArray(baos.toByteArray(), 0,
baos.toByteArray().length, opts);
// 得到圖片的寬度、高度;
int imgWidth = opts.outWidth;
int imgHeight = opts.outHeight;
// 分別計算圖片寬度、高度與目標寬度、高度的比例;取大于該比例的最小整數(shù);
int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth);
int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight);
if (widthRatio > 1 || heightRatio > 1) {
if (widthRatio > heightRatio) {
opts.inSampleSize = widthRatio;
} else {
opts.inSampleSize = heightRatio;
}
}
// 設置好縮放比例后,加載圖片進內存;
opts.inJustDecodeBounds = false;
Bitmap compressedBitmap = BitmapFactory.decodeByteArray(
baos.toByteArray(), 0, baos.toByteArray().length, opts);
recycleBitmap(bitmap);
return compressedBitmap;
}
/**
* 通過壓縮圖片的尺寸來壓縮圖片大小,通過讀入流的方式,可以有效防止網(wǎng)絡圖片數(shù)據(jù)流形成位圖對象時內存過大的問題;
* @param InputStream 要壓縮圖片,以流的形式傳入
* @param targetWidth 縮放的目標寬度
* @param targetHeight 縮放的目標高度
* @return 縮放后的圖片
* @throws IOException 讀輸入流的時候發(fā)生異常
*/
public static Bitmap compressBySize(InputStream is, int targetWidth,
int targetHeight) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len = 0;
while ((len = is.read(buff)) != -1) {
baos.write(buff, 0, len);
}
byte[] data = baos.toByteArray();
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,
opts);
// 得到圖片的寬度、高度;
int imgWidth = opts.outWidth;
int imgHeight = opts.outHeight;
// 分別計算圖片寬度、高度與目標寬度、高度的比例;取大于該比例的最小整數(shù);
int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth);
int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight);
if (widthRatio > 1 || heightRatio > 1) {
if (widthRatio > heightRatio) {
opts.inSampleSize = widthRatio;
} else {
opts.inSampleSize = heightRatio;
}
}
// 設置好縮放比例后,加載圖片進內存;
opts.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
return bitmap;
}
/**
* 旋轉圖片擺正顯示
* @param srcPath
* @param bitmap
* @return
*/
public static Bitmap rotateBitmapByExif(String srcPath, Bitmap bitmap) {
ExifInterface exif;
Bitmap newBitmap = null;
try {
exif = new ExifInterface(srcPath);
if (exif != null) { // 讀取圖片中相機方向信息
int ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int digree = 0;
switch (ori) {
case ExifInterface.ORIENTATION_ROTATE_90:
digree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
digree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
digree = 270;
break;
}
if (digree != 0) {
Matrix m = new Matrix();
m.postRotate(digree);
newBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), m, true);
recycleBitmap(bitmap);
return newBitmap;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
/**
* 回收位圖對象
* @param bitmap
*/
public static void recycleBitmap(Bitmap bitmap) {
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
System.gc();
bitmap = null;
}
}
}
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關內容請查看下面相關鏈接
相關文章
Android之線程池ThreadPoolExecutor的簡介
今天小編就為大家分享一篇關于Android之線程池ThreadPoolExecutor的簡介,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03
Android 自定義view模板并實現(xiàn)點擊事件的回調
這篇文章主要介紹了Android 自定義view模板并實現(xiàn)點擊事件的回調的相關資料,需要的朋友可以參考下2017-01-01
Android中SurfaceView和普通view的區(qū)別及使用
SurfaceView第一印象它是一個view,因為它繼承了View,本文主要介紹了SurfaceView和普通view的區(qū)別及使用,感興趣的小伙伴們可以參考一下2021-06-06

