Camera基础

来源:互联网 发布:淘宝店铺的模板怎么做 编辑:程序博客网 时间:2024/05/18 16:35
 

Camera可以选择两种拍照和视频方式,第一种是使用广播告知系统帮助拍照,第二种是自己实行预览拍照和拍摄视频

权限:

    <uses-permission android:name="android.permission.CAMERA" />    <uses-feature android:name="android.hardware.camera" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-feature android:name="android.hardware.camera.autofocus" />    <uses-feature android:name="android.hardware.camera.flash" />


一、广播拍照/拍摄视频 创建Intent,指定拍照类型

MediaStore.ACTION_IMAGE_CAPTURE 拍摄照片;

MediaStore.ACTION_VIDEO_CAPTURE 拍摄视频;

Intent intent = new Intent(MediaStore.ACTION_IMAGE/VIDEO_CAPTURE);

intent.putExtra(MediaStore.EXTRA_OUTPUT, “保存路径”);

startActivityForResult(intent, 0); 在重写onActivityResult后,返回intent会携带照片uri,Uri uri = data.getData(),然后根据返回的uri在数据库中查找相关信息

有部分手机在获取到uri后无法获取实际尺寸的照片,解决方法如下:

String filename = "xxx.jpg";

cameraFile = new File(Environment.getExternalStorageDirectory()+"/"+"自己文件夹名称"+filename);

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile));

startActivityForResult(intent, REQUEST_CODE_CAPTURE_CAMEIA);

在重写onActivityResult后FileInputStream fis = new FileInputStream(cameraFile);bitmap = BitmapFactory.decodeStream(fis);再根据bitmap获取图片

二、使用camera.takePicture()获取照片

package com.zzr.takepicture;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Bitmap.CompressFormat;import android.graphics.BitmapFactory;import android.hardware.Camera;import android.hardware.Camera.PictureCallback;import android.hardware.Camera.ShutterCallback;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;import android.view.MenuItem;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.view.WindowManager;import android.widget.Button;public class MainActivity extends Activity implements SurfaceHolder.Callback{private Button btTakePic;private Camera camera;private LayoutInflater inflater;private SurfaceView surfaceView;private SurfaceHolder holder;private View view;private ShutterCallback mshutter = new ShutterCallback(){@Overridepublic void onShutter() {}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setType(WindowManager.LayoutParams.FLAG_FULLSCREEN);inflater = LayoutInflater.from(this);view = inflater.inflate(R.layout.activity_main, null);setContentView(view);surfaceView = (SurfaceView) view.findViewById(R.id.movView);btTakePic = (Button) view.findViewById(R.id.take_pic);holder =surfaceView.getHolder();holder.addCallback(this);btTakePic.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {camera.takePicture(null, null, picCallback);}});}private Camera.PictureCallback picCallback = new PictureCallback(){@Overridepublic void onPictureTaken(byte[] data, Camera camera1) {camera.startPreview();try {String path1 = "/sdcard/pic";File file1 = new File(path1);if(!file1.exists()) {file1.mkdir();}String path = path1+File.separator+System.currentTimeMillis()+".jpg";File file = new File(path);if(!file.exists()) {file.createNewFile();} FileOutputStream fos = new FileOutputStream(file);Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);bitmap.compress(CompressFormat.JPEG, 100, fos);}catch (IOException e) {e.printStackTrace();}}};@Overridepublic void surfaceCreated(SurfaceHolder holder) {Log.i("zhangziran", "surfaceCreated");//打开摄像头,获得Camera对象camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);try {//设置显示camera.setPreviewDisplay(holder);camera.setDisplayOrientation(90);} catch (IOException exception) {camera.release();camera = null;}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Log.i("zhangziran", "surfaceChanged");//已经获得Surface的width和height,设置Camera的参数Camera.Parameters parameters = camera.getParameters();parameters.setPreviewSize(height, width);//设置白平衡parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);//设置场景模式parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);//设置对焦模式parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//连续对焦//设置闪光灯模式parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);camera.setParameters(parameters);//开始预览camera.startPreview();camera.cancelAutoFocus();//如果要是实现自动连续对焦,就要把这句话加上}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {Log.i("zhangziran", "destroyed");camera.stopPreview();//释放Cameracamera.release();camera = null;}}
三、使用MediaCodec实现H264编码,并使用MediaMuxer合成视屏

package com.zzr.takeaudio;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.nio.ByteBuffer;import java.util.Arrays;import java.util.List;import android.annotation.SuppressLint;import android.app.Activity;import android.graphics.ImageFormat;import android.hardware.Camera;import android.hardware.Camera.Parameters;import android.hardware.Camera.PreviewCallback;import android.hardware.Camera.Size;import android.media.CamcorderProfile;import android.media.MediaCodec;import android.media.MediaCodecInfo;import android.media.MediaFormat;import android.media.MediaMuxer;import android.media.MediaRecorder;import android.media.MediaRecorder.OnInfoListener;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.view.WindowManager;import android.widget.Button;public class MainActivity extends Activity implements SurfaceHolder.Callback,OnClickListener,PreviewCallback, OnInfoListener{private String tag = "zhangziran";private SurfaceView surfaceView;private SurfaceHolder surfaceHolder;private Camera camera;private MediaRecorder recorder;private File file;private Button btnStart,btnStop; private boolean isRecorder =false;private byte[] btf =null;private Handler handler = new Handler();private boolean isChange = false;private int width = 1280;private int height = 720;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(R.layout.activity_main);btnStart = (Button) findViewById(R.id.start_recorder);btnStop = (Button) findViewById(R.id.stop_recorder);btnStart.setOnClickListener(this);btnStop.setOnClickListener(this);surfaceView = (SurfaceView) findViewById(R.id.surfaceView);surfaceHolder = surfaceView.getHolder();surfaceHolder.addCallback(this);String path = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"audio";file = new File(path);if(!file.exists()) {file.mkdir();}}@Overridepublic void surfaceCreated(SurfaceHolder holder) {try {camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);camera.setPreviewDisplay(holder);camera.setDisplayOrientation(90);} catch (IOException e) {e.printStackTrace();}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Log.i("zhangziran", "width*height="+width+"*"+height);Parameters params = camera.getParameters();//camera默认是横屏,也就是意味着界面高就是预览的宽,界面的高就是预览的宽,//对于我自己的手机分辨率是1920*1080(高*宽),而本手机也支持1920*1080的预览//所以将手机的宽高反向位置放进去//params.setPreviewSize(height, width);params.setPreviewSize(1280, 720);params.setPictureSize(1280, 720);params.setPreviewFormat(ImageFormat.YV12);//设置白平衡params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);//设置场景模式params.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);//设置对焦模式params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);//设置闪光灯模式params.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);camera.setParameters(params);createfile();camera.setPreviewCallback(this);prepareMediaCodec();camera.startPreview();camera.cancelAutoFocus();}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {try {mediaMuxer.stop();mediaMuxer.release();mediaCodec.stop();mediaCodec.release();outputStream.flush();outputStream.close();camera.setPreviewCallback(null);camera.stopPreview();camera.unlock();camera.release();camera=null;} catch (IOException e) {e.printStackTrace();}}private boolean prepareViewRecorder() {//创建工具recorder = new MediaRecorder();//释放摄像机,为MediaRecorder设置摄像机camera.unlock();recorder.setCamera(camera);//设置声音和视频来源recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//设置视频输出格式和编码recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));//设置比特率recorder.setVideoEncodingBitRate(5*1024*1024);//设置输出文件夹recorder.setOutputFile(getSaveFile().toString());//设置最大录制时间recorder.setMaxDuration(10*1000);//设置预览窗口recorder.setPreviewDisplay(surfaceView.getHolder().getSurface());recorder.setOnInfoListener(this);//准备拍摄try {recorder.prepare();} catch (IllegalStateException e) {e.printStackTrace();return false;} catch (IOException e) {e.printStackTrace();return false;}return true;}int i=0;private File getSaveFile() {String path = file.getAbsolutePath()+File.separator+System.currentTimeMillis()+".mp4";File file1= new File(path);if(!file1.exists()) {try {file1.createNewFile();} catch (IOException e) {e.printStackTrace();}}return file1;}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.start_recorder:if(isRecorder) return;if(prepareViewRecorder()) {recorder.start();isRecorder = true;}break;case R.id.stop_recorder:if(isRecorder) {recorder.stop();recorder.release();}mediaMuxer.stop();mediaMuxer.release();mediaCodec.stop();mediaCodec.release();break;}}/** * 初始化编码器 */private MediaCodec mediaCodec;private int frameRate =15;private MediaMuxer mediaMuxer;@SuppressLint("NewApi")private void prepareMediaCodec() {mediaCodec = MediaCodec.createEncoderByType("video/avc");MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", width, height);//设置比特率/码流mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE,125000);//设置帧数mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE,frameRate);//颜色格式mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);//关键帧时间间隔:单位秒mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,5);//设置声道数量mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT,1);mediaFormat.setInteger(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER,1000000/frameRate);mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);mediaCodec.start();try {mediaMuxer = new MediaMuxer(getSaveFile().toString(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);} catch (IOException e) {e.printStackTrace();}}@Overridepublic void onPreviewFrame(byte[] data, Camera camera) {onFrame(data);}//I420: YYYYYYYY UU VV    =>YUV420P //YV12: YYYYYYYY VV UU    =>YUV420P//NV12: YYYYYYYY UVUV     =>YUV420SP//NV21: YYYYYYYY VUVU     =>YUV420SPpublic void swapYV12toI420(byte[] yv12bytes, byte[] i420bytes, int width,int height) {System.arraycopy(yv12bytes, 0, i420bytes, 0, width * height);System.arraycopy(yv12bytes, width * height + width * height / 4,i420bytes, width * height, width * height / 4);System.arraycopy(yv12bytes, width * height, i420bytes, width * height+ width * height / 4, width * height / 4);}private int index=-1;public byte[] configbyte; @SuppressLint("NewApi")private void onFrame(byte[] data1) {// 以720×488大小图象YUV420 planar为例,其存储格式是: 共大小为(720×480×3>>1)//YUV420是4:2:0,Y=720*480*8bit,U=V=720*480*8bit/4,byte[] data = new byte[width*height*3/2];swapYV12toI420(data1, data, width, height);Log.i(tag, "data1="+data1.length);Log.i(tag, " data="+data.length);//取出输出流和输入流数组ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();int inputBufferIndex = mediaCodec.dequeueInputBuffer(0);long audioAbsolutePtsUs = System.nanoTime() / 1000;if(inputBufferIndex >=0){ByteBuffer inputByteBuffer = inputBuffers[inputBufferIndex];inputByteBuffer.clear();inputByteBuffer.put(data);mediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, audioAbsolutePtsUs, 0);}MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();while(true){int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);//outputBufferIndex经常性值为-1,因为数据是断断续续过来的,并不是一直有//在else中一定要释放output缓存空间,否则缓存空间满了outputBufferIndex也会返回-1if(outputBufferIndex==MediaCodec.INFO_TRY_AGAIN_LATER){break;}else if(outputBufferIndex==MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED){outputBuffers = mediaCodec.getOutputBuffers();}else if(outputBufferIndex==MediaCodec.INFO_OUTPUT_FORMAT_CHANGED){MediaFormat format = mediaCodec.getOutputFormat();index=mediaMuxer.addTrack(format);mediaMuxer.start();}else if (outputBufferIndex<0){break;}else {/*try {ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];byte[] outData = new byte[bufferInfo.size];outputBuffer.get(outData);if(bufferInfo.flags == 2){configbyte = new byte[bufferInfo.size];configbyte = outData;}else if(bufferInfo.flags == 1){byte[] keyframe = new byte[bufferInfo.size + configbyte.length];System.arraycopy(configbyte, 0, keyframe, 0, configbyte.length);System.arraycopy(outData, 0, keyframe, configbyte.length, outData.length);outputStream.write(keyframe, 0, keyframe.length);}else{outputStream.write(outData, 0, outData.length);}} catch (Exception e) {}*/ByteBuffer outpurByteBuffer = outputBuffers[outputBufferIndex];if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {bufferInfo.size = 0;}if(bufferInfo.size!=0){outpurByteBuffer.position(bufferInfo.offset);outpurByteBuffer.limit(bufferInfo.offset+bufferInfo.size);mediaMuxer.writeSampleData(index, outpurByteBuffer, bufferInfo);}mediaCodec.releaseOutputBuffer(outputBufferIndex,false);}}}private static String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/test1.h264";private BufferedOutputStream outputStream;FileOutputStream outStream;private void createfile(){File file = new File(path);if(file.exists()){file.delete();}try {outputStream = new BufferedOutputStream(new FileOutputStream(file));} catch (Exception e){ e.printStackTrace();}}@Overridepublic void onInfo(MediaRecorder mr, int what, int extra) {}@Overrideprotected void onDestroy() {mediaCodec.stop();mediaCodec.release();mediaMuxer.stop();mediaMuxer.release();if(camera!=null) {camera.stopPreview();camera.setPreviewCallback(null);camera.unlock();camera.release();camera=null;}super.onDestroy();}}

另:添加水印

private int index=-1;
public byte[] configbyte;
@SuppressLint("NewApi")
private void onFrame(byte[] data1) {
      //对数据做处理:yv12(YUV420P)转RGB
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      YuvImage yuvImage = new YuvImage(data1, ImageFormat.NV21, 1920, 1080, null);
      yuvImage.compressToJpeg(new Rect(0, 0, 1920, 1080), 100, out);
      byte[] imageByte = out.toByteArray();
      //把每一帧数据转换成Bitmap
      Bitmap image = BitmapFactory.decodeByteArray(imageByte, 0, imageByte.length).copy(Bitmap.Config.ARGB_8888, true);
      //渲染图片
      Canvas canvas = new Canvas(image);
      Bitmap shuiyin = BitmapFactory.decodeResource(getResources(), R.drawable.shuiying);
      Paint paint = new Paint();
      canvas.drawBitmap(shuiyin,0,0,paint);
      //再将bitmap转nv21
      byte[] data2 = getNV21(1920, 1080, image);
      // 以720×488大小图象YUV420 planar为例,其存储格式是: 共大小为(720×480×3>>1)
      //YUV420是4:2:0,Y=720*480*8bit,U=V=720*480*8bit/4,
      byte[] data = new byte[width*height*3/2];
      nv21ToI420(data2, data, width, height);
      //swapYV12toI420(data1, data, width, height);
      Log.i(tag, "data1="+data1.length);
      Log.i(tag, " data="+data.length);
      //取出输出流和输入流数组
      ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
      ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
      int inputBufferIndex = mediaCodec.dequeueInputBuffer(0);

接三

相关资料:

注:I420: YYYYYYYY UU VV    =>YUV420P
YV12: YYYYYYYY VV UU    =>YUV420P
NV12: YYYYYYYY UVUV     =>YUV420SP
NV21: YYYYYYYY VUVU     =>YUV420SP

Android常用的几种格式:NV21/NV12/YV12/YUV420P的区别:http://www.cnblogs.com/raomengyang/p/4924787.html

图文详解YUV420数据格式:http://www.cnblogs.com/azraelly/archive/2013/01/01/2841269.htm





原创粉丝点击