From 6df8ad2cb23392917ce3314ba14f40c8582ddda3 Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Thu, 28 Nov 2019 20:29:13 +0100 Subject: [PATCH] RAW support inside Full2PictureRecorder --- .../picture/Full2PictureRecorder.java | 67 ++++++++++++++++--- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java index 4811e80b..9c47d3a2 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java @@ -3,12 +3,15 @@ package com.otaliastudios.cameraview.picture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.DngCreator; +import android.hardware.camera2.TotalCaptureResult; import android.media.Image; import android.media.ImageReader; import android.os.Build; import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.PictureResult; +import com.otaliastudios.cameraview.controls.PictureFormat; import com.otaliastudios.cameraview.engine.Camera2Engine; import com.otaliastudios.cameraview.engine.action.Action; import com.otaliastudios.cameraview.engine.action.ActionHolder; @@ -16,8 +19,11 @@ import com.otaliastudios.cameraview.engine.action.BaseAction; import com.otaliastudios.cameraview.internal.utils.ExifHelper; import com.otaliastudios.cameraview.internal.utils.WorkerHandler; +import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.nio.ByteBuffer; import androidx.annotation.NonNull; @@ -39,6 +45,8 @@ public class Full2PictureRecorder extends PictureRecorder private final ImageReader mPictureReader; private final CaptureRequest.Builder mPictureBuilder; + private DngCreator mDngCreator; + public Full2PictureRecorder(@NonNull PictureResult.Stub stub, @NonNull Camera2Engine engine, @NonNull CaptureRequest.Builder pictureBuilder, @@ -54,7 +62,9 @@ public class Full2PictureRecorder extends PictureRecorder protected void onStart(@NonNull ActionHolder holder) { super.onStart(holder); mPictureBuilder.addTarget(mPictureReader.getSurface()); - mPictureBuilder.set(CaptureRequest.JPEG_ORIENTATION, mResult.rotation); + if (mResult.format == PictureFormat.JPEG) { + mPictureBuilder.set(CaptureRequest.JPEG_ORIENTATION, mResult.rotation); + } mPictureBuilder.setTag(CameraDevice.TEMPLATE_STILL_CAPTURE); try { holder.applyBuilder(this, mPictureBuilder); @@ -75,6 +85,20 @@ public class Full2PictureRecorder extends PictureRecorder setState(STATE_COMPLETED); } } + + @Override + public void onCaptureCompleted(@NonNull ActionHolder holder, + @NonNull CaptureRequest request, + @NonNull TotalCaptureResult result) { + super.onCaptureCompleted(holder, request, result); + if (mResult.format == PictureFormat.DNG) { + mDngCreator = new DngCreator(holder.getCharacteristics(this), result); + mDngCreator.setOrientation(mResult.rotation); + if (mResult.location != null) { + mDngCreator.setLocation(mResult.location); + } + } + } }; } @@ -86,24 +110,37 @@ public class Full2PictureRecorder extends PictureRecorder @Override public void onImageAvailable(ImageReader reader) { LOG.i("onImageAvailable started."); - // Read the JPEG. Image image = null; //noinspection TryFinallyCanBeTryWithResources try { image = reader.acquireNextImage(); - ByteBuffer buffer = image.getPlanes()[0].getBuffer(); - byte[] bytes = new byte[buffer.remaining()]; - buffer.get(bytes); - mResult.data = bytes; + switch (mResult.format) { + case JPEG: readJpegImage(image); break; + case DNG: readRawImage(image); break; + default: throw new IllegalStateException("Unknown format: " + mResult.format); + } } catch (Exception e) { mResult = null; mError = e; dispatchResult(); return; } finally { - if (image != null) image.close(); + if (image != null) { + image.close(); + } } + // Leave. + LOG.i("onImageAvailable ended."); + dispatchResult(); + } + + private void readJpegImage(@NonNull Image image) { + ByteBuffer buffer = image.getPlanes()[0].getBuffer(); + byte[] bytes = new byte[buffer.remaining()]; + buffer.get(bytes); + mResult.data = bytes; + // Just like Camera1, unfortunately, the camera might rotate the image // and put EXIF=0 instead of respecting our EXIF and leave the image unaltered. mResult.rotation = 0; @@ -113,9 +150,19 @@ public class Full2PictureRecorder extends PictureRecorder ExifInterface.ORIENTATION_NORMAL); mResult.rotation = ExifHelper.readExifOrientation(exifOrientation); } catch (IOException ignore) { } + } - // Leave. - LOG.i("onImageAvailable ended."); - dispatchResult(); + private void readRawImage(@NonNull Image image) { + ByteArrayOutputStream array = new ByteArrayOutputStream(); + BufferedOutputStream stream = new BufferedOutputStream(array); + try { + mDngCreator.writeImage(stream, image); + stream.flush(); + mResult.data = array.toByteArray(); + } catch (IOException e) { + mDngCreator.close(); + try { stream.close(); } catch (IOException ignore) {} + throw new RuntimeException(e); + } } }