Android图片压缩和图片大小的计算
图片压缩
图片的压缩大约有三种:
- 采样率压缩,通过
options.inSampleSize的参数 - 质量压缩,通过
bitmap.compress() - 尺寸压缩,改变图片的大小重新进行裁剪,
Bitmap newBitmap = Bitmap.createBitmap(newWdith,newHeiht, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Rect rect = new Rect(0, 0, newWdith);
canvas.drawBitmap(oldBitmap, null, newBitmap, null);
实践
- 1.定义压缩的策略
public abstract class AbstractStrategy {
/**
* 源图片的文件
*/
protected File srcFile;
/**
* 目标文件
*/
protected File outFile;
protected Bitmap.CompressFormat format;
protected int quality;
protected int srcWidth;
protected int srcHeight;
protected float maxWidth;
protected float maxHeight;
public void setSrcFile(File srcFile) {
this.srcFile = srcFile;
}
public void setOutFile(File outFile) {
this.outFile = outFile;
}
public void setFormat(Bitmap.CompressFormat format) {
this.format = format;
}
public void setQuality(int quality) {
this.quality = quality;
}
public void setMaxWidth(float maxWidth) {
this.maxWidth = maxWidth;
}
public void setMaxHeight(float maxHeight) {
this.maxHeight = maxHeight;
}
/**
* 执行压缩并返回图片
*
* @return
*/
public void launch() {
//读取图片信息
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(srcFile.getAbsolutePath(), options);
this.srcWidth = options.outWidth;
this.srcHeight = options.outHeight;
//计算采样率
options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
options.inJustDecodeBounds = false;
options.inDither = false;
//大小压缩
Bitmap scaledBitmap = BitmapFactory.decodeFile(srcFile.getAbsolutePath(), options);
int degree = getRotateDegree(srcFile.getAbsolutePath());
//旋转图片
if (scaledBitmap != null && degree != 0) {
scaledBitmap = rotateBitmap(scaledBitmap, degree);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
scaledBitmap.compress(format, quality, baos);
FileOutputStream fos = null;
try {
outFile.deleteOnExit();
outFile.createNewFile();
fos = new FileOutputStream(outFile);
fos.write(baos.toByteArray());
fos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
if (baos != null) {
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
scaledBitmap.recycle();
}
protected abstract int calculateInSampleSize(BitmapFactory.Options options, float reqWidth, float reqHeight);
/**
* 读取图片的当前角度
*
* @param path
* @return
*/
public int getRotateDegree(String path) {
int degree = 0;
ExifInterface exifInterface = null;
try {
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;
default:
degree = 0;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
/**
* 旋转
*
* @param srcBitmap 原图
* @param angle 旋转的角度
* @return the rotated bitmap
*/
protected Bitmap rotateBitmap(Bitmap srcBitmap, int angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
}
- 2.定义采样率的定义
public class SimpleStrategy extends AbstractStrategy {
@Override
protected int calculateInSampleSize(BitmapFactory.Options options, float reqWidth, float 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;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
}
- 3.入口
public class Compress {
private int DEFAULT_QUALITY = 75;
private Bitmap.CompressFormat DEFAULT_FORMAT = Bitmap.CompressFormat.JPEG;
/**
* 最大宽度,默认为960
*/
private float DEFAULT_MAX_WIDTH = 960f;
/**
* 最大高度,默认为960
*/
private float DEFAULT_MAX_HEIGHT = 960f;
private Context context;
/**
* 源图片文件
*/
private File srcFile;
/**
* 压缩质量
*/
private int quality = DEFAULT_QUALITY;
/**
* 图片格式
*/
private Bitmap.CompressFormat format = DEFAULT_FORMAT;
/**
* 目标文件
*/
private String targetDir;
private String targetFileName;
protected float maxWidth = DEFAULT_MAX_WIDTH;
protected float maxHeight = DEFAULT_MAX_HEIGHT;
public static Compress with(Context context, File srcFile) {
return new Compress(context, srcFile, System.currentTimeMillis() + (int) (Math.random() * 1000) + ".jpg");
}
public static Compress with(Context context, File srcFile, String newFileName) {
return new Compress(context, srcFile, newFileName);
}
private Compress(Context context, File srcFile, String newFileName) {
this.context = context;
this.srcFile = srcFile;
this.targetFileName = newFileName;
}
public Compress setQuality(@IntRange(from = 0, to = 100) int quality) {
this.quality = quality;
return this;
}
public Compress setFormat(Bitmap.CompressFormat format) {
this.format = format;
return this;
}
public Compress setTargetDir(String targetDir) {
this.targetDir = targetDir;
return this;
}
public Compress setTargetFileName(String targetFileName) {
this.targetFileName = targetFileName;
return this;
}
public Compress setMaxWidth(float maxWidth) {
this.maxWidth = maxWidth;
return this;
}
public Compress setMaxHeight(float maxHeight) {
this.maxHeight = maxHeight;
return this;
}
/**
* 定义图片的压缩策略
*
* @param strategy
* @param <T>
* @return
*/
public <T extends AbstractStrategy> T strategy(T strategy) {
strategy.setSrcFile(srcFile);
strategy.setFormat(format);
strategy.setQuality(quality);
strategy.setOutFile(getOutFile());
strategy.setMaxWidth(maxWidth);
strategy.setMaxHeight(maxHeight);
return strategy;
}
/**
* 定义目标图片的位置
*
* @return
*/
private File getOutFile() {
if (isStorageWritable()) {
this.targetDir = context.getExternalCacheDir().getAbsolutePath() + File.separator + "images" + File.separator;
}
if (TextUtils.isEmpty(targetDir)) {
this.targetDir = context.getCacheDir().getAbsolutePath() + File.separator + "images" + File.separator;
}
//防止getExternalCacheDir拿不到文件路径
File targetDir = new File(this.targetDir);
if (!targetDir.exists()) {
targetDir.mkdirs();
}
Log.d("SSS", "目标路径" + this.targetDir + this.targetFileName);
File file = new File(this.targetDir + this.targetFileName);
return file;
}
private static boolean isStorageWritable() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
}
- 4.使用
Compress.with(SampleActivity.this, imageFile)
.setFormat(Bitmap.CompressFormat.JPEG)
.setQuality(80)
.strategy(new SimpleStrategy())
.launch();
当前的图片压缩必须在子线程中进行处理,需要自己实现。图片保存的地址未开放出来,如果向开放出来,可以调整AbstractStrategy类的launch方法
图片大小的计算
/**
* size --> "B", "KB", "MB", "GB", "TB"
*/
public static String getReadableFileSize(long size) {
if (size <= 0) {
return "0";
}
final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}

浙公网安备 33010602011771号