相机Camera(预览

您所在的位置:网站首页 华为nova3怎么设置竖屏 相机Camera(预览

相机Camera(预览

2024-07-15 17:58| 来源: 网络整理| 查看: 265

代码需要权限如下:

1.调用手机自带的相机,预览并拍照

我的另一篇博客已经写到

调用手机相机拍照并返回图片

其中主要的代码就是:

                //调用系统相机,拍照                 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);                 //在onActivityResult()处理                 startActivityForResult(intent , 1);

 

2.自己写一个SurfaceView,预览Camera,并手动拍照Camera.takePicture(); public class MyCameraActivity extends AppCompatActivity implements SurfaceHolder.Callback, android.hardware.Camera.AutoFocusCallback { SurfaceView mySurfaceView; SurfaceHolder holder; android.hardware.Camera myCamera; //照片保存路径 String filePath = null; //拍照按钮 Button capture; //照片缩略图 ImageView editPic; Context mContext; MyOrientoinListener myOrientoinListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_my_camera); mySurfaceView = (SurfaceView) findViewById(R.id.camera_view); holder = mySurfaceView.getHolder(); //回调 holder.addCallback(this); mContext = this; //设置类型,没有这句将调用失败 //当在Canvas中绘制完成后,调用函数unlockCanvasAndPost(Canvas canvas)来通知系统Surface已经绘制完成, // 这样系统会把绘制完的内容显示出来。为了充分利用不同平台的资源,发挥平台的最优效果可以通过SurfaceHolder的setType函数来设置绘制的类型, // 目前接收如下的参数: //SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface //SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface //SURFACE_TYPE_GPU:适用于GPU加速的Surface //SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供, // 在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。 // 如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); capture = (Button) findViewById(R.id.takeP); editPic = (ImageView) findViewById(R.id.p_view); //监听 capture.setOnClickListener(takePicture); } View.OnClickListener takePicture = new View.OnClickListener() { @Override public void onClick(View v) { //自动对焦 并回调 myCamera.autoFocus(MyCameraActivity.this); } }; @Override public void surfaceCreated(SurfaceHolder holder) { if (myCamera == null) { //得到相机实例 myCamera = android.hardware.Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT); try { //相机预览传入surfaceholder myCamera.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); } } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.i("TAG", "change"); //设置预览方向顺时针旋转90 ,摄像头预览方向与实际相差90度 myCamera.setDisplayOrientation(90); //开始预览 myCamera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { //关闭预览并释放资源 myCamera.stopPreview(); myCamera.release(); myCamera = null; } @Override public void onAutoFocus(boolean success, android.hardware.Camera camera) { if (success) { //设置相机参数 android.hardware.Camera.Parameters params = myCamera.getParameters(); params.setPictureFormat(PixelFormat.JPEG); myCamera.setParameters(params); //拍照 产生三个回调对应 (原始图像 压缩图 jpeg图) 这里只回调了jpeg图 myCamera.takePicture(null, null, jpeg); } } android.hardware.Camera.PictureCallback jpeg = new android.hardware.Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, android.hardware.Camera camera) { try { //获得图片 Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length); SimpleDateFormat sDateFormate = new SimpleDateFormat("yyyyMMddHHmmss"); String date = sDateFormate.format(new Date()); if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(mContext, "SD卡不可用", Toast.LENGTH_SHORT).show(); } else { filePath = Environment.getExternalStorageDirectory().getAbsolutePath(); filePath = filePath + "/" + date + ".jpg"; } File file = new File(filePath); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); //创建操作图片用的matrix Matrix matrix = new Matrix(); //图片方向与实际相差270,所以在保存到bos之前将图片顺时针旋转270度 matrix.postRotate(270); //创建新图片 Bitmap rotateBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); //将图片以jpeg格式压缩到流中 rotateBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos); //输出 bos.flush(); //关闭 bos.close(); //显示缩略图 editPic.setBackgroundDrawable(changeBitmapToDrawable(rotateBitmap)); //缩略图点击时得到路径参数 editPic.setTag(filePath); } catch (Exception e) { e.printStackTrace(); } //takePiture会停止预览,我们要重新开启预览 myCamera.startPreview(); } }; private Drawable changeBitmapToDrawable(Bitmap bitmapOrg) { int width = bitmapOrg.getWidth(); int height = bitmapOrg.getHeight(); //定义要转换成的图片的宽和高 int newWidth = 100; //计算缩放率,新尺寸除以旧尺寸 float scaleWidth = (float) newWidth / width; float scaleHeight = scaleWidth; //创建操作图片用的matrix Matrix matrix = new Matrix(); //缩放图片动作 matrix.postScale(scaleWidth, scaleHeight); //创建新图片 Bitmap resizeBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width, height, matrix, true); //将Bitmap转换为Drawable BitmapDrawable bitmapDrawable = new BitmapDrawable(resizeBitmap); return bitmapDrawable; } }

对于简单的预览拍照,上面两种方式已经实现。

下面解决横竖屏切换的问题:(以第二段代码为例)

要想获取屏幕方向,需要在AndroidManifest.xml文件中,对某个Activity加入如下的设置:

android:configChanges="screenSize|orientation|keyboardHidden"

然后还需要手机开启自动旋转的设置。

 

以上准备工作做好,我们接下来有两种方式实现横竖屏的切换:

1.经典方法:activity重写onConfigurationChanged()监听屏幕旋转,而不重新执行onCreate()。 //onConfigurationChanged public void onConfigurationChanged(Configuration newConfig){ super.onConfigurationChanged(newConfig); if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){ // Nothing need to be done here Log.i("TAG","横屏"); //处理代码 } else { // Nothing need to be done here Log.i("TAG","竖屏"); //处理代码 } }

由于屏幕方向自动旋转了,所以Activity自动旋转了,Camera也旋转了,不需要你手动旋转Camera。

不过如果旋转之后的 Camera方向不对,可以手动修改Camera的方向。myCamera.setDisplayOrientation(角度);

 

2.用传感器监听屏幕旋转角度,当达到一定的角度了,手动旋转Camera,不过你的Activity方向还是不变。 public class MyCameraActivity extends AppCompatActivity implements SurfaceHolder.Callback, android.hardware.Camera.AutoFocusCallback { ... MyOrientoinListener myOrientoinListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_my_camera); ... holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); capture = (Button) findViewById(R.id.takeP); editPic = (ImageView) findViewById(R.id.p_view); capture.setOnClickListener(takePicture); //第二种方式,监听屏幕旋转 myOrientoinListener = new MyOrientoinListener(this); boolean autoRotateOn = (android.provider.Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0) == 1); //检查系统是否开启自动旋转 if (autoRotateOn) { myOrientoinListener.enable(); } } @Override protected void onDestroy() { super.onDestroy(); //销毁时取消监听 if (myOrientoinListener != null) { myOrientoinListener.disable(); } } ... ... ... ... class MyOrientoinListener extends OrientationEventListener { private Context context; public MyOrientoinListener(Context context) { super(context); this.context = context; } @Override public void onOrientationChanged(int orientation) { Log.i("TAG", "orention" + orientation); int screenOrientation = context.getResources().getConfiguration().orientation; if (((orientation >= 0) && (orientation < 45)) || (orientation > 315)) {//设置竖屏 if (screenOrientation != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT && orientation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT) { Log.i("TAG", "设置竖屏"); myCamera.setDisplayOrientation(0); } } else if (orientation > 225 && orientation < 315) { //设置横屏 Log.i("TAG", "设置横屏"); if (screenOrientation != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { myCamera.setDisplayOrientation(90); } } else if (orientation > 45 && orientation < 135) {// 设置反向横屏 Log.i("TAG", "反向横屏"); if (screenOrientation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) { myCamera.setDisplayOrientation(180); } } else if (orientation > 135 && orientation < 225) { Log.i("TAG", "反向竖屏"); if (screenOrientation != ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT) { myCamera.setDisplayOrientation(270); } } } } }

在旋转角度oritention达到一定值的时候,上面代码中,我们手动的旋转了Camera的方向,如有90,180,270度的。

对于横屏,竖屏,到底需要需要旋转多少角度,上面我旋转的角度可能不对,你们自行修改。

还有就是在onDestroy()方法中要记得停止监听。

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3