public class BitmapUtils {
private BitmapUtils() {
}
//可以直接將網(wǎng)絡(luò)連接得到的輸入流讀取到字節(jié)流,壓縮為bitmpa
public static Bitmap decodeBitmapFromBytes(byte[] data, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
/*
* 計(jì)算采樣率
*/
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;
while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
/**
* 裁剪
*
* @param bitmap 原圖
* @return 裁剪后的圖像
*/
public static Bitmap cropBitmap(Bitmap bitmap, float hRatioW) {
int w = bitmap.getWidth(); // 得到圖片的寬,高
int h = bitmap.getHeight();
return Bitmap.createBitmap(bitmap, 0, 0, w, (int) (w * hRatioW), null, false);
}
/**
* 按比例縮放圖片
*
* @param origin 原圖
* @param ratio 比例
* @return 新的bitmap
*/
public static Bitmap scaleBitmap(Bitmap origin, float ratio) {
if (origin == null) {
return null;
}
int width = origin.getWidth();
int height = origin.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(ratio, ratio);
Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
return newBM;
}
/*
* 質(zhì)量壓縮法:將圖片文件壓縮,壓縮是耗時(shí)操作
*/
public static void compressFile(CompressFileBean compressFileBean, CompressFileCallback compressFileCallback) {
new CompressFileThread(compressFileBean, compressFileCallback).start();
}
/*
* 由file轉(zhuǎn)bitmap
*/
public static Bitmap decodeBitmapFromFilePath(String path, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//如此,無法decode bitmap
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;//如此,方可decode bitmap
return BitmapFactory.decodeFile(path, options);
}
/**
* 根據(jù)路徑 創(chuàng)建文件
*
* @param pathFile
* @return
* @throws IOException
*/
private static File createFile(String pathFile) throws IOException {
File fileDir = new File(pathFile.substring(0, pathFile.lastIndexOf(File.separator)));
File file = new File(pathFile);
if (!fileDir.exists()) fileDir.mkdirs();
if (!file.exists()) file.createNewFile();
return file;
}
/**
* 讀取圖片的旋轉(zhuǎn)的角度
*
* @param path 圖片絕對(duì)路徑
* @return 圖片的旋轉(zhuǎn)角度
*/
public static int getBitmapDegree(String path) {
int degree = 0;
try {
// 從指定路徑下讀取圖片,并獲取其EXIF信息
ExifInterface exifInterface = new ExifInterface(path);
// 獲取圖片的旋轉(zhuǎn)信息
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;
}
/**
* 將圖片按照某個(gè)角度進(jìn)行旋轉(zhuǎn)
*
* @param bm 需要旋轉(zhuǎn)的圖片
* @param degree 旋轉(zhuǎn)角度
* @return 旋轉(zhuǎn)后的圖片
*/
public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
Bitmap returnBm = null;
// 根據(jù)旋轉(zhuǎn)角度,生成旋轉(zhuǎn)矩陣
Matrix matrix = new Matrix();
matrix.postRotate(degree);
try {
// 將原始圖片按照旋轉(zhuǎn)矩陣進(jìn)行旋轉(zhuǎn),并得到新的圖片
returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
} catch (OutOfMemoryError e) {
}
if (returnBm == null) {
returnBm = bm;
}
if (bm != returnBm) {
bm.recycle();
}
return returnBm;
}
/**
* 對(duì)View進(jìn)行量測(cè),布局后截圖
*
* @param view
* @return
*/
public static Object[] captureViewToBitmap(View view) {
view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
view.layout(0, 0, width, height);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
Object[] objects = new Object[3];
objects[0] = bitmap;
objects[1] = width;
objects[2] = height;
return objects;
}
/**
* 對(duì)View進(jìn)行量測(cè),布局后截圖
*
* @param view
* @return
*/
public static Bitmap captureViewToBitmap(View view, int reqWidth, int reqHeight) {
view.layout(0, 0, reqWidth, reqHeight);
Bitmap bitmap = Bitmap.createBitmap(reqWidth, reqHeight, Bitmap.Config.ARGB_4444);
// CYLogUtils.log("bitmap原始width", bitmap.getWidth());
// CYLogUtils.log("bitmap原始height", bitmap.getHeight());
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
/*
壓縮bitmap,會(huì)被壓縮到指定寬高
*/
public static Bitmap compressBitmap(Bitmap bitmap, int reqWidth, int reqHeight) {
return Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, true);
}
private static class CompressFileThread extends Thread {
private Handler handler_deliver = new Handler(Looper.getMainLooper());
private CompressFileBean compressFileBean;
private CompressFileCallback compressFileCallback;
public CompressFileThread(CompressFileBean compressFileBean, CompressFileCallback compressFileCallback) {
this.compressFileBean = compressFileBean;
this.compressFileCallback = compressFileCallback;
}
@Override
public void run() {
super.run();
final Bitmap bitmap = decodeBitmapFromFilePath(compressFileBean.getPathSource(), compressFileBean.getReqWidth(), compressFileBean.getReqHeight());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int quality = 80;
//壓縮格式選取JPEG就行了,quality,壓縮精度盡量不要低于50,否則影響清晰度
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream);
while (byteArrayOutputStream.toByteArray().length / 1024 > compressFileBean.getKb_max() && quality > compressFileBean.getQuality_max()) {
// 循環(huán)判斷如果壓縮后圖片是否大于kb_max kb,大于繼續(xù)壓縮,
byteArrayOutputStream.reset();
quality -= 10;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream);
}
try {
final File fileCompressed = createFile(compressFileBean.getPathCompressed());
FileOutputStream fileOutputStream = new FileOutputStream(fileCompressed);
fileOutputStream.write(byteArrayOutputStream.toByteArray());//寫入目標(biāo)文件
fileOutputStream.flush();
fileOutputStream.close();
byteArrayOutputStream.close();
if (fileCompressed != null && fileCompressed.length() > 0)
runOnUiThread(new Runnable() {
@Override
public void run() {
//壓縮成功
compressFileCallback.onCompressFileFinished(fileCompressed, bitmap);
}
});
} catch (final Exception e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
//壓縮失敗
compressFileCallback.onCompressFileFailed("壓縮圖片文件失敗" + e.getMessage());
}
});
}
}
private void runOnUiThread(Runnable run) {
handler_deliver.post(run);
}
}
public static class CompressFileBean {
private String pathSource;//原圖文件路徑
private String pathCompressed;//壓縮后的圖片文件路徑
private int kb_max = 1000;//壓縮到多少KB,不能精確,只能<=kb_max
private int quality_max = 80;//壓縮精度,盡量>=50
private int reqWidth = 1000;//期望的圖片寬度
private int reqHeight = 1000;//期望的圖片高度
private CompressFileBean(Builder builder) {
this.pathSource = builder.getFileSource();
this.pathCompressed = builder.getFileCompressed();
this.kb_max = builder.getKb_max();
this.quality_max = builder.getQuality_max();
this.reqWidth = builder.getReqWidth();
this.reqHeight = builder.getReqHeight();
}
public static class Builder {
private String pathSource;//原圖文件路徑
private String pathCompressed;//壓縮后的圖片文件路徑
private int kb_max = 1000;//壓縮到多少KB,不能精確,只能<=kb_max
private int quality_max = 80;//壓縮精度,盡量>=50
private int reqWidth = 1000;//期望的圖片寬度
private int reqHeight = 1000;//期望的圖片高度
public String getFileSource() {
return pathSource;
}
public Builder setFileSource(String pathSource) {
this.pathSource = pathSource;
return this;
}
public String getFileCompressed() {
return pathCompressed;
}
public Builder setFileCompressed(String pathCompressed) {
this.pathCompressed = pathCompressed;
return this;
}
public int getKb_max() {
return kb_max;
}
public Builder setKb_max(int kb_max) {
this.kb_max = kb_max;
return this;
}
public int getQuality_max() {
return quality_max;
}
public Builder setQuality_max(int quality_max) {
this.quality_max = quality_max;
return this;
}
public int getReqWidth() {
return reqWidth;
}
public Builder setReqWidth(int reqWidth) {
this.reqWidth = reqWidth;
return this;
}
public int getReqHeight() {
return reqHeight;
}
public Builder setReqHeight(int reqHeight) {
this.reqHeight = reqHeight;
return this;
}
public CompressFileBean build() {
return new CompressFileBean(this);
}
}
public String getPathSource() {
return pathSource;
}
public String getPathCompressed() {
return pathCompressed;
}
public int getKb_max() {
return kb_max;
}
public int getQuality_max() {
return quality_max;
}
public int getReqWidth() {
return reqWidth;
}
public int getReqHeight() {
return reqHeight;
}
}
public static interface CompressFileCallback {
//圖片壓縮成功
public void onCompressFileFinished(File file, Bitmap bitmap);
//圖片壓縮失敗
public void onCompressFileFailed(String errorMsg);
}
}
BitmapUtils
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 書籍是人類最好的老師,讀書的益處很多,不僅能擴(kuò)大人的知識(shí)面、陶冶人的情操、讓人明真理,辨是非,對(duì)學(xué)生來說更...