Android Camera拍照实现
来源:互联网 发布:大数据和股票有哪些 编辑:程序博客网 时间:2024/03/29 07:45
既然都已经学了如何打开Camera,那么就顺着官方API的引导,实现一下Camera拍照的功能吧!
百度了一下Android Camera拍照的功能实现,其中yanzi1225627是我认为写得比较好的,所以我也是照着他的思路实现的拍照功能实现,但是有个问题是,我按博主的代码实现后,SurfaceView中预览不到,其中的原因在我上一篇博文有讲解到,所以在这里,我对其代码进行了简单的修改后,就没有问题了!
首先是布局文件,我并没有作任何修改:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="org.hwm.app.photograph.PhotographActivity" > <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <org.hwm.app.photograph.PhotographSurface android:id="@+id/surfaceview" android:layout_width="0dip" android:layout_height="0dip" /> </FrameLayout> <ImageButton android:id="@+id/btn_shutter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="10dip"/> </RelativeLayout>
其次是AndroidManifest.xml文件,需要注意的是,在使用autofocus时,应该再加个android:required="false",不然事实证明,并不能聚焦,所以修改如下:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.hwm.app.photograph" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" android:required="false"/> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".PhotographActivity" android:label="@string/app_name" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
下面是Java代码的实现部分,先让我们来看一下工具类的实现,工具类还是一模一样的:
1. ImageUtil.java : 对得到的照片进行旋转处理。
package org.hwm.app.util;import android.graphics.Bitmap;import android.graphics.Matrix;public class ImageUtil { /** * Rotate Bitmap * @param b * @param rotateDegree * @return */ public static Bitmap getRotateBitmap(Bitmap b, float rotateDegree){ Matrix matrix = new Matrix(); matrix.postRotate((float)rotateDegree); Bitmap rotaBitmap = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, false); return rotaBitmap; } }
2. FileUtil.java:设置照片的保存路径。
package org.hwm.app.util;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import android.graphics.Bitmap;import android.os.Environment;import android.util.Log;public class FileUtil { private static final String TAG = "FileUtil"; private static final File parentPath = Environment.getExternalStorageDirectory(); private static String savePath = ""; private static final String SAVE_FOLDER_NAME = "Photograph"; /**Initiate savePath * @return */ private static String initPath(){ if(savePath.equals("")){ savePath = parentPath.getAbsolutePath()+"/" + SAVE_FOLDER_NAME; File f = new File(savePath); if(!f.exists()){ f.mkdir(); } } return savePath; } /**save Bitmap to sdcard * @param b */ public static void saveBitmap(Bitmap b){ String path = initPath(); long dataTake = System.currentTimeMillis(); String jpegName = path + "/" + dataTake +".jpg"; Log.i(TAG, "saveBitmap:jpegName = " + jpegName); try { FileOutputStream fos = new FileOutputStream(jpegName); BufferedOutputStream bos = new BufferedOutputStream(fos); b.compress(Bitmap.CompressFormat.JPEG, 100, bos); bos.flush(); bos.close(); Log.i(TAG, "saveBitmap successed"); } catch (IOException e) { // TODO Auto-generated catch block Log.i(TAG, "saveBitmap failed"); e.printStackTrace(); } } }
3. DisplayUtil
package org.hwm.app.util;import android.content.Context;import android.graphics.Point;import android.util.DisplayMetrics;import android.util.Log;public class DisplayUtil { private static final String TAG = "DisplayUtil"; /** * dip to px * @param context * @param dipValue * @return */ public static int dip2px(Context context, float dipValue){ final float scale = context.getResources().getDisplayMetrics().density; return (int)(dipValue * scale + 0.5f); } /** * px to dip * @param context * @param pxValue * @return */ public static int px2dip(Context context, float pxValue){ final float scale = context.getResources().getDisplayMetrics().density; return (int)(pxValue / scale + 0.5f); } /** * Obtain the width and height of screen * @param context * @return */ public static Point getScreenMetrics(Context context){ DisplayMetrics dm =context.getResources().getDisplayMetrics(); int w_screen = dm.widthPixels; int h_screen = dm.heightPixels; Log.i(TAG, "Screen---Width = " + w_screen + " Height = " + h_screen + " densityDpi = " + dm.densityDpi); return new Point(w_screen, h_screen); } /** * Obtain the rate of width and height * @param context * @return */ public static float getScreenRate(Context context){ Point P = getScreenMetrics(context); float H = P.y; float W = P.x; return (H/W); } }
4. CamParamUtil.java :解析Camera的参数
package org.hwm.app.util;import java.util.Collections;import java.util.Comparator;import java.util.List;import android.hardware.Camera;import android.hardware.Camera.Size;import android.util.Log;public class CamParaUtil { private static final String TAG = "CamParaUtil"; private CameraSizeComparator sizeComparator = new CameraSizeComparator(); private static CamParaUtil myCamPara = null; private CamParaUtil(){ } public static CamParaUtil getInstance(){ if(myCamPara == null){ myCamPara = new CamParaUtil(); } return myCamPara; } public Size getPropPreviewSize(List<Camera.Size> list, float th, int minWidth){ Collections.sort(list, sizeComparator); int i = 0; for(Size s:list){ if((s.width >= minWidth) && equalRate(s, th)){ Log.i(TAG, "PreviewSize:w = " + s.width + "h = " + s.height); break; } i++; } if(i == list.size()){ i = 0;//set the minimum one } return list.get(i); } public Size getPropPictureSize(List<Camera.Size> list, float th, int minWidth){ Collections.sort(list, sizeComparator); int i = 0; for(Size s:list){ if((s.width >= minWidth) && equalRate(s, th)){ Log.i(TAG, "PictureSize : w = " + s.width + "h = " + s.height); break; } i++; } if(i == list.size()){ i = 0;//set the minimum one } return list.get(i); } public boolean equalRate(Size s, float rate){ float r = (float)(s.width)/(float)(s.height); if(Math.abs(r - rate) <= 0.03) { return true; } else{ return false; } } public class CameraSizeComparator implements Comparator<Camera.Size>{ @Override public int compare(Size lhs, Size rhs) { if(lhs.width == rhs.width){ return 0; } else if(lhs.width > rhs.width){ return 1; } else{ return -1; } } } /**Print previewSizes * @param params */ public void printSupportPreviewSize(Camera.Parameters params){ List<Size> previewSizes = params.getSupportedPreviewSizes(); for(int i=0; i< previewSizes.size(); i++){ Size size = previewSizes.get(i); Log.i(TAG, "previewSizes:width = "+size.width+" height = "+size.height); } } /**Print pictureSizes * @param params */ public void printSupportPictureSize(Camera.Parameters params){ List<Size> pictureSizes = params.getSupportedPictureSizes(); for(int i=0; i< pictureSizes.size(); i++){ Size size = pictureSizes.get(i); Log.i(TAG, "pictureSizes:width = "+ size.width +" height = " + size.height); } } /**Print supportFocusMode * @param params */ public void printSupportFocusMode(Camera.Parameters params){ List<String> focusModes = params.getSupportedFocusModes(); for(String mode : focusModes){ Log.i(TAG, "focusModes--" + mode); } } }
5. PhotographSurface.java :和原博主的SurfaceView不同,类中,我通过setCamera方法为PhotographSurface类传入Camera对象,并在surfaceCreated的方法中为传入的Camera设置Holder,这也是我和原博主的主要不同。
package org.hwm.app.photograph;import android.content.Context;import android.hardware.Camera;import android.util.AttributeSet;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;public class PhotographSurface extends SurfaceView implements SurfaceHolder.Callback{private static final String TAG = "PhotographSurface";private SurfaceHolder mSurfaceHolder;private Camera mCamera;public PhotographSurface(Context context) {super(context);init();}/** if you want to create a View in the layout, you have to implement the constructor with two parameters **/public PhotographSurface(Context context, AttributeSet attrs) {super(context, attrs);init();}public PhotographSurface(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init();}private void init() {mSurfaceHolder = getHolder();mSurfaceHolder.addCallback(this); //mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);}public void setCamera(Camera camera) {mCamera = camera;}@Overridepublic void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {// TODO Auto-generated method stub}@Overridepublic void surfaceCreated(SurfaceHolder arg0) { try { if( mCamera != null ) { mCamera.setPreviewDisplay( mSurfaceHolder ); } } catch( Exception exception ) { Log.d( TAG, "SurfaceCreated failed" ); }}@Overridepublic void surfaceDestroyed(SurfaceHolder arg0) {// TODO Auto-generated method stub}}
6. SingleCamera.java:Camera的单例模式,这里我去掉了Camera在open时的回调,主要是因为,我原博主在回调的方法中就开始startPreview了,而我需要在这之间为创建的PhotographSurface对象传入Camera,并设置Holder,这样才能在PhotographSurface中正常的预览。
package org.hwm.app.photograph;import org.hwm.app.util.CamParaUtil;import org.hwm.app.util.FileUtil;import org.hwm.app.util.ImageUtil;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.ImageFormat;import android.hardware.Camera;import android.hardware.Camera.PictureCallback;import android.hardware.Camera.ShutterCallback;import android.util.Log;public class SingleCamera {private static final String TAG = "SingleCamera";private static SingleCamera cameraInstance;private Camera mCamera;private Camera.Parameters mCameraParams;private boolean isPreviewing = false;private SingleCamera(){};public static SingleCamera getInstance(){if (cameraInstance == null) {synchronized(SingleCamera.class) {cameraInstance = new SingleCamera();}}return cameraInstance;}public void doOpenCamera(){Log.i(TAG, "Camera open...");mCamera = Camera.open();}/** * start preview */public void doStartPreview(float previewRate){Log.i(TAG, "start preview...");if (isPreviewing) {mCamera.stopPreview();return;}if (mCamera != null) {// get Camera's parameters and reset itmCameraParams = mCamera.getParameters();mCameraParams.setPictureFormat(ImageFormat.JPEG);Camera.Size pictureSize = CamParaUtil.getInstance().getPropPictureSize(mCameraParams.getSupportedPictureSizes(), previewRate, 800); Camera.Size previewSize = CamParaUtil.getInstance().getPropPreviewSize(mCameraParams.getSupportedPreviewSizes(), previewRate, 800);mCameraParams.setPictureSize(pictureSize.width, pictureSize.height);mCameraParams.setPreviewSize(previewSize.width, previewSize.height);mCamera.setParameters(mCameraParams);// set display orientationmCamera.setDisplayOrientation(90);// start previewmCamera.startPreview();isPreviewing = true;}}/** * stop preview, and release Camera that other app can use it */public void doStopCamera() {if (mCamera != null) {mCamera.setPreviewCallback(null);mCamera.stopPreview();isPreviewing = false;mCamera.release();mCamera = null;}}/** * photoghraph */public void doTakePicture() {if (isPreviewing && (mCamera != null)) {mCamera.takePicture(mShutterCallback, mPictureCallback, mJpegPictureCallback);}}// the callback for image capture moment, or nullShutterCallback mShutterCallback = new ShutterCallback() {@Overridepublic void onShutter() {Log.i(TAG, "ShutterCallback...");}};// the callback for raw (uncompressed) image data, or nullPictureCallback mPictureCallback = new PictureCallback() {@Overridepublic void onPictureTaken(byte[] arg0, Camera arg1) {Log.i(TAG, "PictureCallback...");}};// the callback for JPEG image data. set the path to save picturePictureCallback mJpegPictureCallback = new PictureCallback() {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {Log.i(TAG, "JpegPictureCallback...");Bitmap b = null;// to take a picture, we have to stop previewif (null != data) {b = BitmapFactory.decodeByteArray(data, 0, data.length);mCamera.stopPreview();isPreviewing = false;}// save the picture to sdcardif (null != b) {Bitmap rotateBitmap = ImageUtil.getRotateBitmap(b, 90f);FileUtil.saveBitmap(rotateBitmap);}// after saving picture, start previewmCamera.startPreview();isPreviewing = true;}};public Camera getCamera() {return this.mCamera;}}
7. PhotographActivity.java:在我的Activity中,大家可以看到我在执行doOpenCamera()和doStartPreview()方法之间,为SurfaceView传入了Camera。
package org.hwm.app.photograph;import org.hwm.app.util.DisplayUtil;import android.app.Activity;import android.graphics.Point;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup.LayoutParams;import android.widget.ImageButton;public class PhotographActivity extends Activity {private PhotographSurface mCameraSurface;private ImageButton btn_shutter;private float previewRate = -1f; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_photograph); initView(); initParams(); btn_shutter.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_shutter :SingleCamera.getInstance().doTakePicture();break;default :break;}} }); }private void initView() { mCameraSurface = (PhotographSurface) findViewById(R.id.surfaceview); btn_shutter = (ImageButton) findViewById(R.id.btn_shutter);} private void initParams() { LayoutParams params = mCameraSurface.getLayoutParams(); Point p = DisplayUtil.getScreenMetrics(this); params.width = p.x; params.height = p.y; previewRate = DisplayUtil.getScreenRate(this); mCameraSurface.setLayoutParams(params); LayoutParams p2 = btn_shutter.getLayoutParams(); p2.width = DisplayUtil.dip2px(this, 80); p2.height = DisplayUtil.dip2px(this, 80);; btn_shutter.setLayoutParams(p2); }@Override public void onResume() { super.onResume(); SingleCamera.getInstance().doOpenCamera(); mCameraSurface.setCamera(SingleCamera.getInstance().getCamera()); SingleCamera.getInstance().doStartPreview(previewRate); }}
总之,实现Camera的拍照也是很简单的,但最好还是先看一下官方API给的流程。而对于原博主的代码,我不知道为什么原博主可以正常预览,而我的不行,所以在这里做了这些修改,以供以后查阅使用!
0 0
- Android Camera拍照实现
- Android Camera+SurfaceView实现自定义拍照
- Android实现拍照功能,使用SurfaceView+camera
- 使用Camera实现拍照
- android camera 后台拍照
- Android Camera进行拍照
- Android之Camera拍照
- android Camera拍照
- Android Camera进行拍照
- Android+Camera+拍照
- Android Camera 无法拍照
- Android Camera拍照
- Android之Camera拍照
- Android照相机拍照Camera
- Android camera拍照分辨率
- android相机camera拍照
- android开发之textureview绑定camera实现拍照功能
- android camera 如何实现拍照后不停止预览功能
- 编写一个函数,删除字符串中出现次数最少的字符,若多个字符出现次数一样,则都删除。
- 线段树 hdu1255 覆盖的面积
- hdu 2006 求奇数的乘积
- 使用elasticsearch与kibana来分析nginx日志小结
- C#定时检测子线程是否已经完成
- Android Camera拍照实现
- 基于QT-widget的电子词典实现
- 黑马程序员——Java基础---常用类--Object类,Scanner类,String类,StringBuffer类,StringBuilder类
- C++输入cin应用详解
- grunt(项目实践01)
- String StringBuffer StringBuilder的区别
- Android学习笔记(四十六):JSTL标签函数库
- 大一新生第一次写java程序,用System.currentTimeMillis() 获取当前时间
- JAVA多线程实现的三种方式