选择手机中的一张照片或拍照上传图片(超高清晰度)
2016-05-23 14:50
399 查看
本文借鉴了多位前辈的代码,在自己的项目使用中根据需求做了一些修改,为了以后再次使用类似功能的时候方便一些,特把主要的代码流程部分贴出来
首先在activity中定义几个常量
然后在你需要添加图片的操作里面加入如下选项
多选的操作需要跳一个自定义的activity,不在本文讨论,因为是直接使用的http://blog.csdn.net/books1958/article/details/41010077中的例子,只是稍作修改,想看多选操作的请移步
拍照会调用相机拍照后在内存卡根目录存一张临时图片,单选会选择一张图片后返回图片路径,这两个都是取的文件路径,而不是bitmap,因为要保证清晰度,最好是自己去重绘bitmap,特别是你需要切图的,切完之后不能直接返回bitmap,而是将切完之后的图保存成临时文件,然后重绘
拍完选完之后会自动调用当前activity的onActivityResult,在onActivityResult处理返回的图片
AddImg2DGV(newBitmap);方法是将得到的bitmap显示出来,isgood是用来判断是不是需要切图的,default中执行的是切图后的返回数据
切图后并没有返回bitmap而是把切图后的图作为一个临时文件存储了起来
切图代码:
根据路径取出缩小后的bitmap:
根据原始bitmap再次缩小:
有人要问为什么要这么写?
再贴一些关于biemap的各种操作方法:
Drawable转bitmap:
bitmap转Drawable:
InputStream流转bitmap:
byteArray转bitmap:
byteArray转Drawable:
bitmap转byteArray:
Drawable转byteArray:
图片Uri转路径:
首先在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 ""; } }
相关文章推荐
- 如何学习一门新技术(感想)
- Ubuntu下安装arm-linux-gnueabi-xxx编译器
- 20个优秀的前端框架
- win10 为了对电脑进行保护,已经阻止此应用 解决方法 亲测可用
- U-Mail邮件网关鉴伪防窃杜绝“家贼”
- HashMap 、TreeMap、Hashtable、LinkedHashMap
- OpenERP开发文档 2.1.模块开发
- hdu 2807 The Shortest Path(矩阵)
- 使用SharedPreferences做记住密码
- 从客户端 中检测到有潜在危险的Request.Form值
- 英文不好,学Unity3D,一件小事搞疯我--(二)
- Python读取PDF内容
- Hadoop MapReduce并行编程框架
- cocos2d-x项目实战
- arm交叉编译器gnueabi、none-eabi、arm-eabi、gnueabihf、gnueabi区别
- 【转】Android实现点击两次返回键退出
- 线程同步与锁
- Android RecyclerView实现瀑布流
- C语言中的static 详细分析
- leetcode.30. Substring with Concatenation of All Words