拍照及选择照片略。
在onActivityResult方法里通过Intent的getData方法获取的数据转换成bitmap并显示在界面上,有时候会有取不到数据,或者显示的bitmap会非常小,如果将bitmap保存到sd卡后会发现,图片的分辨率很低,并且图片大小也是经过压缩的,不管将相机的像素设置多高,最后通过这种方式返回的bitmap总是经过压缩了的。如果想获得理想的照片大小和分辨率改如何处理呢?
另外官方文档中有说明,Android系统分配给每个应用的最大内存是16M,所以,系统为了防止应用内存占用过大,对于在应用内通过相机拍摄的图片最终返回来的结果进行了压缩,压缩后的图片变得很小,通过之前说的getData的方式只能满足比如显示个头像这样的需求。
拍照时,将拍得的照片先保存在本地,通过修改之前的代码如下:
Intent intent = new Intent( "android.media.action.IMAGE_CAPTURE");imageUri = Uri.fromFile(new File(Environment .getExternalStorageDirectory(), "photo.jpg")); // 指定照片保存路径(SD卡),photo.jpg为一个临时文件,每次拍照后这个图片都会被替换(未压缩) intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);startActivityForResult(intent, CODE_TAKE_PHOTO);
在onActivityResult中:
if(requestCode == TAKE&& resultCode == RESULT_OK){ startPhotoZoom(imageUri);//进行图片的剪切操作 }
private void startPhotoZoom(Uri uri) { try { // 获取系统时间 然后将裁剪后的图片保存至指定的文件夹 SimpleDateFormat sDateFormat = new SimpleDateFormat( "yyyyMMddhhmmss"); String address = sDateFormat.format(new java.util.Date()); if (!FileUtils.isFileExist("")) { FileUtils.createSDDir(""); } Log.d("TAG", "path = " + FileUtils.SDPATH + address + ".JPEG"); Uri imageUri = Uri.parse("file://" + FileUtils.SDPATH + address + ".JPEG"); // 执行剪切得到正方形,图片的路径 path_original = FileUtils.SDPATH + address + ".JPEG"; final Intent intent = new Intent("com.android.camera.action.CROP"); // 照片URL地址 intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 480); intent.putExtra("outputY", 480); // 输出路径 intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); // 输出格式 intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); // 不启用人脸识别 intent.putExtra("noFaceDetection", false); intent.putExtra("return-data", false); startActivityForResult(intent, CUT_PHOTO_REQUEST_CODE); } catch (IOException e) { e.printStackTrace(); } }
剪切返回后在onActivityResult中进行压缩,然后显示到ImageView控件上。
为什么要压缩呢,因为即使是已经截图了的图片,也可能图片还是过大,控件无法显示图片内容。压缩之后的文件保存在path路径所在的文件中。
if (requestCode == CUT_PHOTO_REQUEST_CODE && resultCode == RESULT_OK) { Bitmap smallBitmap = null; try { smallBitmap = BitmapUtil.revitionImageSize(path_original, //压缩Bitmap得到smallBitmap n_Bitmap_size_show); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } iv_storelogo.setImageBitmap(smallBitmap); path = Environment.getExternalStorageDirectory() + "/photo.jpg"; File file = new File(path); if (file.exists()) { file.delete(); } FileOutputStream fOut = null; try { fOut = new FileOutputStream(new File(path)); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } smallBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);// 把Bitmap对象解析成流,写到文件中}
接下来我把BitmapUtil文件的源码贴出来,供大家参考。也就是压缩技术
public class BitmapUtil { private static final int STROKE_WIDTH = 4; /** * 压缩图片到指定大小 * * @param path * @param size * 图片的大小 * @return * @throws IOException */ public static Bitmap revitionImageSize(String path, int size) throws IOException { BufferedInputStream in = new BufferedInputStream(new FileInputStream( new File(path))); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // Bitmap btBitmap=BitmapFactory.decodeFile(path); // System.out.println("原尺寸高度:"+btBitmap.getHeight()); // System.out.println("原尺寸宽度:"+btBitmap.getWidth()); BitmapFactory.decodeStream(in, null, options); in.close(); int i = 0; Bitmap bitmap = null; while (true) { // 这一步是根据要设置的大小,使宽和高都能满足 if ((options.outWidth >> i <= size) && (options.outHeight >> i <= size)) { // 重新取得流,注意:这里一定要再次加载,不能二次使用之前的流! in = new BufferedInputStream( new FileInputStream(new File(path))); // 这个参数表示 新生成的图片为原始图片的几分之一。 options.inSampleSize = (int) Math.pow(2.0D, i); // 这里之前设置为了true,所以要改为false,否则就创建不出图片 options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeStream(in, null, options); break; } i += 1; } // 当机型为三星时图片翻转 // bitmap = Photo.photoAdapter(path, bitmap); // System.out.println("-----压缩后尺寸高度:" + bitmap.getHeight()); // System.out.println("-----压缩后尺寸宽度度:" + bitmap.getWidth()); return bitmap; }/** * 根据文件名得到,Bitmap对象 * @param url 文件的路径全名 * @return */ public static Bitmap getLoacalBitmap(String url) { try { FileInputStream fis = new FileInputStream(url); return BitmapFactory.decodeStream(fis); // /把流转化为Bitmap图片 } catch (FileNotFoundException e) { e.printStackTrace(); return null; } } /** * * @param x * 图像的宽度 * @param y * 图像的高度 * @param image * 源图片 * @param outerRadiusRat * 圆角的大小 * @return 圆角图片 */ public static Bitmap createFramedPhoto(int x, int y, Bitmap image, float outerRadiusRat) { // 根据源文件新建一个darwable对象 Drawable imageDrawable = new BitmapDrawable(image); // 新建一个新的输出图片 Bitmap output = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); // 新建一个矩形 RectF outerRect = new RectF(0, 0, x, y); // 产生一个红色的圆角矩形 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.RED); canvas.drawRoundRect(outerRect, outerRadiusRat, outerRadiusRat, paint); // 将源图片绘制到这个圆角矩形上 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); imageDrawable.setBounds(0, 0, x, y); canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); imageDrawable.draw(canvas); canvas.restore(); return output; } /** * 生成圆角的Bitmap STROKE_WIDTH为白色圆圈的宽度 * * @param context * @param bitmap * @return */ public static Bitmap toRoundBitmap(Context context, Bitmap bitmap) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); float roundPx; float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom; if (width <= height) { roundPx = width / 2; top = 0; left = 0; bottom = width; right = width; height = width; dst_left = 0; dst_top = 0; dst_right = width; dst_bottom = width; } else { roundPx = height / 2; float clip = (width - height) / 2; left = clip; right = width - clip; top = 0; bottom = height; width = height; dst_left = 0; dst_top = 0; dst_right = height; dst_bottom = height; } Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888); Canvas canvas = new Canvas(output); final Paint paint = new Paint(); final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom); final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom); final RectF rectF = new RectF(dst); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(Color.BLUE); paint.setStrokeWidth(4); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, src, dst, paint); // 画白色圆圈 paint.reset(); paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(STROKE_WIDTH); paint.setAntiAlias(true); canvas.drawCircle(width / 2, width / 2, width / 2 - STROKE_WIDTH / 2, paint); return output; }}
希望对大家有所帮助。如果大家有问题,或者更好的建议,欢迎大家留言。