>>分享Android开发相关的技术 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 20005 个阅读者 刷新本主题
 * 贴子主题:  Android Camera2.0 结合ImageReader拍照并解决图片偏转问题 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2020-03-08 21:24:11     消息  查看  搜索  好友  邮件  复制  引用

                                                                                                

Android Camera2.0 结合ImageReader拍照并解决图片偏转问题

         在Camera 2.0的API中,要想实现拍照功能,则要借助于ImageReader。

         首先在自定义的TextureView.SurfaceTextureListener的实现类中,维护ImageReader的引用        

  private ImageReader mImageReader ;

     然后在setUpCamera方法中对ImageReader进行初始化                

  /**
     * 设置camera2.0的初始化参数
     */

     private  void  setUpCamera() {
        cameraManager = (CameraManager)mContext.getSystemService(Context.CAMERA_SERVICE);
         try{
             for (String id : cameraManager.getCameraIdList()) {

                 //获取代表摄像头特征类characteristics
                characteristics = cameraManager.getCameraCharacteristics(id);

                 //如果是前置摄像头
                 if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
                    mCameraId = id ;

                    StreamConfigurationMap streamConfigurationMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

                    sizes = streamConfigurationMap.getOutputSizes(SurfaceHolder.class);

                     //设置预览大小
                    mPreviewSize = sizes[ 0];

                     //imageReader初始化
                    mImageReader = ImageReader.newInstance(mPreviewSize.getWidth(),
                            mPreviewSize.getHeight(),
                            ImageFormat.JPEG,
                             2 );
                    mImageReader.setOnImageAvailableListener(onImageAvailableListener , mBackgroundHandler);

                     //获取人脸检测参数
                     int[] FD =characteristics.get(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);
                     int maxFD=characteristics.get(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT);

                     if (FD.length> 0) {
                        List<Integer> fdList =  new ArrayList<>();
                         for ( int FaceD : FD
                                ) {
                            fdList.add(FaceD);
                            Log.e(TAG,  "setUpCameraOutputs: FD type:" + Integer.toString(FaceD));
                        }
                        Log.e(TAG,  "setUpCameraOutputs: FD count" + Integer.toString(maxFD));

                         if (maxFD >  0) {
                            mFaceDetectSupported =  true;
                            mFaceDetectMode = Collections.max(fdList);
                        }
                    }
                }
            }
        }  catch ( CameraAccessException e ){
            e.printStackTrace();
        }
    }

     然后将ImageReader的Surface添加进CaptureRequest.Builder中

    在startPreview()方法中添加                

previewRequestBuilder .addTarget(mImageReader .getSurface()) ;

     接下来创建一个类实现ImageReader.OnImageAvailableListener接口,在其中获取每一帧的Image对象,并生成一个Bitmap,并对该Bitmap进行镜像和旋转操作,因为摄像头获取的原始图像和预览中见到的图像是并不一样                

  /**
*OnImageAvailableListener实现类
*/


   private final ImageReader .OnImageAvailableListener onImageAvailableListener = new ImageReader .OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {

            Image image = reader .acquireNextImage()  ;

            ByteBuffer byteBuffer = image .getPlanes()[ 0] .getBuffer() ;
            byte[] bytes = new byte ;
            byteBuffer .get(bytes) ;

            try {
                Bitmap temp = BitmapFactory .decodeByteArray(bytes, 0,bytes .length) ;
                Bitmap newBitmap = Bitmap .createBitmap(mPreviewSize .getWidth(),mPreviewSize .getWidth(),temp .getConfig()) ;

                Canvas canvas = new Canvas(newBitmap) ;
                Paint paint = new Paint() ;
                Matrix matrix = new Matrix() ;
                //图片镜像并旋转 90度
                matrix .setScale(- 1,  1) ;
                matrix .postTranslate(temp .getWidth(),  0) ;
                matrix .postRotate( 90 ,temp .getWidth()/ 2,temp .getHeight()/ 2) ;
                matrix .postTranslate( 0,(temp .getWidth()-temp .getHeight())/ 2) ;

                canvas .drawBitmap(temp, matrix , paint ) ;

                File newFile = new File( Environment .getExternalStorageDirectory() ,  "345.jpg") ;
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile)) ;
                newBitmap .compress(Bitmap .CompressFormat .JPEG,  100, bos) ;
                bos .flush() ;
                bos .close() ;
                temp .recycle() ;
                newBitmap .recycle() ;
            } catch (FileNotFoundException e) {
                e .printStackTrace() ;
            } catch (IOException e) {
                e .printStackTrace() ;
            } finally {
                image .close() ;
                byteBuffer .clear() ;
            }

            image .close() ;

                }
    } ;

     上面做的是用ImageReader获取每一帧实时图像,要想实现拍照,调用CameraCaptureSession的capture方法即可                

public void captureStillImage(){
        try {

            CaptureRequest .Builder captureStillBuilder = cameraDevice .createCaptureRequest(CameraDevice .TEMPLATE_STILL_CAPTURE) ;
            captureStillBuilder .addTarget(mImageReader .getSurface()) ;
            // 设置自动对焦模式
            captureStillBuilder .set(CaptureRequest .CONTROL_AF_MODE,
                    CaptureRequest .CONTROL_AF_MODE_CONTINUOUS_PICTURE) ;
            // 设置自动曝光模式
            captureStillBuilder .set(CaptureRequest .CONTROL_AE_MODE,
                    CaptureRequest .CONTROL_AE_MODE_ON_AUTO_FLASH) ;

            int rotation = ((Activity)mContext) .getWindowManager() .getDefaultDisplay() .getRotation() ;
            captureStillBuilder .set( CaptureRequest .JPEG_ORIENTATION ,
                    ORIENTATIONS .get(rotation)) ;

            CameraCaptureSession .CaptureCallback captureCallback = new CameraCaptureSession .CaptureCallback() {
                @Override
                public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                    super .onCaptureCompleted(session, request, result) ;

                    Toast .makeText(mContext, "Image Captured" , Toast .LENGTH_SHORT) .show() ;
                }

                    } ;

            captureSession .stopRepeating() ;
            captureSession .capture( captureStillBuilder .build() , captureCallback , null ) ;
            captureSession .setRepeatingRequest(captureRequest, new CameraCaptureSession .CaptureCallback() {
                @Override
                public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
                    super .onCaptureStarted(session, request, timestamp, frameNumber) ;
                }
            },mBackgroundHandler) ;
        } catch (CameraAccessException e) {
            e .printStackTrace() ;
        }
    }

     在成员变量中设置ROTATION                

//设置Surface旋转角
    private static final SparseIntArray ORIENTATIONS = new SparseIntArray() ;
    static {
        ORIENTATIONS .append(Surface .ROTATION_0, 90) ;
        ORIENTATIONS .append(Surface .ROTATION_90, 0) ;
        ORIENTATIONS .append(Surface .ROTATION_180, 270) ;
        ORIENTATIONS .append(Surface .ROTATION_270, 180) ;
    }

----------------------------
原文链接:https://blog.csdn.net/SakuraMashiro/article/details/78346419

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-03-10 13:01:14 重新编辑]
  Java面向对象编程-->按面向对象开发的基础范例
  JavaWeb开发-->JSP技术详解(Ⅰ)
  JSP与Hibernate开发-->通过JPA API检索数据
  Java网络编程-->Socket用法详解
  精通Spring-->Vue组件开发基础
  Vue3开发-->Vue简介
  Android ListView高度问题
  Android Application Theme的实现及管理
  启动和运用Android VNC Server
  回眸Android发展历史
  Android带有粘性头部的ScrollView
  从Android中Activity之间的通信说开来
  Android JSON网络数据交换
  Android使用讯飞SDK开发语音识别及合成小Demo
  Android UI优化—从Android渲染原理理解UI卡顿
  Android性能优化-过度渲染
  Android Camera2.0 API实现摄像头预览并获取人脸关键坐标
  Android仿Volley手写属于自己的万能网络访问框架
  一款在Linux下运行Android应用的软件:xDroid
  Android Resource介绍和使用-学习Android
  Android访问WEBAPI,传递json
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。