选择相册、拍照,图片过大导致控件无法显示图片

拍照及选择照片略。

在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;
 }
}

希望对大家有所帮助。如果大家有问题,或者更好的建议,欢迎大家留言。

转载于:https://my.oschina.net/u/660536/blog/368662

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值