zoukankan      html  css  js  c++  java
  • Android 7.1 Camera2 拍照镜像分析

     https://www.cnblogs.com/Free-Thinker/p/6394797.html Android入门——Bitmap和BitmapFactory

    要求:Camera2 拍照 镜像
    主要的想法: 是根据 拍照按钮来跟踪成像照片 最后镜像翻转
    Rk3288 PhotoModule 模式
    A40i     CaptureModule 模式 ,改缩略图 改成像图

    ====================================================
    				RK3288 android7.1
    ====================================================
    
    K:K-Rxxx_7.1_RK3288_FirmwareK_RXXX_RK3288_ANDROID7.1packagesappsCamera2srccomandroidcameraPhotoModule.java
    1.1.拍照按钮回调 onShutterButtonClick
        @Override
        public void onShutterButtonClick() {
    
    1.2.找到拍照最后保存照片 saveFinalPhoto 由Matrix 创建矩阵,并水平平移 镜像
     
    --- a/packages/apps/Camera2/src/com/android/camera/PhotoModule.java
    +++ b/packages/apps/Camera2/src/com/android/camera/PhotoModule.java
    @@ -103,7 +103,7 @@ import java.lang.ref.WeakReference;
     import java.util.ArrayList;
     import java.util.List;
     import java.util.Vector;
    -
    +import android.graphics.Matrix;
     
     public class PhotoModule
             extends CameraModule
    @@ -1644,6 +1644,9 @@ public class PhotoModule
     
             void saveFinalPhoto(final byte[] jpegData, NamedEntity name, final ExifInterface exif,
                     CameraProxy camera) {
    +					
    +			android.util.Log.d("gatsby", "PhotoModule.saveFinalPhoto CameraCaputre");	
    +			
                 int orientation = Exif.getOrientation(exif);
     
                 float zoomValue = 1.0f;
    @@ -1714,8 +1717,17 @@ public class PhotoModule
                             exif.setTag(directionRefTag);
                             exif.setTag(directionTag);
                         }
    +                    Bitmap bitmap = CameraUtil.makeBitmap(jpegData, exifWidth*exifHeight);
    +                    Matrix m = new Matrix();
    +                    m.postScale(-1, 1);
    +                    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
    +                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    +                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    +					 byte[] tm_jpegData;
    +                    tm_jpegData = baos.toByteArray();										
    +					//gatsby
                         getServices().getMediaSaver().addImage(
    -                            jpegData, title, date, mLocation, width, height,
    +                            tm_jpegData, title, date, mLocation, width, height,
                                 orientation, exif, mOnMediaSavedListener);
                     }
                     // Animate capture with real jpeg data instead of a preview
    

    A40i android7.1

    =====================================================
    			     2021.01.15
    ======================================================
    1.1. 拍照按钮
    K:K_A40X_A40i_ANDROID7.1androidpackagesappsCamera2srccomandroidcameraCaptureModule.java
    
        @Override
        public void onShutterButtonClick() {
    			
            if (mCamera == null) {
                return;
            }
    
            int countDownDuration = mSettingsManager
                    .getInteger(SettingsManager.SCOPE_GLOBAL, Keys.KEY_COUNTDOWN_DURATION);
            if (countDownDuration > 0) {
                // Start count down.
                mAppController.getCameraAppUI().transitionToCancel();
                mAppController.getCameraAppUI().hideModeOptions();
                mUI.setCountdownFinishedListener(this);
                mUI.startCountdown(countDownDuration);
                // Will take picture later via listener callback.
            } else {
                takePictureNow();
            }
        }
    1.2. 拍照
    K:K_A40X_A40i_ANDROID7.1androidpackagesappsCamera2srccomandroidcameraCaptureModule.java
    
        private void takePictureNow() {
            if (mCamera == null) {
                Log.i(TAG, "Not taking picture since Camera is closed.");
                return;
            }
    		android.util.Log.d("gatsby", "CaptureModule takePictureNow");	
    		
            CaptureSession session = createAndStartCaptureSession();
            int orientation = mAppController.getOrientationManager().getDeviceOrientation()
                    .getDegrees();
    
            // TODO: This should really not use getExternalCacheDir and instead use
            // the SessionStorage API. Need to sync with gcam if that's OK.
            PhotoCaptureParameters params = new PhotoCaptureParameters(
                    session.getTitle(), orientation, session.getLocation(),
                    mContext.getExternalCacheDir(), this, mPictureSaverCallback,
                    mHeadingSensor.getCurrentHeading(), mZoomValue, 0);
            decorateSessionAtCaptureTime(session);
    		//gatsby take a pircture
            mCamera.takePicture(params, session);
        }
    	
    1.3
    K:K_A40X_A40i_ANDROID7.1androidpackagesappsCamera2srccomandroidcameraoneOneCamera.java
    		
        /**
         * Call this to take a picture.
         *
         * @param params parameters for taking pictures.
         * @param session the capture session for this picture.
         */
        public void takePicture(PhotoCaptureParameters params, CaptureSession session);		
    		
    
    1.4. 定义PictureTaker接口
    K:K_A40X_A40i_ANDROID7.1androidpackagesappsCamera2srccomandroidcameraonev2photoPictureTaker.java
    public interface PictureTaker {
        /**
         * @See {@link OneCamera#takePicture}
         */
        public void takePicture(OneCamera.PhotoCaptureParameters params, CaptureSession session);
    }
    		
    1.5. PictureTakerImpl类 实现 PictureTaker接口 重写了takePicture方法,
    K:K_A40X_A40i_ANDROID7.1androidpackagesappsCamera2srccomandroidcameraonev2photoPictureTakerImpl.java
    
    	class PictureTakerImpl implements PictureTaker {
    		
        @Override
        public void takePicture(OneCamera.PhotoCaptureParameters params, final CaptureSession session) {
    		android.util.Log.d("gatsby", "PictureTakerImpl  takePicture");
            OneCamera.PictureCallback pictureCallback = params.callback;
    
            // Wrap the pictureCallback with a thread-safe adapter which guarantees
            // that they are always invoked on the main thread.
            PictureCallbackAdapter pictureCallbackAdapter =
                    new PictureCallbackAdapter(pictureCallback, mMainExecutor);
    
            final Updatable<Void> imageExposureCallback =
                    pictureCallbackAdapter.provideQuickExposeUpdatable();
    
            final ImageSaver imageSaver = mImageSaverBuilder.build(
                    params.saverCallback,
                    OrientationManager.DeviceOrientation.from(params.orientation),
                    session);
    		//Log future
            mCameraCommandExecutor.execute(new PictureTakerCommand(
                    imageExposureCallback, imageSaver, session));
        }
    		
    1.6. Executing command
    gatsby  (13557): Executing command: PictureTakerCommand{command=com.android.camera.one.v2.photo.SimpleImageCaptureCommand@d754686} START
    K:K_A40X_A40i_ANDROID7.1androidpackagesappsCamera2srccomandroidcameraonev2commandsCameraCommandExecutor.java
        public Future<?> execute(CameraCommand command) {
            if (mClosed) {
                return Futures.immediateFuture(null);
            }
            synchronized (mLock) {
                if (mExecutor == null) {
                    // Create a new executor, if necessary.
                    mExecutor = mExecutorProvider.get();
                }
                checkNotNull(mExecutor);
    			android.util.Log.d("gatsby", "CameraCommandExecutor Future<?> checkNotNull(mExecutor)"+new CommandRunnable(command));
                return mExecutor.submit(new CommandRunnable(command));
            }
        }
    
    1.7. 发送拍照请求  (走到这里断了,研究ing)
    https://blog.csdn.net/afei__/article/details/86326991 
    a.CaptureRequest 表示一个捕捉的请求。根据不同的场景(预览、拍照)创建不同的捕捉请求,并可以配置不同的捕捉属性,如:
    预览分辨率,预览目标,对焦模式、曝光模式等等
    b.CaptureRequest.Builder TEMPLATE_STILL_CAPTURE : 用于创建一个拍照请求。相机会优先保证高画质而不是高帧率。适用于所有相机设备
    
    K:K_A40X_A40i_ANDROID7.1androidpackagesappsCamera2srccomandroidcameraonev2photoSimpleImageCaptureCommand.java
        /**
         * Sends a request to take a picture and blocks until it completes.
         */
    	 //发送一个拍照请求并阻塞直到它完成
        @Override
        public void run(Updatable<Void> imageExposureUpdatable, ImageSaver imageSaver) throws
                InterruptedException, CameraAccessException, CameraCaptureSessionClosedException,
                ResourceAcquisitionFailedException {
            try (FrameServer.Session session = mFrameServer.createExclusiveSession();
                    ImageStream imageStream = mImageReader.createStream(1)) {
    			android.util.Log.d("gatsby", "SimpleImageCaptureCommand  run");
                UpdatableCountDownLatch<Void> exposureLatch = new UpdatableCountDownLatch<>(1);
                RequestBuilder photoRequest = mBuilderFactory.create(CameraDevice
                        .TEMPLATE_STILL_CAPTURE);
                photoRequest.addStream(imageStream);
                MetadataFuture metadataFuture = new MetadataFuture();
                photoRequest.addResponseListener(metadataFuture);
                photoRequest.addResponseListener(forFrameExposure(imageExposureUpdatable));
                photoRequest.addResponseListener(forFrameExposure(exposureLatch));
                session.submitRequest(Arrays.asList(photoRequest.build()),
                        FrameServer.RequestType.NON_REPEATING);
    
                // Release the FrameServer session (allowing subsequent camera
                // operations to occur) as soon as the image is exposed.
                exposureLatch.await();
                session.close();
    
                ImageProxy image = imageStream.getNext();
    			//addFullSizeImage 时间戳 拍照尺寸
                imageSaver.addFullSizeImage(image, metadataFuture.getMetadata());
            } catch (BufferQueue.BufferQueueClosedException e) {
                // If we get here, the request was submitted, but the image
                // never arrived.
                // TODO Log failure and notify the caller
            } finally {
                imageSaver.close();
            }
        }
    	
    1.7.1 获取照片 时间戳、尺寸
    
    01-01 20:16:33.927  3321  3882 D gatsby  : MostRecentImageSaver  addFullSizeImage333->MetadataImage{timestamp=994912780557, width=1280, height=960}
    
        @Override
        public void addFullSizeImage(ImageProxy imageProxy,
                ListenableFuture<TotalCaptureResultProxy> metadata) {
            mFullSizeImages.put(imageProxy.getTimestamp(), new MetadataImage(imageProxy, metadata));
            closeOlderImages();
        }
    
    1.8.重新回到 PictureTakerImpl 这里来 ,JpegImageBackendImageSaver.java 缩略图
    
    	        final ImageSaver imageSaver = mImageSaverBuilder.build(
                    params.saverCallback,
                    OrientationManager.DeviceOrientation.from(params.orientation),
                    session);
    	
    K:K_A40X_A40i_ANDROID7.1androidpackagesappsCamera2srccomandroidcameraonev2imagesaverJpegImageBackendImageSaver.java
    public class JpegImageBackendImageSaver implements ImageSaver.Builder {
    	    @Override
            public void onResultCompressed(TaskImageContainer.TaskInfo task,
                    TaskImageContainer.CompressedPayload payload) {
                if (task.destination == TaskImageContainer.TaskInfo.Destination.FINAL_IMAGE) {
                    // Just start the thumbnail now, since there's no earlier event.
    
                    // Downsample and convert the JPEG payload to a reasonably-sized
                    // Bitmap
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inSampleSize = JPEG_DOWNSAMPLE_FOR_FAST_INDICATOR;
    				//gatsby payload.data  获得data
                    final Bitmap bitmap = BitmapFactory.decodeByteArray(payload.data, 0,
                            payload.data.length, options);
    
                    // If the rotation is implemented as an EXIF flag, we need to
                    // pass this information onto the UI call, since the rotation is
                    // NOT applied to the bitmap directly.
                    int rotation = Exif.getOrientation(payload.data);
                    mSession.updateCaptureIndicatorThumbnail(bitmap, rotation);
                    // Send image to remote devices
                    mPictureSaverCallback.onRemoteThumbnailAvailable(payload.data);
                }
    

     A40i  Camera2 默认镜像 改法

    一.开日志

    --- a/packages/apps/Camera2/src/com/android/camera/debug/Log.java
    +++ b/packages/apps/Camera2/src/com/android/camera/debug/Log.java
    @@ -192,7 +192,10 @@ public class Log {
         }
     
         private static boolean isLoggable(Tag tag, int level) {
    -        if (sSuppressForTesting) {
    +		
    +		return true;
    +		
    +       /* if (sSuppressForTesting) {
                 return false;
             }
             try {
    @@ -208,7 +211,7 @@ public class Log {
             } catch (IllegalArgumentException ex) {
                 e(TAG, "Tag too long:" + tag);
                 return false;
    -        }
    +        }*/
         }
    

     二.预览图

      

     

      

  • 相关阅读:
    Nginx进程信号管理
    Nginx配置缓存服务器
    访问Nginx显示目录
    kubeadm快速安装k8s
    《构建之法》读书笔记(一)
    Android Studio连接SQLite数据库与SQLite Studio实时同步的实现
    关于sqlite数据库与sqlite studio
    AS之去掉顶部标题栏
    今日学习
    AS之AlertDialog使用
  • 原文地址:https://www.cnblogs.com/crushgirl/p/14311734.html
Copyright © 2011-2022 走看看