拍照及选择照片略。
在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;
}
}
希望对大家有所帮助。如果大家有问题,或者更好的建议,欢迎大家留言。