Android 拍照并显示在ImageView中(解决图片压缩失真的问题)
2015-11-02 21:35
656 查看
拍照后图片放ImageView中,ImageView中显示的是经过Android系统处理过的缩略图,很小。下面,我们来看看为什么拍照后从data里拿到的图片会小的呢?
在Activity中通过如下代码可以启动相机,然后在重写的onActivityResult方法中可以获取到返回的照片数据:
Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(openCameraIntent, TAKE_PICTURE);
问题来了,在onActivityResult方法里通过Intent的getData方法获取的数据转换成bitmap并显示在界面上,有时候会有取不到数据,或者显示的bitmap会非常小,如果将bitmap保存到sd卡后会发现,图片的分辨率很低,并且图片大小也是经过压缩的,不管将相机的像素设置多高,最后通过这种方式返回的bitmap总是经过压缩了的。如果想获得理想的照片大小和分辨率改如何处理呢?
那么为什么返回的图片是经过了压缩的?大家都知道,现在手机像素少则500W或800W,多则4KW(某亚),就拿常见的800W像素的相机拍出来的照片来说,分辨率大概在3200*2400左右,用800W像素拍出来大概就是这个分辨率,照片大小在2M左右。试想一下,在Android系统中bitmap占用4个字节,3200*2400*4=?,结果大家自己算算,如果为了一张图片,耗用这么大的内存,肯定是不合理的,并且,官方文档中有说明,Android系统分配给每个应用的最大内存是16M,所以,系统为了防止应用内存占用过大,对于在应用内通过相机拍摄的图片最终返回来的结果进行了压缩,压缩后的图片变得很小,通过之前说的getData的方式只能满足比如显示个头像这样的需求,如果要显示大图,就会出现模糊的情况。那如何获取清晰的大图呢?
1、页面布局中ImageView的定义:
注意:
android:layout_width=”wrap_content”和android:layout_height=”wrap_content”,否则你按比例缩放后的图片放在这也有可能会虚的。
2、调用android系统的拍照:拍照时,将拍得的照片先保存在本地(未缩小):
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri
imageUri =Uri.fromFile(newFile(Environment.getExternalStorageDirectory(),”workupload.jpg”));
//指定照片保存路径(SD卡),workupload.jpg为一个临时文件,每次拍照后这个图片都会被替换
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(cameraIntent, REQUEST_CODE);
3、拍照后,自动跳转到onActivityResult()方法,处理照片信息;
在onActivityResult方法中再将图片取出,并经过缩小处理再显示在界面上或上传给服务器(压缩比例自定义)
4、由于Android给bitmap分配的内存最大不超过8M,所以对使用完的较大的Bitmap要释放内存,调用其recycle()方法即可。然后将缩小(缩小方法在Demo源码中有)后的bitmap显示在界面上或保存到SD卡,至于之前保存的原图,可以删掉,也可以放在那,下次拍照时,这张原图就会被下一张照片覆盖,所以SD卡上使用只有一张临时图片,占用也不是很大。
上面是我的处理方法,虽然不是最好,但是帮我解决了这个需求。
补充:上面ImageThumbnail类中方法调用的实现:
在Activity中通过如下代码可以启动相机,然后在重写的onActivityResult方法中可以获取到返回的照片数据:
Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(openCameraIntent, TAKE_PICTURE);
问题来了,在onActivityResult方法里通过Intent的getData方法获取的数据转换成bitmap并显示在界面上,有时候会有取不到数据,或者显示的bitmap会非常小,如果将bitmap保存到sd卡后会发现,图片的分辨率很低,并且图片大小也是经过压缩的,不管将相机的像素设置多高,最后通过这种方式返回的bitmap总是经过压缩了的。如果想获得理想的照片大小和分辨率改如何处理呢?
那么为什么返回的图片是经过了压缩的?大家都知道,现在手机像素少则500W或800W,多则4KW(某亚),就拿常见的800W像素的相机拍出来的照片来说,分辨率大概在3200*2400左右,用800W像素拍出来大概就是这个分辨率,照片大小在2M左右。试想一下,在Android系统中bitmap占用4个字节,3200*2400*4=?,结果大家自己算算,如果为了一张图片,耗用这么大的内存,肯定是不合理的,并且,官方文档中有说明,Android系统分配给每个应用的最大内存是16M,所以,系统为了防止应用内存占用过大,对于在应用内通过相机拍摄的图片最终返回来的结果进行了压缩,压缩后的图片变得很小,通过之前说的getData的方式只能满足比如显示个头像这样的需求,如果要显示大图,就会出现模糊的情况。那如何获取清晰的大图呢?
1、页面布局中ImageView的定义:
<ImageView android:id="@+id/staff_add_photo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="centerCrop" android:layout_gravity="center_horizontal" android:adjustViewBounds="true" android:visibility="gone" android:layout_marginLeft="@dimen/between_space" android:layout_marginRight="@dimen/between_space" android:contentDescription="@string/staff_camora"/>
注意:
android:layout_width=”wrap_content”和android:layout_height=”wrap_content”,否则你按比例缩放后的图片放在这也有可能会虚的。
2、调用android系统的拍照:拍照时,将拍得的照片先保存在本地(未缩小):
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri
imageUri =Uri.fromFile(newFile(Environment.getExternalStorageDirectory(),”workupload.jpg”));
//指定照片保存路径(SD卡),workupload.jpg为一个临时文件,每次拍照后这个图片都会被替换
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(cameraIntent, REQUEST_CODE);
3、拍照后,自动跳转到onActivityResult()方法,处理照片信息;
在onActivityResult方法中再将图片取出,并经过缩小处理再显示在界面上或上传给服务器(压缩比例自定义)
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode != Activity.RESULT_OK){//result is not correct return; }else{ if(requestCode == REQUEST_CODE ){ //将保存在本地的图片取出并缩小后显示在界面上 Bitmap camorabitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/workupload.jpg"); if(null != camorabitmap ){ // 下面这两句是对图片按照一定的比例缩放,这样就可以完美地显示出来。 int scale = ImageThumbnail.reckonThumbnail(camorabitmap.getWidth(),camorabitmap.getHeight(), 500, 600); bitMap = ImageThumbnail.PicZoom(camorabitmap, camorabitmap.getWidth() / scale,camorabitmap.getHeight() / scale); //由于Bitmap内存占用较大,这里需要回收内存,否则会报out of memory异常 camorabitmap.recycle(); //将处理过的图片显示在界面上,并保存到本地 photoImgView.setVisibility(View.VISIBLE); photoImgView.setImageBitmap(bitMap); photoLocalPath = ImageThumbnail.savaPhotoToLocal(data, bitMap); } } } }
4、由于Android给bitmap分配的内存最大不超过8M,所以对使用完的较大的Bitmap要释放内存,调用其recycle()方法即可。然后将缩小(缩小方法在Demo源码中有)后的bitmap显示在界面上或保存到SD卡,至于之前保存的原图,可以删掉,也可以放在那,下次拍照时,这张原图就会被下一张照片覆盖,所以SD卡上使用只有一张临时图片,占用也不是很大。
上面是我的处理方法,虽然不是最好,但是帮我解决了这个需求。
补充:上面ImageThumbnail类中方法调用的实现:
public static int reckonThumbnail(int oldWidth, int oldHeight, int newWidth, int newHeight) { if ((oldHeight > newHeight && oldWidth > newWidth) || (oldHeight <= newHeight && oldWidth > newWidth)) { int be = (int) (oldWidth / (float) newWidth); if (be <= 1) be = 1; return be; } else if (oldHeight > newHeight && oldWidth <= newWidth) { int be = (int) (oldHeight / (float) newHeight); if (be <= 1) be = 1; return be; } return 1; } public static Bitmap PicZoom(Bitmap bmp, int width, int height) { int bmpWidth = bmp.getWidth(); int bmpHeght = bmp.getHeight(); Matrix matrix = new Matrix(); matrix.postScale((float) width / bmpWidth, (float) height / bmpHeght); return Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeght, matrix, true); } public static String savaPhotoToLocal(Intent data,Bitmap btp){ // 如果文件夹不存在则创建文件夹,并将bitmap图像文件保存 File rootdir = Environment.getExternalStorageDirectory(); String imagerDir = rootdir.getPath() + WorkUpload.SDCARD_PATH; File dirpath = createDir(imagerDir); String filename = System.currentTimeMillis() + ".jpg"; File tempFile = new File(dirpath, filename); String filePath = tempFile.getAbsolutePath(); try { // 将bitmap转为jpg文件保存 FileOutputStream fileOut = new FileOutputStream(tempFile); btp.compress(CompressFormat.JPEG, 100, fileOut); } catch (FileNotFoundException e) { e.printStackTrace(); } return filePath; }
相关文章推荐
- Java 图片压缩实现思路及代码
- Android中3种图片压缩处理方法
- android图片压缩的3种方法实例
- java实现文件上传下载和图片压缩代码示例
- php商品图片压缩
- XenDesktop&XenApp发布Photoshop图片失真
- android图片压缩总结
- 关于网站App缩略图的一些思考
- android处理图片方法
- 在RHEL5中安装grunt-contrib-imagemin,并与J2EE集成
- Android图片压缩
- IOS开发基础之——图像压缩成指定大小(高度/宽度)
- Android 框架练成 教你打造高效的图片加载框架
- 手机通过页面调用摄相头或选择照片压缩后并显示
- android 比较靠谱的图片压缩
- Android-Universal-Image-Loader 图片异步加载类库使用方法
- 实现图片的任意压缩,可以根据宽度或者高度进行
- android拍照,并获取压缩后的图片。
- struts2多文件上传(修改名称、压缩图片、删除图片)
- android开发之就本地和网络图片的压缩以及缓存详解