Skip to content

Commit

Permalink
尝试解决width,height must be > 0
Browse files Browse the repository at this point in the history
  • Loading branch information
nanchen2251 committed Apr 26, 2017
1 parent c7ccfe3 commit b090895
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 309 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ private void initInstances() {

public void compress(View view) {
// 默认的压缩方法,多张图片只需要直接加入循环即可
newFile = CompressHelper.getDefault(this).compressToFile(oldFile);
newFile = CompressHelper.getDefault(getApplicationContext()).compressToFile(oldFile);


// String yourFileName = "123.jpg";
Expand Down
303 changes: 187 additions & 116 deletions compresshelper/src/main/java/com/nanchen/compresshelper/BitmapUtil.java
Original file line number Diff line number Diff line change
@@ -1,159 +1,230 @@
package com.nanchen.compresshelper;

import android.content.res.Resources;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.media.ExifInterface;
import android.net.Uri;
import android.text.TextUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
* Bitmap 压缩相关操作工具类
*
*
*
* 原理不明白请查看我博客:http://www.cnblogs.com/liushilin/p/6116759.html
* 图片处理工具类
*
* Author: nanchen
* Email: liushilin520@foxmail.com
* Date: 2017-02-13 15:43
* Date: 2017-03-08 9:03
*/

public class BitmapUtil {
/**
* 计算图片的压缩比率
*
* @param options 参数
* @param reqWidth 目标的宽度
* @param reqHeight 目标的高度
* @param pathName 路径
* @return 计算的SampleSize
*/
private static int calculateInSampleSize(BitmapFactory.Options options,String pathName, int reqWidth, int reqHeight) {
// 源图片的高度和宽度
int height = options.outHeight;
int width = options.outWidth;
if (height == -1 || width == -1) {

private BitmapUtil() {
throw new UnsupportedOperationException("u can't instantiate me...");
}

static Bitmap getScaledBitmap(Context context, Uri imageUri, float maxWidth, float maxHeight, Bitmap.Config bitmapConfig) {
String filePath = FileUtil.getRealPathFromURI(context, imageUri);
Bitmap scaledBitmap = null;

BitmapFactory.Options options = new BitmapFactory.Options();

//by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
//you try the use the bitmap here, you will get null.
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
if (bmp == null) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(filePath);
BitmapFactory.decodeStream(inputStream, null, options);
inputStream.close();
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} catch (IOException exception) {
exception.printStackTrace();
}
}

int actualHeight = options.outHeight;
int actualWidth = options.outWidth;

if (actualHeight == -1 || actualWidth == -1){
try {
ExifInterface exifInterface = new ExifInterface(pathName);
height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的高度
width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的宽度
ExifInterface exifInterface = new ExifInterface(filePath);
actualHeight = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的高度
actualWidth = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, ExifInterface.ORIENTATION_NORMAL);//获取图片的宽度
} catch (IOException e) {
e.printStackTrace();
}
}
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;

if (actualWidth <= 0 || actualHeight <= 0) {
Bitmap bitmap2 = BitmapFactory.decodeFile(filePath);
if (bitmap2 != null){
actualWidth = bitmap2.getWidth();
actualHeight = bitmap2.getHeight();
}else{
return null;
}
}
return inSampleSize;
}

float imgRatio = (float) actualWidth / actualHeight;
float maxRatio = maxWidth / maxHeight;

/**
* 计算图片的压缩比率
*
* @param options 参数
* @param reqWidth 目标的宽度
* @param reqHeight 目标的高度
* @return 计算的SampleSize
*/
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// 源图片的高度和宽度
int height = options.outHeight;
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;
//width and height values are set maintaining the aspect ratio of the image
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
return inSampleSize;
}

/**
* 从Resources中加载图片
*
* @param res Resource
* @param resId 资源id
* @param reqWidth 请求宽度
* @param reqHeight 请求高度
* @return Bitmap
*/
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 设置成了true,不占用内存,只获取bitmap宽高
BitmapFactory.decodeResource(res, resId, options); // 读取图片长款
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 调用上面定义的方法计算inSampleSize值
// 使用获取到的inSampleSize值再次解析图片
//setting inSampleSize value allows to load a scaled down version of the original image
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);

//inJustDecodeBounds set to false to load the actual bitmap
options.inJustDecodeBounds = false;
Bitmap src = BitmapFactory.decodeResource(res, resId, options); // 载入一个稍大的缩略图
return createScaleBitmap(src, reqWidth, reqHeight, options.inSampleSize); // 进一步得到目标大小的缩略图
}

/**
* 通过传入的bitmap,进行压缩,得到符合标准的bitmap
*
* @param src Bitmap源图
* @param dstWidth 宽度
* @param dstHeight 高度
* @return 新的Bitmap
*/
private static Bitmap createScaleBitmap(Bitmap src, int dstWidth, int dstHeight, int inSampleSize) {
//如果inSampleSize是2的倍数,也就说这个src已经是我们想要的缩略图了,直接返回即可。
if (inSampleSize % 2 == 0) {
return src;
//this options allow android to claim the bitmap memory if it runs low on memory
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];

try {
// load the bitmap getTempFile its path
bmp = BitmapFactory.decodeFile(filePath, options);
if (bmp == null) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(filePath);
BitmapFactory.decodeStream(inputStream, null, options);
inputStream.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
if (src == null){
if (actualHeight <= 0 || actualWidth <= 0){
return null;
}
// 如果是放大图片,filter决定是否平滑,如果是缩小图片,filter无影响,我们这里是缩小图片,所以直接设置为false
Bitmap dst = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false);
if (src != dst) { // 如果没有缩放,那么不回收
src.recycle(); // 释放Bitmap的native像素数组

try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, bitmapConfig);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
return dst;

float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;

Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, 0, 0);

Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));

//check the rotation of the image and display it properly
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
} else if (orientation == 3) {
matrix.postRotate(180);
} else if (orientation == 8) {
matrix.postRotate(270);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(),
matrix, true);
} catch (IOException e) {
e.printStackTrace();
}

return scaledBitmap;
}

/**
* 从SD卡上加载图片
*
* @param pathName 路径
* @param reqWidth 请求宽度
* @param reqHeight 请求高度
* @return Bitmap
*/
public static Bitmap decodeSampledBitmapFromFile(String pathName, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
options.inSampleSize = calculateInSampleSize(options, pathName,reqWidth, reqHeight);
options.inJustDecodeBounds = false;
Bitmap src = BitmapFactory.decodeFile(pathName, options);
return createScaleBitmap(src, reqWidth, reqHeight, options.inSampleSize);
static File compressImage(Context context, Uri imageUri, float maxWidth, float maxHeight,
Bitmap.CompressFormat compressFormat, Bitmap.Config bitmapConfig,
int quality, String parentPath, String prefix, String fileName) {
FileOutputStream out = null;
String filename = generateFilePath(context, parentPath, imageUri, compressFormat.name().toLowerCase(), prefix, fileName);
try {
out = new FileOutputStream(filename);
//write the compressed bitmap at the destination specified by filename.
BitmapUtil.getScaledBitmap(context, imageUri, maxWidth, maxHeight, bitmapConfig).compress(compressFormat, quality, out);

} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ignored) {
}
}

return new File(filename);
}

private static String generateFilePath(Context context, String parentPath, Uri uri,
String extension, String prefix, String fileName) {
File file = new File(parentPath);
if (!file.exists()) {
file.mkdirs();
}
/** if prefix is null, set prefix "" */
prefix = TextUtils.isEmpty(prefix) ? "" : prefix;
/** reset fileName by prefix and custom file name */
fileName = TextUtils.isEmpty(fileName) ? prefix + FileUtil.splitFileName(FileUtil.getFileName(context, uri))[0] : fileName;
return file.getAbsolutePath() + File.separator + fileName + "." + extension;
}


/**
* 删除临时图片
* @param path 图片路径
* 计算inSampleSize
*/
public static void deleteTempFile(String path){
File file = new File(path);
if (file.exists()){
file.delete();
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}

final float totalPixels = width * height;
final float totalReqPixelsCap = reqWidth * reqHeight * 2;

while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}

return inSampleSize;
}
}
Loading

0 comments on commit b090895

Please sign in to comment.