图片的几种压缩方式总结
实际项目中,对图片的压缩处理相当常见,下面总结几种压缩的方式:
- 只压缩质量的方式:
/**
* 只压缩质量的方法
* @param file 源文件
* @param targetPath 目标路径
* @param quality 质量 取值为0-100 100表示按最大质量,此参数对PNG图片无效,即compress方法的第一个参数为
* Bitmap.CompressFormat.PNG时,quality的设置是无效的。
* **/
public static File scalFile(File file, String targetPath,int quality){
try {
//将文件转换为字节数组
byte[] bytes = getBytesFromFile(file);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
Bitmap bitmap=BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
if(bitmap != null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
baos.close();
File targetFile = new File(targetPath);
if(targetFile.exists()){
boolean flag = targetFile.delete();
Log.i("ImageUtils.scalFile()", "flag: " + flag);
}
FileOutputStream fos = new FileOutputStream(targetFile);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
return targetFile;
}
} catch (Exception e) {
e.printStackTrace();
Log.i("ImageUtils.scalFile()",e.getMessage());
}
return null;
}
- 压缩到指定分辨率的方式:例从任意分辨率压缩到1280X960或960X1280,以矩阵缩放的方式达到目的,宽高分别取相应的比例去与目标宽高达成一致
/**
* 压缩到指定分辨率的方法 以1280X960为例
* @param file 源文件
* @param targetPath 目标路径
*
*
* **/
public static File scalFile(File file, String targetPath){
long fileSize = file.length();
final long fileMaxSize = 200 * 1024;//超过200K的图片需要进行压缩
if(fileSize > fileMaxSize){
try {
byte[] bytes = getBytesFromFile(file);//将文件转换为字节数组
BitmapFactory.Options options = new BitmapFactory.Options();
//仅仅解码边缘区域
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
//得到宽高
int width = options.outWidth;
int height = options.outHeight;
float scaleWidth=0f;
float scaleHeight=0f;
Matrix matrix=new Matrix();
if(width>height)
{
scaleWidth=(float)1280/width;
scaleHeight=(float)960/height;
}else{
scaleWidth=(float)960/width;
scaleHeight=(float)1280/height;
}
Bitmap bitmap=BitmapFactory.decodeFile(file.getPath());
matrix.postScale(scaleWidth, scaleHeight);//执行缩放
Bitmap resizeBitmap=Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
if(resizeBitmap != null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
resizeBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
//限制压缩后图片最大为200K,否则继续压缩
while (baos.toByteArray().length > fileMaxSize) {
baos.reset();
quality -= 10;
resizeBitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
}
baos.close();
File targetFile = new File(targetPath);
if(targetFile.exists()){
boolean flag = targetFile.delete();
Log.i("ImageUtils.scalFile()", "flag: " + flag);
}
FileOutputStream fos = new FileOutputStream(targetFile);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
return targetFile;
}
} catch (Exception e) {
e.printStackTrace();
Log.i("ImageUtils.scalFile()",e.getMessage());
}
return null;
}else{
return file;
}
}
- 等比例压缩方式1:这种是用采样率的方式来等比例的缩小,优点是同等条件下会清晰一点,缺点是无法按计算得到的比例去缩小
,因为根据官方说明sampleSize为2的幂时,效果较好,而根据实测,发现其取值会趋向于2的幂,比如sampleSize为4到8之间的值,会均按4来缩小
/***
*等比例压缩方式1,以采样率的方式,以1280X960为例
*@param file 源文件
*@param targetPath 目标路径
*
**/
public static File scalFile(File file, String targetPath){
long fileSize = file.length();
final long fileMaxSize = 200 * 1024;
if(fileSize > fileMaxSize){
try {
byte[] bytes = getBytesFromFile(file);//将文件转换为字节数组
BitmapFactory.Options options = new BitmapFactory.Options();
//仅仅解码边缘区域
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
//得到宽高
int width = options.outWidth;
int height = options.outHeight;
int sampleSize =1;
if(width>height)
{
sampleSize=Math.max(width/1280, height/960);
}else{
sampleSize=Math.max(width/960, height/1280);
}
if(sampleSize < 1)
sampleSize = 1;
//不再加载图片边缘
options.inJustDecodeBounds = false;
//制定缩放比例
options.inSampleSize = sampleSize;
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
if(bitmap != null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
while (baos.toByteArray().length > fileMaxSize) {
baos.reset();
quality -= 10;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
}
baos.close();
File targetFile = new File(targetPath);
if(targetFile.exists()){
boolean flag = targetFile.delete();
Log.i("ImageUtils.scalFile()", "flag: " + flag);
}
FileOutputStream fos = new FileOutputStream(targetFile);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
return targetFile;
}
} catch (Exception e) {
e.printStackTrace();
Log.i("ImageUtils.scalFile()",e.getMessage());
}
return null;
}else{
return file;
}
}
- 等比例压缩方式2:这种是采用矩阵缩放的方式来等比例缩放,首先计算取得一个合适的比例,然后宽高取同一个比例,进行缩放。优点是可以压缩任意一个比例,不像”等比例压缩方式1”只局限于2的幂,无法压缩指定的倍数,缺点是虽然压缩后的图片比”等比例压缩方式 1”得到的图片小,但也没有小多少,但质量远远不如。
/**
* 等比例压缩方式2 以1280X960为例
* @param file 源文件
* @param targetPath 目标路径
*
*
***/
public static File scalFile(File file, String targetPath){
long fileSize = file.length();
final long fileMaxSize = 200 * 1024;
if(fileSize > fileMaxSize){
try {
byte[] bytes = getBytesFromFile(file);//将文件转换为字节数组
BitmapFactory.Options options = new BitmapFactory.Options();
//仅仅解码边缘区域
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
//得到宽高
int width = options.outWidth;
int height = options.outHeight;
float scaleWidth=0f;
float scaleHeight=0f;
float scale=0f;
Matrix matrix=new Matrix();
if(width>height)
{
scaleWidth=(float)1280/width;
scaleHeight=(float)960/height;
}else{
scaleWidth=(float)960/width;
scaleHeight=(float)1280/height;
}
//取两者之间较大的比例,这是为了尽可能得到分辨率大的图片
scale=Math.max(scaleWidth, scaleHeight);
Bitmap bitmap=BitmapFactory.decodeFile(file.getPath());
matrix.postScale(scale, scale);
Bitmap resizeBitmap=Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
if(resizeBitmap != null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 100;
resizeBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
while (baos.toByteArray().length > fileMaxSize) {
baos.reset();
quality -= 10;
resizeBitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
}
baos.close();
File targetFile = new File(targetPath);
if(targetFile.exists()){
boolean flag = targetFile.delete();
Log.i("ImageUtils.scalFile()", "flag: " + flag);
}
FileOutputStream fos = new FileOutputStream(targetFile);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
return targetFile;
}
} catch (Exception e) {
e.printStackTrace();
Log.i("ImageUtils.scalFile()",e.getMessage());
}
return null;
}else{
return file;
}
}