Android 自定义相机Demo 入门学习
16lz
2021-01-23
Android 自定义相机Demo
本文是参考网上一些自定义相机示例,再结合自己对相机的功能需求写的,基本上包含了很多基本功能,比如相机对焦、闪光灯,以及在手机预览界面上绘制自己想要绘制的图案。
话不多说,先上一张图:
应用是在Android Studio中开发的,java程序如下:
//主程序import android.annotation.SuppressLint;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.graphics.ImageFormat;import android.hardware.Camera;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.FrameLayout;import android.widget.ImageView;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;@SuppressLint("NewApi")public class CameraActivity extends AppCompatActivity { protected static final String TAG = "main"; private Camera mCamera; private CameraPreview mPreview; private static int Cur_State = 0; public ImageView imgDu; public File pictureFile; Draw draw; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); imgDu = (ImageView) findViewById(R.id.img1); mCamera = getCameraInstance(); draw = new Draw(CameraActivity.this); // 创建预览类,并与Camera关联,最后添加到界面布局中 mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); preview.addView(draw); Button captureButton = (Button) findViewById(R.id.button_capture); //button_capture captureButton.setOnClickListener(new View.OnClickListener() { @SuppressWarnings("deprecation") @Override public void onClick(View v) { Camera.Parameters parameters = mCamera.getParameters(); // 设置相片格式 parameters.setJpegQuality(100); //生成图像的质量 mCamera.setParameters(parameters); parameters.setPictureFormat(ImageFormat.JPEG); // 设置预览大小 parameters.setPreviewSize(800, 480); parameters.setPictureSize(4160, 3120); //生成图像的风辨率 mCamera.setParameters(parameters); parameters.setRotation(90); //生成的图像旋转90度 mCamera.setParameters(parameters); parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); mCamera.setParameters(parameters); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // 从Camera捕获图片 mCamera.takePicture(null, null, mPicture); } }); /*if (Cur_State < 2) { switch (Cur_State) { case 0: parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); mCamera.setParameters(parameters); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // 从Camera捕获图片 mCamera.takePicture(null, null, mPicture); } }); Cur_State++; break; case 1: parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);//FLASH_MODE_OFF mCamera.setParameters(parameters); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // 从Camera捕获图片 mCamera.takePicture(null, null, mPicture); } }); Cur_State++; break; } } else { Cur_State = 0; }*/ } }); } /** 检测设备是否存在Camera硬件 */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_CAMERA)) { // 存在 return true; } else { // 不存在 return false; } } /** 打开一个Camera */ public static Camera getCameraInstance() { Camera c = null; try { c = Camera.open(); } catch (Exception e) { Log.d(TAG, "打开Camera失败失败"); } return c; } private Camera.PictureCallback mPicture = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera arg1) { //将拍照得到的数据信息存储到本地 File tempFile=new File("/sdcard/temp.png"); try { FileOutputStream fos=new FileOutputStream(tempFile); fos.write(data); fos.close(); //注意,,,然后将这个照片的数据信息传送给要进行展示的Activity即可,这部 //分代码是我自己需要的,你使用时需要将他去掉修改成你的。 Intent intent=new Intent(CameraActivity.this,MainActivity.class); intent.putExtra("PicturePath", tempFile.getAbsolutePath()); startActivity(intent); //拍照结束之后销毁当前的Activity,进入到图片展示界面 CameraActivity.this.finish(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; @Override protected void onDestroy() { // 回收Camera资源 if(mCamera!=null){ mCamera.stopPreview(); mCamera.release(); mCamera=null; } super.onDestroy(); }}
/** * 定义一个预览类 预览界面设置 */import android.annotation.SuppressLint;import android.content.Context;import android.hardware.Camera;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import java.io.IOException;@SuppressLint("NewApi")public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private static final String TAG = "main"; private SurfaceHolder mHolder; @SuppressWarnings("deprecation") private Camera mCamera; @SuppressWarnings("deprecation") public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; // 通过SurfaceView获得SurfaceHolder mHolder = getHolder(); // 为SurfaceHolder指定回调 mHolder.addCallback(this); mCamera.setDisplayOrientation(90); } public void surfaceCreated(SurfaceHolder holder) { // 当Surface被创建之后,开始Camera的预览 try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d(TAG, "预览失败"); } } public void surfaceDestroyed(SurfaceHolder holder) { } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // Surface发生改变的时候将被调用,第一次显示到界面的时候也会被调用 if (mHolder.getSurface() == null){ // 如果Surface为空,不继续操作 return; } // 停止Camera的预览 try { mCamera.stopPreview(); } catch (Exception e){ Log.d(TAG, "当Surface改变后,停止预览出错"); } // 重新开始预览 try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d(TAG, "预览Camera出错"); } }}
/** * Created by Administrator on 2018/1/24. * 这个是在预览界面绘制图案部分 */import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.view.View;public class Draw extends View{ private Canvas canvas;//声明画笔 private Paint paint;//声明画布 private Paint paint1; private Paint paint2; private Bitmap bitmap;//声明位图 public Draw(Context context) { super(context); // TODO 自动生成的构造函数存根 //创建一个画笔 paint = new Paint(Paint.DITHER_FLAG); paint1 = new Paint(Paint.DITHER_FLAG); paint2 = new Paint(Paint.DITHER_FLAG); //设置位图的宽高,采用32位ARGB位图模式 bitmap = Bitmap.createBitmap(720, 1280, Bitmap.Config.ARGB_8888); canvas = new Canvas(bitmap); paint.setStyle(Paint.Style.STROKE);//设置非填充 paint.setStrokeWidth(2);//笔宽5像素 paint.setColor(Color.RED);//设置为红笔 paint.setAntiAlias(true);//锯齿不显示 paint.setDither(true);//设置图像抖动处理 paint.setStrokeJoin(Paint.Join.ROUND);//设置图像的结合方式 paint.setStrokeCap(Paint.Cap.ROUND);//设置画笔为圆形样式 paint1.setStyle(Paint.Style.FILL);//设置非填充 paint1.setStrokeWidth(33);//笔宽5像素 paint1.setStrokeJoin(Paint.Join.ROUND);//设置图像的结合方式 paint1.setStrokeCap(Paint.Cap.ROUND);//设置画笔为圆形样式 paint1.setColor(Color.BLACK);//设置为黑笔 paint.setAntiAlias(true);//锯齿不显示 paint.setDither(true);//设置图像抖动处理 paint2.setStyle(Paint.Style.FILL);//设置填充 paint2.setStrokeWidth(12);//笔宽5像素 paint2.setAntiAlias(true);//锯齿不显示 paint2.setDither(true);//设置图像抖动处理 paint2.setStrokeJoin(Paint.Join.ROUND);//设置图像的结合方式 paint2.setStrokeCap(Paint.Cap.ROUND);//设置画笔为圆形样式 paint2.setColor(Color.BLACK);//设置为黑笔 } @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { // TODO 自动生成的方法存根 super.onDraw(canvas); canvas.drawBitmap(bitmap, 0, 0, paint); float[] pts = {0,240,260,70}; canvas.drawLines(pts , paint); //在画布上画线 1 float[] pts2 = {695,522,340,1040}; canvas.drawLines(pts2, paint); //在画布上画线 2 Path mPath = new Path(); mPath.moveTo(260, 70); mPath.quadTo(780, 0, 695, 522); canvas.drawPath(mPath, paint); //塞尔塔曲线 Path path = new Path(); //定义一条路径 path.moveTo(0,0); //移动到 坐标(0,0) path.lineTo(0,240); path.lineTo(270,62); path.lineTo(270,0); path.lineTo(0,0); canvas.drawPath(path, paint2); Path path1 = new Path(); //定义一条路径 path1.moveTo(260,0); //移动到 坐标(260,0) path1.lineTo(720,0); path1.lineTo(720,60); path1.lineTo(260,60); path1.lineTo(260,0); canvas.drawPath(path1, paint2); Path path2 = new Path(); //定义一条路径 path2.moveTo(720,60); //移动到 坐标(720,60) path2.lineTo(720,522); path2.lineTo(715,522); path2.lineTo(715,512); path2.lineTo(700,60); path2.lineTo(720,60); canvas.drawPath(path2, paint2); Path path3 = new Path(); //定义一条路径 path3.moveTo(340,1040); //移动到 坐标(340,1040) path3.lineTo(720,1040); path3.lineTo(720,522); path3.lineTo(710,512); path3.lineTo(340,1040); canvas.drawPath(path3, paint2); Path path4 = new Path(); //定义一条路径 path4.moveTo(720,200); //移动到 坐标(715,512) path4.lineTo(500,60); path4.lineTo(720,60); path4.lineTo(720,200); canvas.drawPath(path4, paint2); float[] pts3 = {720,108,450,56}; canvas.drawLines(pts3, paint2); //在画布上画线 3 float[] pts4 = {715,230,630,110}; canvas.drawLines(pts4, paint1); //在画布上画线 4 float[] pts5 = {660,130,718,272}; canvas.drawLines(pts5, paint1); //在画布上画线 5 float[] pts6 = {714,522,720,440}; canvas.drawLines(pts6, paint1); //在画布上画线 6 }}
布局文件 activity_camera.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <FrameLayout android:id="@+id/camera_preview" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <Button android:id="@+id/button_capture" android:text="拍照" android:textColor="#6633cc" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" />LinearLayout>
应用权限:
<uses-permission android:name="android.permission.CAMERA"/> > <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
具体的细节就不在说明,可以自己在网上搜一下相关知识,大家使用中有什么问题可以留言哦,如果能解决尽量帮大家解决。
更多相关文章
- 基于Android的图像处理演示软件介绍文档
- Android 图像按钮ImageButton
- Gallery图像重叠问题以及每屏只显示一张
- 实现android图像识别的几种方法
- Android下使用camera2和Surfaceview预览图像并取得YUV420p数据回
- Android和C#基于UDP的实时图像传输