Android Bitmap Compress 稳定版

import java.io.FileOutputStream;
import java.io.IOException;


import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.media.ThumbnailUtils;


import com.idtechinfo.common.CoderHelper;


/**
 * 图片处理工具类
 * 
 */
public class ImageUtil {
public static final int UNCONSTRAINED = -1;


/**
* 从字节数组中解析Bitmap

* 参数定义参见:@{link #decodeFile}
*/
public static Bitmap decodeByteArray(byte[] data, int minSideLength) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
if (options.outWidth < 0 || options.outHeight < 0)
return null;


// Calculate inSampleSize
options.inSampleSize = computeSampleSize(options, minSideLength);


options.inDither = false;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}


/**
* 从文件中解析Bitmap

* @param minSideLength
*            最小边界的大小(宽、高中最小的一边值,例如需要1280*720的图,则传720)
*            传{@link #UNCONSTRAINED}则不限制大小
* @return null则解码失败
*/
public static Bitmap decodeFile(String pathName, int minSideLength) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
if (options.outWidth < 0 || options.outHeight < 0)
return null;


// Calculate inSampleSize
options.inSampleSize = computeSampleSize(options, minSideLength);


// Decode bitmap with inSampleSize set
options.inDither = false;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(pathName, options);
}


/**
* 保存图像到文件
* @author 老吴
*/
public static boolean saveBitmapToFile(Bitmap bitmap, String outFileName, int jpegQuality, boolean isRecycleBitmap) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(outFileName, false);
return bitmap.compress(CompressFormat.JPEG, jpegQuality, outStream);
} catch (Throwable e) {
e.printStackTrace();
return false;
} finally {
CoderHelper.close(outStream);
if (isRecycleBitmap) {
if (bitmap != null && !bitmap.isRecycled())
bitmap.recycle();
}
}
}


/**
* 压缩图像

* @param imgPath
*            待压缩的图片路径
* @param outImgPath
*            压缩后输出路径
* @param jpegQuality
*            压缩质量 0-100
* @param minSideLength
*            取值参见{@link #decodeFile(String, int)}的同名参数
* @param considerRotate
*            是否考虑图片旋转
*/
public static boolean compresImage(String imgPath, String outImgPath, int jpegQuality, int minSideLength, boolean considerRotate) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imgPath, options);


options.inSampleSize = computeSampleSize(options, minSideLength);


options.inJustDecodeBounds = false;
try {
Bitmap bmp = BitmapFactory.decodeFile(imgPath, options);
int dstWidth = 0, dstHeight = 0;
if (options.outWidth > options.outHeight) {
dstWidth = (int) ((double) minSideLength / (double) options.outHeight * (double) options.outWidth);
dstHeight = minSideLength;
} else {
dstWidth = minSideLength;
dstHeight = (int) ((double) minSideLength / (double) options.outWidth * (double) options.outHeight);
}
bmp = ThumbnailUtils.extractThumbnail(bmp, dstWidth, dstHeight, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);


int degreeRotate = 0;
if (considerRotate && (degreeRotate = getExifOrientation(imgPath)) != 0) {
Bitmap bmp2 = rotateBitmap(bmp, degreeRotate);
if (!bmp.isRecycled())
bmp.recycle();
bmp = bmp2;
}
return saveBitmapToFile(bmp, outImgPath, jpegQuality, true);
} catch (Throwable ex) {
ex.printStackTrace();
}
return false;
}


/**
* 获取图片文件扩展信息(方向)


* @param filepath
*            文件路径
* @return int 图片的旋转角度

* @author 老吴
*/
public static int getExifOrientation(String filepath) {
int degree = 0;
ExifInterface exif = null;
try {
exif = new ExifInterface(filepath);
} catch (IOException ex) {
ex.printStackTrace();
}


if (exif != null) {
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);


if (orientation != -1) {
// We only recognize a subset of orientation tag values.
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;
}
}
}


return degree;
}


/**
* 将Bitmpa纠正到正确方向

* @param degree
*            : 图片被系统旋转的角度
* @param bitmap
*            : 需纠正方向的图片
* @return 纠向后的图片

* @author 老吴
*/
public static Bitmap rotateBitmap(Bitmap bitmap, int degree) {
Matrix matrix = new Matrix();
matrix.postRotate(degree);
try {
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
} catch (Throwable ex) {
ex.printStackTrace();
return null;
}
}


private static int computeSampleSize(BitmapFactory.Options options, int minSideLength) {
return computeSampleSize(options, minSideLength, UNCONSTRAINED);
}


private static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);


int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}


return roundedSize;
}


private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;


int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == UNCONSTRAINED) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));


if (upperBound < lowerBound) {
// return the larger one when there is no overlapping zone.
return lowerBound;
}


if ((maxNumOfPixels == UNCONSTRAINED) && (minSideLength == UNCONSTRAINED)) {
return 1;
} else if (minSideLength == UNCONSTRAINED) {
return lowerBound;
} else {
return upperBound;
}
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值