近期在做Android的项目,当中部分涉及到图像处理的内容.这里先讲述怎样调用Camera应用程序进行拍照,并截图和保存显示在ImageView控件中以及遇到的困难和解决方法.

    PS:作者购买了本《Android第一行代码 著:郭霖》,參照里面的内容完毕(推荐该书,前面的布局及应用很不错).网上这类资料许多,作者只分享给刚開始学习的人同一时候在线记录些内容,希望对大家有所帮助.

   首先,设置activity_main.xml为LinearLayout布局且 android:orientation="vertical"

<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TakePhoto Button" /> <ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />

   然后,在MainActivity.java文件中public class MainActivity extends Activity改动源码.加入自己定义变量:

//自己定义变量
public static final int TAKE_PHOTO = 1;
public static final int CROP_PHOTO = 2;
private Button takePhotoBn;
private ImageView showImage;
private Uri imageUri; //图片路径
private String filename; //图片名称

   加入函数实现点击拍照功能:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
takePhotoBn = (Button) findViewById(R.id.button1);
showImage = (ImageView) findViewById(R.id.imageView1);
//点击"Photo Button"button照相
takePhotoBn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//图片名称 时间命名
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date(System.currentTimeMillis());
filename = format.format(date);
//创建File对象用于存储拍照的图片 SD卡根文件夹
//File outputImage = new File(Environment.getExternalStorageDirectory(),"test.jpg");
//存储至DCIM目录
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
File outputImage = new File(path,filename+".jpg");
try {
if(outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
} catch(IOException e) {
e.printStackTrace();
}
//将File对象转换为Uri并启动照相程序
imageUri = Uri.fromFile(outputImage);
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); //照相
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //指定图片输出地址
startActivityForResult(intent,TAKE_PHOTO); //启动照相
//拍完照startActivityForResult() 结果返回onActivityResult()函数
}
}); if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}

   通过startActivityForResult和onActivityResult方法实现拍照截图和保存功能:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) {
Toast.makeText(MainActivity.this, "ActivityResult resultCode error", Toast.LENGTH_SHORT).show();
return;
}
switch(requestCode) {
case TAKE_PHOTO:
Intent intent = new Intent("com.android.camera.action.CROP"); //剪裁
intent.setDataAndType(imageUri, "image/*");
intent.putExtra("scale", true);
//设置宽高比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
//设置裁剪图片宽高
intent.putExtra("outputX", 340);
intent.putExtra("outputY", 340);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
Toast.makeText(MainActivity.this, "剪裁图片", Toast.LENGTH_SHORT).show();
//广播刷新相冊
Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intentBc.setData(imageUri);
this.sendBroadcast(intentBc);
startActivityForResult(intent, CROP_PHOTO); //设置裁剪參数显示图片至ImageView
break;
case CROP_PHOTO:
try {
//图片解析成Bitmap对象
Bitmap bitmap = BitmapFactory.decodeStream(
getContentResolver().openInputStream(imageUri));
Toast.makeText(MainActivity.this, imageUri.toString(), Toast.LENGTH_SHORT).show();
showImage.setImageBitmap(bitmap); //将剪裁后照片显示出来
} catch(FileNotFoundException e) {
e.printStackTrace();
}
break;
default:
break;
}
}

   
因为涉及到SD卡中写数据操作和Camera操作,须要在AndroidMainfest.xml文件里声明权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />

执行结果例如以下图所看到的:

       

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRWFzdG1vdW50/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="180" height="340">

    须要注意下面几个问题:

    1.拍照和截图都涉及到startActivityForResult和onActivityResult的交互操作.

startActivityForResult(
Intent intent, //Intent对象
int requestCode //>=0 当Activity结束时requestCode将归还在onActivityResult()中
)
onActivityResult(
int requestCode, //提供给onActivityResult,以确认返回的数据是从哪个Activity返回的
int resultCode, //由子Activity通过其setResult()方法返回 通常为RESULT_CANCELED或RESULT_OK
Intent data //一个Intent对象,带有返回的数据
)

当中onActivityResult的requestCode和startActivityForResult中的requestCode相相应.同一时候结合Intent意图实现拍照和截图,核心代码例如以下:(intent的參数设置省略)

    Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");

    startActivityForResult(intent,TAKE_PHOTO);

    Intent intent = new Intent("com.android.camera.action.CROP"); 

    startActivityForResult(intent, CROP_PHOTO);

    2.使用Android拍照保存在系统相冊,图库不能立马显示最新照片.解决方法是发送系统内置的广播去刷新相冊实现显示.代码例如以下:

Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intentBc.setData(imageUri);
this.sendBroadcast(intentBc);

    可能你会使用以下这条广播扫描整个SD卡,但4.4已禁止这种操作:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse(...)))

    參考资料 http://blog.csdn.net/xiaanming/article/details/8990627

    3.当执行程序是可能会发现结果图像显示非常小,当通过一个Intent意图触发时,Camera程序不会将全尺寸图像返回给主调活动,这样须要大量的内存,而移动设备内存会有一定限制.通常Camera将在返回的意图中返回一幅非常小的缩略图,大图可能会导致OOM问题.參考:《Android多媒体开发高级编程 著:Shawn Van Every》

    针对大图像Android提供BitmapFactory类,同意通过各种资源载入Bitmap图像.调用BitmapFactory.Options类能够定义怎样将Bitmap读入内存,当载入图像时,可设置BitmapFactory採样大小.并指定inSampleSize參数表明载入时结果Bitmap图像所占的比例.如inSampleSize=8表明产生一副大小为原始图像1/8的图像.參考以下代码:

if(resultCode==RESULT_OK) {
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels; //宽度
int height = dm.heightPixels ; //高度
//载入图像尺寸而不是图像本身
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true; //bitmap为null 仅仅是把图片的宽高放在Options里
Bitmap bitmap = BitmapFactory.decodeFile(imageUri.toString(), bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);
//设置图片压缩比例 假设两个比例大于1 图像一边将大于屏幕
if(heightRatio>1&&widthRatio>1) {
if(heightRatio>widthRatio) {
bmpFactoryOptions.inSampleSize = heightRatio;
}
else {
bmpFactoryOptions.inSampleSize = widthRatio;
}
}
//图像真正解码
bmpFactoryOptions.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(imageUri.toString(), bmpFactoryOptions);
showImage.setImageBitmap(bitmap); //将剪裁后照片显示出来
}

    4.使用nexus 4 剪裁图片后不能setImageBitmap显示在ImageView控件中,当中仅仅有保存button,没有剪裁button.測试发现没有返回RESULT_OK.这个问题不能解决.Why?

參考:Unable to Save Photo Edits

    最后希望文章对大家有所帮助,这是我学习Android图像处理部分的基础性文章与解决过程.下载地址:
http://download.csdn.net/detail/eastmount/8074833

參考资料和推荐博文:(都是很不错的资料-.-)

    《Android第一行代码》著郭霖 參考8.3 调用摄像头和相冊

    android拍照图片选取与图片剪裁 By:Lee_Allen 

    Android_照相机Camera_调用系统照相机返回data为空 By:strawberry2013    Android图片剪裁功能实心具体解释
By:小马


    Android开发 拍照、图片集保存照片技巧

    Android 拍照并显示在ImageView中(进阶)
By:leesa


    android调动系统的照相机并把照片显示在ImageView上

    cameraintent
data null in onActivityResult(int requestCode, int resultCode, Intentdata)


    Android高效载入大图、多图解决方式,有效避免程序OOM By:guolin

    Android相机、相冊获取图片显示并保存到SD卡
By:唐韧_Ryan


    android、获取本地图片|直接获取照相图片
By:zcljy0318


(By:Eastmount 2014-10-23 晚10点
http://blog.csdn.net/eastmount/)

最新文章

  1. 利用GBDT模型构造新特征
  2. Deprecated: Function split() is deprecated in ... 解决办法
  3. bootstrap精简教程
  4. OpenMp之false sharing
  5. [经典算法] 字符串搜索Boyer-Moore
  6. OpenID说明
  7. C字符串总结+字符串库实现(增,改,删,查):
  8. A WebBrowser Toy
  9. PAT甲级训练刷题代码记录
  10. Linux 软件包安装管理
  11. spring,property not found on type
  12. MAC地址表配置与绑定
  13. disk.go
  14. python的StringIO
  15. lua 5.3最简单plugin编写
  16. EF5.x Code First 一对多关联条件查询,Contains,Any,All
  17. Line云端全自动加好友机器人
  18. CodeForces - 831A Unimodal Array 模拟
  19. BestCoder Round #40 解题报告
  20. High-current supply uses standard three-terminal regulator

热门文章

  1. 【微信】微信小程序 获取本次场景值
  2. 为docker创建ubuntu带SSH的基础镜像
  3. django book用户认证学习
  4. 编译安装Nginx和php搭建KodExplorer网盘
  5. ecshop_商品描述远程图片自动本地化插件
  6. 前端存储之Web Sql Database
  7. [PWA] Show an Error when a POST or DELETE Fails in an Offline PWA
  8. Angular 学习笔记——sublime
  9. WCF 404.3 MIME 映射错误
  10. Fog of War小调研