您的位置:首页 > 其它

通过URI获取图片处理

2016-05-04 18:34 267 查看
获取流对象读取

InputStream is = getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();


//根据uri获取真实路径

private String getRealPath(Uri fileUrl){

String fileName = null;

Uri filePathUri = fileUrl;

if(fileUrl!= null){

if
(fileUrl.getScheme().toString().compareTo("content")==0) //content://开头的uri

{

Cursor cursor = mContext.getContentResolver().query(videoUrl, null, null, null, null);

if (cursor != null && cursor.moveToFirst())

{

int column_index = cursor.getColumnIndexOrThrow(***.***.***.DATA);

fileName = cursor.getString(column_index); //取出文件路径

if(!fileName.startsWith("/mnt")){//检查是否有”/mnt“前缀

fileName = "/mnt" + fileName;

}

cursor.close();

}

}else if (videoUrl.getScheme().compareTo("file")==0) //file:///开头的uri

{

fileName = filePathUri.toString();

fileName = filePathUri.toString().replace("file://", "");//替换file://

if(!fileName.startsWith("/mnt")){//加上"/mnt"头

fileName
+= "/mnt";

}

}

}

return fileName;

}

很多人在调用图库选择图片时会在onActivityResult中用Media.getBitmap来获取返回的图片,如下:

[java] view
plain copy







Uri mImageCaptureUri = data.getData();

Bitmap photoBmp = null;

if (mImageCaptureUri != null) {

photoBmp = MediaStore.Images.Media.getBitmap(ac.getContentResolver(), mImageCaptureUri);

}

但是Media.getBitmap这个方法获取已知uri图片的方式并不可取,咱来看看Media.getBitmap()方法的源码:

[java] view
plain copy







public static final Bitmap getBitmap(ContentResolver cr, Uri url)

throws FileNotFoundException, IOException {

InputStream input = cr.openInputStream(url);

Bitmap bitmap = BitmapFactory.decodeStream(input);

input.close();

return bitmap;

}

其实它很简单很粗暴,返回的是原始大小的bitmap,当图库选择的图片很大时程序极有可能会报OOM。

为了避免OOM,咱们需要改进该方法,在 BitmapFactory.decodeStream 之前压缩图片,以下是我改进后的代码:

在onActivityResult中调用

[java] view
plain copy







Uri mImageCaptureUri = data.getData();

Bitmap photoBmp = null;

if (mImageCaptureUri != null) {

photoBmp = getBitmapFormUri(ac, mImageCaptureUri);

}

[java] view
plain copy







/**

* 通过uri获取图片并进行压缩

*

* @param uri

*/

public static Bitmap getBitmapFormUri(Activity ac, Uri uri) throws FileNotFoundException, IOException {

InputStream input = ac.getContentResolver().openInputStream(uri);

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

onlyBoundsOptions.inJustDecodeBounds = true;

onlyBoundsOptions.inDither = true;//optional

onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional

BitmapFactory.decodeStream(input, null, onlyBoundsOptions);

input.close();

int originalWidth = onlyBoundsOptions.outWidth;

int originalHeight = onlyBoundsOptions.outHeight;

if ((originalWidth == -1) || (originalHeight == -1))

return null;

//图片分辨率以480x800为标准

float hh = 800f;//这里设置高度为800f

float ww = 480f;//这里设置宽度为480f

//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可

int be = 1;//be=1表示不缩放

if (originalWidth > originalHeight && originalWidth > ww) {//如果宽度大的话根据宽度固定大小缩放

be = (int) (originalWidth / ww);

} else if (originalWidth < originalHeight && originalHeight > hh) {//如果高度高的话根据宽度固定大小缩放

be = (int) (originalHeight / hh);

}

if (be <= 0)

be = 1;

//比例压缩

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

bitmapOptions.inSampleSize = be;//设置缩放比例

bitmapOptions.inDither = true;//optional

bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional

input = ac.getContentResolver().openInputStream(uri);

Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);

input.close();

return compressImage(bitmap);//再进行质量压缩

}

* 质量压缩方法

*

* @param image

* @return

*/

public static Bitmap compressImage(Bitmap image) {

ByteArrayOutputStream baos = new ByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中

int options = 100;

while (baos.toByteArray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩

baos.reset();//重置baos即清空baos

//第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差 ,第三个参数:保存压缩后的数据的流

image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中

options -= 10;//每次都减少10

}

ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中

Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片

return bitmap;

}

OOM的问题解决了,但是又碰到另外一个问题,用三星手机拍照或者选择照片后返回来的图片居然转了90度,接着改。

在onActivityResult中的代码进行改进:

[java] view
plain copy







Uri originalUri = null;

File file = null;

if (null != data && data.getData() != null) {

originalUri = data.getData();

file = getFileFromMediaUri(ac, originalUri);

}

Bitmap photoBmp = getBitmapFormUri(ac, Uri.fromFile(file));

int degree = getBitmapDegree(file.getAbsolutePath());

/**

* 把图片旋转为正的方向

*/

Bitmap newbitmap = rotateBitmapByDegree(photoBmp, degree);

[java] view
plain copy







/**

* 通过Uri获取文件

* @param ac

* @param uri

* @return

*/

public static File getFileFromMediaUri(Context ac, Uri uri) {

if(uri.getScheme().toString().compareTo("content") == 0){

ContentResolver cr = ac.getContentResolver();

Cursor cursor = cr.query(uri, null, null, null, null);// 根据Uri从数据库中找

if (cursor != null) {

cursor.moveToFirst();

String filePath = cursor.getString(cursor.getColumnIndex("_data"));// 获取图片路径

cursor.close();

if (filePath != null) {

return new File(filePath);

}

}

}else if(uri.getScheme().toString().compareTo("file") == 0){

return new File(uri.toString().replace("file://",""));

}

return null;

}

[java] view
plain copy







/**

* 读取图片的旋转的角度

*

* @param path 图片绝对路径

* @return 图片的旋转角度

*/

public static int getBitmapDegree(String path) {

int degree = 0;

try {

// 从指定路径下读取图片,并获取其EXIF信息

ExifInterface 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;

}

} catch (IOException e) {

e.printStackTrace();

}

return degree;

}

[java] view
plain copy







/**

* 将图片按照某个角度进行旋转

*

* @param bm 需要旋转的图片

* @param degree 旋转角度

* @return 旋转后的图片

*/

public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {

Bitmap returnBm = null;

// 根据旋转角度,生成旋转矩阵

Matrix matrix = new Matrix();

matrix.postRotate(degree);

try {

// 将原始图片按照旋转矩阵进行旋转,并得到新的图片

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: