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();}}
另:添加水印
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
- Camera基础
- Camera 基础
- Camera基础
- Android基础(五) Camera
- Qualcomm Camera基础
- Qualcomm Camera基础
- Qualcomm Camera基础
- camera调试基础
- camera调试基础
- camera调试基础 .
- Qualcomm Camera基础
- Qualcomm Camera基础
- Camera曝光基础
- camera 调试基础
- Unity3D 基础篇-Camera
- Android基础:Camera
- Android相机Camera基础
- Camera tuning 基础知识点
- 【基本图像操作】NumPy
- ubuntu14.04安装CPU版SSD(Single Shot MultiBox Detector)/Caffe版本
- 了解ThreadLocal
- PAT-AL 1039. Course List for Student
- http请求返回json对象。简单的接口处理
- Camera基础
- Linux Shell简明教程(一)
- 从 Apache RocketMQ 和 Kafka 看 Topic 数量对单机性能的影响
- 给定机器人坐标和朝向,判断某点在机器人的哪个方位
- Tomcat中404/500 错误,自定义错误页面
- 树莓派Android Things物联网开发:已知Bug发行说明
- 批量解压当前目录下的zip文件_循环执行
- PAT (Basic Level) Practise (中文) 1044. 火星数字(20)
- Linux 系统编程--查看目录文件