AndroID自定义照相机实现
近期小巫在学校有一个创新项目,也不是最近,是一个拖了很久的项目,之前一直没有去搞,最近因为要中期检查,搞得我跟小组成员一阵忙活,其实开发一款照相机软件并不太难,下面就是通过自定义的方式来实现手机照相的功能。
创建一个项目:FingerTakePicture
首先来搞一下界面:
<FrameLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:tools="http://schemas.androID.com/tools" androID:ID="@+ID/FrameLayout1" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" > <!-- 显示预览图形 --> <SurfaceVIEw androID:ID="@+ID/surfaceVIEw" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" /> <!-- 相对布局,放置两个按钮 --> <relativeLayout androID:ID="@+ID/buttonLayout" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:visibility="gone" > <!-- 拍照按钮 --> <button androID:ID="@+ID/takepicture" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_alignParentRight="true" androID:layout_alignParentBottom="true" androID:background="@drawable/btn_tabkepicture_selector" androID:onClick="btnOnclick" /> <ImageVIEw androID:ID="@+ID/scalePic" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_alignParentleft="true" androID:layout_alignParentBottom="true" androID:layout_marginleft="5dp" androID:background="@drawable/img_showpic_selector" androID:onClick="imageClick" /> </relativeLayout> </FrameLayout>
界面效果(无法把预览给截屏下来滴):
权限设置少不了:
<manifest xmlns:androID="http://schemas.androID.com/apk/res/androID" package="com.wwj.finger" androID:versionCode="1" androID:versionname="1.0" > <uses-sdk androID:minSdkVersion="4" androID:targetSdkVersion="15" /> <uses-permission androID:name="androID.permission.CAMERA" /> <!-- 在SDCard中创建与删除文件权限 --> <uses-permission androID:name="androID.permission.MOUNT_UNMOUNT_fileSYstemS" /> <!-- 往SDCard写入数据权限 --> <uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE" /> <application androID:icon="@drawable/ic_launcher" androID:label="@string/app_name" androID:theme="@style/Apptheme" > <activity androID:name=".MainActivity" androID:label="@string/Title_activity_main" > <intent-filter> <action androID:name="androID.intent.action.MAIN" /> <category androID:name="androID.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity androID:name=".ShowPicActivity" androID:label="@string/app_name" androID:theme="@style/Apptheme" androID:configChanges="orIEntation|keyboardHIDden" ></activity> </application> </manifest>
主Activity:
package com.wwj.finger; import java.io.file; import java.io.fileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import androID.app.Activity; import androID.content.Intent; import androID.graphics.PixelFormat; import androID.harDWare.Camera; import androID.harDWare.Camera.PictureCallback; import androID.os.Bundle; import androID.os.Environment; import androID.vIEw.KeyEvent; import androID.vIEw.MotionEvent; import androID.vIEw.Surface; import androID.vIEw.SurfaceHolder; import androID.vIEw.SurfaceHolder.Callback; import androID.vIEw.SurfaceVIEw; import androID.vIEw.VIEw; import androID.vIEw.VIEwGroup; import androID.Widget.Toast; /** * AndroID手指拍照 * * @author wwj * @date 2013/4/29 */ public class MainActivity extends Activity { private VIEw layout; private Camera camera; private Camera.Parameters parameters = null; Bundle bundle = null; // 声明一个Bundle对象,用来存储数据 @OverrIDe public voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 显示界面 setContentVIEw(R.layout.activity_main); layout = this.findVIEwByID(R.ID.buttonLayout); SurfaceVIEw surfaceVIEw = (SurfaceVIEw) this .findVIEwByID(R.ID.surfaceVIEw); surfaceVIEw.getHolder() .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceVIEw.getHolder().setFixedSize(176,144); //设置Surface分辨率 surfaceVIEw.getHolder().setKeepScreenOn(true);// 屏幕常亮 surfaceVIEw.getHolder().addCallback(new SurfaceCallback());//为SurfaceVIEw的句柄添加一个回调函数 } /** * 按钮被点击触发的事件 * * @param v */ public voID btnOnclick(VIEw v) { if (camera != null) { switch (v.getID()) { case R.ID.takepicture: // 拍照 camera.takePicture(null,null,new MyPictureCallback()); break; } } } /** * 图片被点击触发的时间 * * @param v */ public voID imageClick(VIEw v) { if (v.getID() == R.ID.scalePic) { if (bundle == null) { Toast.makeText(getApplicationContext(),R.string.takephoto,Toast.LENGTH_SHORT).show(); } else { Intent intent = new Intent(this,ShowPicActivity.class); intent.putExtras(bundle); startActivity(intent); } } } private final class MyPictureCallback implements PictureCallback { @OverrIDe public voID onPictureTaken(byte[] data,Camera camera) { try { bundle = new Bundle(); bundle.putByteArray("bytes",data); //将图片字节数据保存在bundle当中,实现数据交换 savetoSDCard(data); // 保存图片到sd卡中 Toast.makeText(getApplicationContext(),R.string.success,Toast.LENGTH_SHORT).show(); camera.startPrevIEw(); // 拍完照后,重新开始预览 } catch (Exception e) { e.printstacktrace(); } } } /** * 将拍下来的照片存放在SD卡中 * @param data * @throws IOException */ public static voID savetoSDCard(byte[] data) throws IOException { Date date = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 格式化时间 String filename = format.format(date) + ".jpg"; file fileFolder = new file(Environment.getExternalStorageDirectory() + "/finger/"); if (!fileFolder.exists()) { // 如果目录不存在,则创建一个名为"finger"的目录 fileFolder.mkdir(); } file jpgfile = new file(fileFolder,filename); fileOutputStream outputStream = new fileOutputStream(jpgfile); // 文件输出流 outputStream.write(data); // 写入sd卡中 outputStream.close(); // 关闭输出流 } private final class SurfaceCallback implements Callback { // 拍照状态变化时调用该方法 @OverrIDe public voID surfaceChanged(SurfaceHolder holder,int format,int wIDth,int height) { parameters = camera.getParameters(); // 获取各项参数 parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式 parameters.setPrevIEwSize(wIDth,height); // 设置预览大小 parameters.setPrevIEwFrameRate(5); //设置每秒显示4帧 parameters.setPictureSize(wIDth,height); // 设置保存的图片尺寸 parameters.setJpegQuality(80); // 设置照片质量 } // 开始拍照时调用该方法 @OverrIDe public voID surfaceCreated(SurfaceHolder holder) { try { camera = Camera.open(); // 打开摄像头 camera.setPrevIEwdisplay(holder); // 设置用于显示拍照影像的SurfaceHolder对象 camera.setdisplayOrIEntation(getPrevIEwDegree(MainActivity.this)); camera.startPrevIEw(); // 开始预览 } catch (Exception e) { e.printstacktrace(); } } // 停止拍照时调用该方法 @OverrIDe public voID surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { camera.release(); // 释放照相机 camera = null; } } } /** * 点击手机屏幕是,显示两个按钮 */ @OverrIDe public boolean ontouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: layout.setVisibility(VIEwGroup.VISIBLE); // 设置视图可见 break; } return true; } @OverrIDe public boolean onKeyDown(int keyCode,KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_CAMERA: // 按下拍照按钮 if (camera != null && event.getRepeatCount() == 0) { // 拍照 //注:调用takePicture()方法进行拍照是传入了一个PictureCallback对象――当程序获取了拍照所得的图片数据之后 //,PictureCallback对象将会被回调,该对象可以负责对相片进行保存或传入网络 camera.takePicture(null,new MyPictureCallback()); } } return super.onKeyDown(keyCode,event); } // 提供一个静态方法,用于根据手机方向获得相机预览画面旋转的角度 public static int getPrevIEwDegree(Activity activity) { // 获得手机的方向 int rotation = activity.getwindowManager().getDefaultdisplay() .getRotation(); int degree = 0; // 根据手机的方向计算相机预览画面应该选择的角度 switch (rotation) { case Surface.ROTATION_0: degree = 90; break; case Surface.ROTATION_90: degree = 0; break; case Surface.ROTATION_180: degree = 270; break; case Surface.ROTATION_270: degree = 180; break; } return degree; } }
用来显示图片的Activity:
package com.wwj.finger; import androID.app.Activity; import androID.content.Intent; import androID.graphics.Bitmap; import androID.graphics.BitmapFactory; import androID.graphics.Matrix; import androID.os.Bundle; import androID.Widget.ImageVIEw; public class ShowPicActivity extends Activity { private ImageVIEw ivPic = null; // 显示图片控件 /** * Activity在创建的时候回调的函数 主要用来初始化一些变量 */ @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.showpic); ivPic = (ImageVIEw) findVIEwByID(R.ID.ivPic); setimageBitmap(getimageFormBundle()); } /** * 将MainActivity传过来的图片显示在界面当中 * * @param bytes */ public voID setimageBitmap(byte[] bytes) { Bitmap cameraBitmap = byte2Bitmap(); // 根据拍摄的方向旋转图像(纵向拍摄时要需要将图像选择90度) Matrix matrix = new Matrix(); matrix.setRotate(MainActivity.getPrevIEwDegree(this)); cameraBitmap = Bitmap .createBitmap(cameraBitmap,cameraBitmap.getWIDth(),cameraBitmap.getHeight(),matrix,true); ivPic.setimageBitmap(cameraBitmap); } /** * 从Bundle对象中获取数据 * * @return */ public byte[] getimageFormBundle() { Intent intent = getIntent(); Bundle data = intent.getExtras(); byte[] bytes = data.getByteArray("bytes"); return bytes; } /** * 将字节数组的图形数据转换为Bitmap * * @return */ private Bitmap byte2Bitmap() { byte[] data = getimageFormBundle(); // 将byte数组转换成Bitmap对象 Bitmap bitmap = BitmapFactory.decodeByteArray(data,data.length); return bitmap; } }
这是小巫那个创新项目的一小部分,已经完美实现简单的照相机功能了,保存图片不会像有些网友提供的代码给定一个特定的文件名,不能保存多张图片,还特定把一些方法封装了一下,有需要的朋友好好看看吧。
以上是内存溢出为你收集整理的Android自定义照相机的实例全部内容,希望文章能够帮你解决Android自定义照相机的实例所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)