Android 7.1 RK3288 A40i Camera2 拍照镜像分析

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
====================================================
                RK3288 android7.1
====================================================
 
K:\ZK-Rxxx_7.1_RK3288_Firmware\ZK_RXXX_RK3288_ANDROID7.1\packages\apps\Camera2\src\com\android\camera\PhotoModule.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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
=====================================================
                 2021.01.15
======================================================
1.1. 拍照按钮
K:\ZK_A40X_A40i_ANDROID7.1\android\packages\apps\Camera2\src\com\android\camera\CaptureModule.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:\ZK_A40X_A40i_ANDROID7.1\android\packages\apps\Camera2\src\com\android\camera\CaptureModule.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:\ZK_A40X_A40i_ANDROID7.1\android\packages\apps\Camera2\src\com\android\camera\one\OneCamera.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:\ZK_A40X_A40i_ANDROID7.1\android\packages\apps\Camera2\src\com\android\camera\one\v2\photo\PictureTaker.java
public interface PictureTaker {
    /**
     * @See {@link OneCamera#takePicture}
     */
    public void takePicture(OneCamera.PhotoCaptureParameters params, CaptureSession session);
}
         
1.5. PictureTakerImpl类 实现 PictureTaker接口 重写了takePicture方法,
K:\ZK_A40X_A40i_ANDROID7.1\android\packages\apps\Camera2\src\com\android\camera\one\v2\photo\PictureTakerImpl.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:\ZK_A40X_A40i_ANDROID7.1\android\packages\apps\Camera2\src\com\android\camera\one\v2\commands\CameraCommandExecutor.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:\ZK_A40X_A40i_ANDROID7.1\android\packages\apps\Camera2\src\com\android\camera\one\v2\photo\SimpleImageCaptureCommand.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:\ZK_A40X_A40i_ANDROID7.1\android\packages\apps\Camera2\src\com\android\camera\one\v2\imagesaver\JpegImageBackendImageSaver.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 默认镜像 改法

一.开日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
--- 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;
-        }
+        }*/
     }

 二.A40i 缩略图 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
--- a/packages/apps/Camera2/src/com/android/camera/one/v2/imagesaver/JpegImageBackendImageSaver.java
+++ b/packages/apps/Camera2/src/com/android/camera/one/v2/imagesaver/JpegImageBackendImageSaver.java
@@ -48,6 +48,18 @@ import java.util.concurrent.Executors;
 import javax.annotation.Nonnull;
 import javax.annotation.ParametersAreNonnullByDefault;
  
+import android.graphics.Matrix;
+import android.graphics.BitmapFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+
+import android.os.SystemProperties;
+
 /**
  * Wires up the ImageBackend task submission process to save JPEG images. Camera
  * delivers a JPEG-compressed full-size image. This class does very little work
@@ -74,6 +86,7 @@ public class JpegImageBackendImageSaver implements ImageSaver.Builder {
         @Override
         public void saveAndCloseImage(ImageProxy image, Optional<ImageProxy> thumbnail,
                 ListenableFuture<TotalCaptureResultProxy> metadata) {
+               android.util.Log.d("gatsby", "JpegImageBackendImageSaver.saveAndCloseImage()");
             // TODO: Use thumbnail to speed up RGB thumbnail creation whenever
             // possible. For now, just close it.
             if (thumbnail.isPresent()) {
@@ -132,12 +145,97 @@ public class JpegImageBackendImageSaver implements ImageSaver.Builder {
                 // 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);
+              
+               saveBimap(bitmap);
+              
+               String savePicturePath = "storage/emulated/0/gatsby.jpg";              
+               String savePicturePath2 = "storage/emulated/0/gatsby2.jpg";
+               File savePictureFile2 = new File("/storage/emulated/0/gatsby2.jpg");
+                                          
+               Bitmap rawBitmap = BitmapFactory.decodeFile(savePicturePath);
+               Matrix matrix = new Matrix();
+               matrix.postScale(-1, 1);
+               rawBitmap = Bitmap.createBitmap(rawBitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+               try{
+                   FileOutputStream fileOutputStream = new FileOutputStream(savePictureFile2);
+                   rawBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
+                   fileOutputStream.flush();
+                   fileOutputStream.close();
+               } catch (Exception e){
+                   e.printStackTrace();
+               }
+                          
+               Bitmap rawBitmap2 = BitmapFactory.decodeFile(savePicturePath2);
+                          
+                mSession.updateCaptureIndicatorThumbnail(rawBitmap2, rotation);
                 // Send image to remote devices
                 mPictureSaverCallback.onRemoteThumbnailAvailable(payload.data);
+               RootCommand("rm -rf storage/emulated/0/gatsby.jpg");
+               RootCommand("rm -rf storage/emulated/0/gatsby2.jpg");
             }
+        }
+
  
+
+        public static void saveBimap(Bitmap bitmap) {
+              
+           String savePicturePath = "storage/emulated/0/gatsby.jpg";
+           File file = new File(savePicturePath);
+            if(!file.exists()){
+                try {
+                    file.createNewFile();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            try {
+                FileOutputStream out = new FileOutputStream(file);
+                if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) {
+                    out.flush();
+                    out.close();
+                }
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+      
         }
+          
+        private void RootCommand(String cmd) {
+           android.util.Log.d("gatsby", "JpegImageBackendImageSaver.RootCommand");
+            Process process = null;
+            DataOutputStream os = null;
+            DataInputStream is = null;
+            try {
+                process = Runtime.getRuntime().exec("/system/xbin/su");
+                os = new DataOutputStream(process.getOutputStream());
+                os.writeBytes(cmd + "\n");
+                os.writeBytes("exit\n");
+                os.flush();
+      
+                int aa = process.waitFor();
+                is = new DataInputStream(process.getInputStream());
+      
+                byte[] buffer = new byte[is.available()];
+                is.read(buffer);
+      
+                String out = new String(buffer);
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                try {
+                    if (os != null) {
+                        os.close();
+                    }
+                    if (is != null) {
+                        is.close();
+                    }
+                    process.destroy();
+                } catch (Exception e) {
+                }
+            }
+        }     
  
         @Override
         public void onResultUncompressed(TaskImageContainer.TaskInfo task,

 三.A40i 成像工具类 中改成像图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
--- a/packages/apps/Camera2/src/com/android/camera/data/PhotoDataFactory.java
+++ b/packages/apps/Camera2/src/com/android/camera/data/PhotoDataFactory.java
@@ -26,6 +26,13 @@ import com.android.camera.util.Size;
  
 import java.util.Date;
  
+import android.graphics.Matrix;
+import android.graphics.BitmapFactory;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
 public class PhotoDataFactory {
     private static final Log.Tag TAG = new Log.Tag("PhotoDataFact");
  
@@ -68,6 +75,27 @@ public class PhotoDataFactory {
         Location location = Location.from(latitude, longitude);
  
         Uri uri = PhotoDataQuery.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build();
+      
+       File filePhotoDataPath = new File(filePath);
+       android.util.Log.d("gatsby", "PhotoDataFactory.filePhotoDataPath");
+       Bitmap rawBitmap = BitmapFactory.decodeFile(filePath);
+       Matrix matrix = new Matrix();
+       matrix.postScale(-1, 1);
+       rawBitmap = Bitmap.createBitmap(rawBitmap, 0, 0, rawBitmap.getWidth(), rawBitmap.getHeight(), matrix, true);
+       try {
+           FileOutputStream fileOutputStream = new FileOutputStream(filePhotoDataPath);
+           rawBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
+           fileOutputStream.flush();
+           fileOutputStream.close();
+       } catch (Exception e){
+           e.printStackTrace();
+       }
+      
+       try {
+           Thread.sleep(300);
+       } catch (InterruptedException e) {
+           e.printStackTrace();
+       }      
  
         return new FilmstripItemData(
               id,

  

 

posted @   CrushGirl  阅读(1590)  评论(0编辑  收藏  举报
(评论功能已被禁用)
点击右上角即可分享
微信分享提示