第一章 Android图像概述
1. 调用系统摄像头, onActivityResult中获取的图片是经过压缩之后的。一般比较小。
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(i, REQUEST_CODE_CAMERA);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CAMERA){
if (resultCode == RESULT_OK){
if (data != null) {
Bundle extras = data.getExtras();
Bitmap bmp = (Bitmap) extras.get("data");
mImageView.setImageBitmap(bmp);
}
}
}
}
2. 要获取更大的图像,可以使用BitmapFactory.Options进行缩放。
@NonNull
private BitmapFactory.Options getBitmapOptions() {
Display currentDisplay = getWindowManager().getDefaultDisplay();
int dw = currentDisplay.getWidth(); //最大宽度
int dh = currentDisplay.getHeight(); //最大高度
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true; //只解析大小,不解析图片
Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)dh); //高度比
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)dw); //宽度比
if (heightRatio > 1 && widthRatio > 1){
bmpFactoryOptions.inSampleSize = Math.max(widthRatio, heightRatio); //以压缩大的比例为最终缩放比例
// bmpFactoryOptions.inSampleSize = 8; //产生一幅大小是原始大小1/8的图像
}
bmpFactoryOptions.inJustDecodeBounds = false; //解析图片
return bmpFactoryOptions;
}
private void setImageFromSD(){
BitmapFactory.Options bmpFactoryOptions = getBitmapOptions();
Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
mImageView.setImageBitmap(bmp);
}
3. 保存原图,方法一,把图片保存到sd卡
//方法一: 保存图片到sd卡
imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "mypic.jpg";
File imageFile = new File(imageFilePath);
imageFileUri = Uri.fromFile(imageFile);
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
startActivityForResult(i, REQUEST_CODE_CAMERA);
注意:此时onActivityResult里面data就会为null。所以不能直接从data显示图片,而是要从文件显示。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CAMERA){
if (resultCode == RESULT_OK){
if (data != null) { //如果指定了MediaStore.EXTRA_OUTPUT, 则此处data为null
Bundle extras = data.getExtras();
Bitmap bmp = (Bitmap) extras.get("data");
mImageView.setImageBitmap(bmp);
}else{
BitmapFactory.Options bmpFactoryOptions = getBitmapOptions();
Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
mImageView.setImageBitmap(bmp);
}
}
}
}
4. 保存原图,方法二,使用MediaStore进行图像存储及元数据关联。
//方法二: 使用MediaStore和content resolver
ContentValues contentValues = new ContentValues(3);
contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "This is a test title");
contentValues.put(MediaStore.Images.Media.DESCRIPTION, "This is a test description");
contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
//此处有一个坑。 每次进拍照页面的时候,就已经insert了一个了。但是我实际可以不拍照就返回,这样就会有一个空的数据。所以要在onActivityResult里面判断,cancel的时候,要删掉
imageFileUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); //创建一个新的uri
imageFilePath = imageFileUri.getPath();
//如果需要更新一条已有的uri, 使用getContentResolver().update(imageFileUri, contentValues, null, null);
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
startActivityForResult(i, REQUEST_CODE_CAMERA);
由于每次点击拍照,都会insert一个记录,如果不拍照的话,就会有一条多余的数据了。所以在onActivityResult里面要判断,如果取消了,要删除那一条多余的数据。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CAMERA){
if (resultCode == RESULT_OK){
if (data != null) { //如果指定了MediaStore.EXTRA_OUTPUT, 则此处data为null
Bundle extras = data.getExtras();
Bitmap bmp = (Bitmap) extras.get("data");
mImageView.setImageBitmap(bmp);
}else{
//使用content resolver解析图片
BitmapFactory.Options bmpFactoryOptions = getBitmapOptions();
Bitmap bmp;
try {
bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpFactoryOptions);
mImageView.setImageBitmap(bmp);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}else{
//取消了的话,uri的新纪录也要删掉
getContentResolver().delete(imageFileUri, null, null);
}
}
}
5. 使用 Cursor 查询图片,用 ExifInterface 获取或设置图片信息
//最近三天的照片
mImageTitleTextView = (TextView)findViewById(R.id.imageTitleTextView);
mExifDescTextView = (TextView)findViewById(R.id.imageExifDescTextView);
String [] columns = {Media.DATA, Media._ID, Media.TITLE, Media.DISPLAY_NAME, Media.DATE_ADDED};
long threeDaysAgo = System.currentTimeMillis()/1000 - 3 * 24 * 60 * 60; //单位用秒,因为Media.DATE_ADDED的单位是秒
String [] whereValues = {String.valueOf(threeDaysAgo)};
final Cursor cursor = managedQuery(Media.EXTERNAL_CONTENT_URI, columns, Media.DATE_ADDED + " > ?", whereValues, Media.DATE_ADDED + " asc");
if (cursor.moveToFirst()){
setImageFromCursor(cursor);
}
mShowPrevButton = (Button)findViewById(R.id.showPicPrev);
mShowPrevButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (cursor.moveToPrevious()){
setImageFromCursor(cursor);
}else{
showToast(R.string.already_the_first);
}
}
});
mShowNextButton = (Button)findViewById(R.id.showPicNext);
mShowNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (cursor.moveToNext()) {
setImageFromCursor(cursor);
} else {
showToast(R.string.already_the_last);
}
}
});
private void setImageFromCursor(Cursor cursor){
int fileColumn = cursor.getColumnIndexOrThrow(Media.DATA);
int titleColumn = cursor.getColumnIndexOrThrow(Media.TITLE);
int displayColumn = cursor.getColumnIndexOrThrow(Media.DISPLAY_NAME);
String displayName = cursor.getString(titleColumn) + " - " + cursor.getString(displayColumn);
mImageTitleTextView.setText(displayName);
imageFilePath = cursor.getString(fileColumn);
File imageFile = new File(imageFilePath);
if (!imageFile.exists()){
//这是之前insert了一条记录,但是没有拍照产生的脏数据,删掉
int _idColumn = cursor.getColumnIndexOrThrow(Media._ID);
int _id = cursor.getInt(_idColumn);
getContentResolver().delete(Media.EXTERNAL_CONTENT_URI, Media._ID + " = ?", new String[]{String.valueOf(_id)});
mExifDescTextView.setText("");
mImageView.setImageBitmap(null);
return;
}
//EXIF 可交换的图像文件格式
try {
ExifInterface ei = new ExifInterface(imageFilePath);
String modelAttribute = ei.getAttribute(ExifInterface.TAG_MODEL);
String makeAttribute = ei.getAttribute(ExifInterface.TAG_MAKE);
String timeAttribute = ei.getAttribute(ExifInterface.TAG_DATETIME);
if (modelAttribute != null && makeAttribute != null){
mExifDescTextView.setText(String.format("%s %s %s", makeAttribute, modelAttribute, timeAttribute));
}else{
mExifDescTextView.setText("");
}
} catch (IOException e) {
e.printStackTrace();
}
Log.d("dhy", imageFilePath);
BitmapFactory.Options bmpFactoryOptions = getBitmapOptions();
Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
mImageView.setImageBitmap(bmp);
}