您的位置:首页 > 其它

选择手机中的一张照片或拍照上传图片(超高清晰度)

2016-05-23 14:50 399 查看
本文借鉴了多位前辈的代码,在自己的项目使用中根据需求做了一些修改,为了以后再次使用类似功能的时候方便一些,特把主要的代码流程部分贴出来

首先在activity中定义几个常量

private static final String IMAGE_UNSPECIFIED = "image/*";
private static final int TAKE_PICTURE = 0;//拍照
private static final int CHOOSE_PICTURE = 1;//手机内单选
private static final int MULTIPLE_CHOICE = 2;//手机内多选

private static final int SCALE = 5;// 照片缩小比例
//临时图片的位置,主要是为了得到tempUri
File tempFile = new File(Environment.getExternalStorageDirectory(), "temp.jpg");
Uri tempUri = Uri.fromFile(tempFile);


然后在你需要添加图片的操作里面加入如下选项

switch (position) {
case TAKE_PICTURE://拍照
Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri imageUri = Uri
.fromFile(new File(Environment.getExternalStorageDirectory(), "temp.jpg"));
// 指定照片保存路径(SD卡),image.jpg为一个临时文件,每次拍照后这个图片都会被替换
openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(openCameraIntent, TAKE_PICTURE);
break;

case CHOOSE_PICTURE://单选
Intent openAlbumIntent = new Intent(Intent.ACTION_GET_CONTENT);
openAlbumIntent.setType("image/*");
startActivityForResult(openAlbumIntent, CHOOSE_PICTURE);
break;
case MULTIPLE_CHOICE:// 多选
Intent intent = new Intent(AddGoodsActivity.this, PhotoWallActivity.class);
intent.putExtra("size", 8 - dgv_add_goods_imgs2.getChildCount());
startActivityForResult(intent, MULTIPLE_CHOICE);
break;
default:
break;
}


多选的操作需要跳一个自定义的activity,不在本文讨论,因为是直接使用的http://blog.csdn.net/books1958/article/details/41010077中的例子,只是稍作修改,想看多选操作的请移步

拍照会调用相机拍照后在内存卡根目录存一张临时图片,单选会选择一张图片后返回图片路径,这两个都是取的文件路径,而不是bitmap,因为要保证清晰度,最好是自己去重绘bitmap,特别是你需要切图的,切完之后不能直接返回bitmap,而是将切完之后的图保存成临时文件,然后重绘

拍完选完之后会自动调用当前activity的onActivityResult,在onActivityResult处理返回的图片

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
Bitmap bitmap = null;
Bitmap newBitmap = null;
switch (requestCode) {
case TAKE_PICTURE://拍照
if (isgood) {
startPhotoZoom(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/temp.jpg")));
} else {
// 将保存在本地的图片取出并缩小后显示在界面上
bitmap = ImageTools.getSmallBitmap(Environment.getExternalStorageDirectory() + "/temp.jpg");
newBitmap = ImageTools.zoomBitmap(bitmap,
bitmap.getWidth() / SCALE > 0 ? bitmap.getWidth() / SCALE : bitmap.getWidth(),
bitmap.getHeight() / SCALE > 0 ? bitmap.getHeight() / SCALE : bitmap.getHeight());
// 由于Bitmap内存占用较大,这里需要回收内存,否则会报out of memory异常
AddImg2DGV(newBitmap);
bitmap.recycle();
}
break;

case CHOOSE_PICTURE://单选
ContentResolver resolver = getContentResolver();
// 照片的原始资源地址
Uri originalUri = data.getData();
try {
// 使用ContentProvider通过URI获取原始图片
bitmap = MediaStore.Images.Media.getBitmap(resolver, originalUri);
if (bitmap != null) {
if (isgood) {
startPhotoZoom(Uri.fromFile(new File(getPath(originalUri))));
} else {
// 为防止原始图片过大导致内存溢出,这里先缩小原图显示,然后释放原始Bitmap占用的内存
newBitmap = ImageTools.zoomBitmap(bitmap,
bitmap.getWidth() / SCALE > 0 ? bitmap.getWidth() / SCALE : bitmap.getWidth(),
bitmap.getHeight() / SCALE > 0 ? bitmap.getHeight() / SCALE : bitmap.getHeight());
AddImg2DGV(newBitmap);
}
// 释放原始图片占用的内存,防止out of memory异常发生
bitmap.recycle();
}
} catch (Exception e) {
e.printStackTrace();
}
break;
case MULTIPLE_CHOICE:// 多选
ArrayList<String> paths = data.getStringArrayListExtra("paths");
for (int i = 0; i < paths.size(); i++) {
// 将保存在本地的图片取出并缩小后显示在界面上
bitmap=ImageTools.getSmallBitmap(paths.get(i));
newBitmap = ImageTools.zoomBitmap(bitmap,
bitmap.getWidth() / SCALE > 0 ? bitmap.getWidth() / SCALE : bitmap.getWidth(),
bitmap.getHeight() / SCALE > 0 ? bitmap.getHeight() / SCALE : bitmap.getHeight());
// 由于Bitmap内存占用较大,这里需要回收内存,否则会报out of memory异常
AddImg2DGV(newBitmap);
bitmap.recycle();
}
break;
default:
bitmap = ImageTools.getSmallBitmap(Environment.getExternalStorageDirectory() + "/temp.jpg");
AddImg2DGV(bitmap);
break;
}
}
}


AddImg2DGV(newBitmap);方法是将得到的bitmap显示出来,isgood是用来判断是不是需要切图的,default中执行的是切图后的返回数据

切图后并没有返回bitmap而是把切图后的图作为一个临时文件存储了起来

切图代码:

public void startPhotoZoom(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, IMAGE_UNSPECIFIED);
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 14);
intent.putExtra("aspectY", 10);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 640);
intent.putExtra("outputY", 450);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, tempUri);
startActivityForResult(intent, PHOTORESOULT);
}


根据路径取出缩小后的bitmap:

public static Bitmap getSmallBitmap(String path){
//new 出来一个bitmap的参数
BitmapFactory.Options options=new BitmapFactory.Options();
//设置为true,不会生成bitmao对象,只是读取尺寸和类型信息
options.inJustDecodeBounds=true;
BitmapFactory.decodeFile(path, options);
//得到这个比例   并赋予option里面的inSampleSize
options.inSampleSize = calculateInSampleSize(options, 450, 640);
//设置为false,即将要生成bitmap对象啦
options.inJustDecodeBounds = false;
//有了这个option,我们可以生成bitmap对象了
Bitmap bitmap=BitmapFactory.decodeFile(path, options);

return bitmap;

}


public static int calculateInSampleSize(BitmapFactory.Options options,int reqHeight,int reqWidth){
//得到原始图片宽高
int height=options.outHeight;
int width=options.outWidth;
//默认设置为1,即不缩放
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;
}
return inSampleSize;

}


根据原始bitmap再次缩小:
public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
float scaleWidth = ((float) width / w);
float scaleHeight = ((float) height / h);
matrix.postScale(scaleWidth, scaleHeight);
Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
return newbmp;
}


有人要问为什么要这么写?

ImageTools.zoomBitmap(bitmap,
bitmap.getWidth() / SCALE > 0 ? bitmap.getWidth() / SCALE : bitmap.getWidth(),
bitmap.getHeight() / SCALE > 0 ? bitmap.getHeight() / SCALE : bitmap.getHeight());
因为这个长宽取的是int,如果图片本来的长宽就很小,除一下就会变0,这时候是会报异常的

再贴一些关于biemap的各种操作方法:

Drawable转bitmap:

public static Bitmap drawableToBitmap(Drawable drawable) {
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();

Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}


bitmap转Drawable:
public static Drawable bitmapToDrawable(Bitmap bitmap) {
return new BitmapDrawable(bitmap);
}


InputStream流转bitmap:

public static Bitmap inputStreamToBitmap(InputStream inputStream)
throws Exception {
return BitmapFactory.decodeStream(inputStream);
}


byteArray转bitmap:
public static Bitmap byteToBitmap(byte[] byteArray) {
if (byteArray.length != 0) {
return BitmapFactory
.decodeByteArray(byteArray, 0, byteArray.length);
} else {
return null;
}
}


byteArray转Drawable:

public static Drawable byteToDrawable(byte[] byteArray) {
ByteArrayInputStream ins = null;
if (byteArray != null) {
ins = new ByteArrayInputStream(byteArray);
}
return Drawable.createFromStream(ins, null);
}


bitmap转byteArray:

public static byte[] bitmapToBytes(Bitmap bm) {
byte[] bytes = null;
if (bm != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
bytes = baos.toByteArray();
}
return bytes;
}


Drawable转byteArray:

public static byte[] drawableToBytes(Drawable drawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
byte[] bytes = bitmapToBytes(bitmap);
;
return bytes;
}


图片Uri转路径:

public String getPath(Uri originalUri) {
try {
String[] proj = { MediaStore.Images.Media.DATA };

// 好像是Android多媒体数据库的封装接口,具体的看Android文档
Cursor cursor = managedQuery(originalUri, proj, null, null, null);
// 按我个人理解 这个是获得用户选择的图片的索引值
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
// 将光标移至开头 ,这个很重要,不小心很容易引起越界
cursor.moveToFirst();
// 最后根据索引值获取图片路径
return cursor.getString(column_index);
} catch (Exception e) {
return "";
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: