main
Matthew 8 months ago
parent d0ac749705
commit 73a8dd7216

@ -36,10 +36,14 @@ android {
compileSdk 33 compileSdk 33
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 24
targetSdkVersion 27 targetSdkVersion 27
} }
lint {
baseline = file("lint-baseline.xml")
}
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8

@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.xypower.mppreview",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0",
"outputFile": "Application-release.apk"
}
],
"elementType": "File"
}

@ -16,7 +16,7 @@
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.camera2raw" package="com.xypower.mppreview"
android:versionCode="1" android:versionCode="1"
android:versionName="1.0"> android:versionName="1.0">
@ -34,7 +34,8 @@
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"
android:theme="@style/MaterialTheme"> android:theme="@style/MaterialTheme">
<activity android:name="com.example.android.camera2raw.CameraActivity" <activity android:name="com.xypower.mppreview.CameraActivity"
android:screenOrientation="landscape"
android:label="@string/app_name"> android:label="@string/app_name">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.example.android.camera2raw; package com.xypower.mppreview;
import android.content.Context; import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.example.android.camera2raw; package com.xypower.mppreview;
import android.Manifest; import android.Manifest;
import android.app.Activity; import android.app.Activity;
@ -66,6 +66,7 @@ import android.view.Surface;
import android.view.TextureView; import android.view.TextureView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Switch;
import android.widget.Toast; import android.widget.Toast;
import java.io.File; import java.io.File;
@ -301,13 +302,6 @@ public class Camera2RawFragment extends Fragment
*/ */
private RefCountedAutoCloseable<ImageReader> mJpegImageReader; private RefCountedAutoCloseable<ImageReader> mJpegImageReader;
/**
* A reference counted holder wrapping the {@link ImageReader} that handles RAW image captures.
* This is used to allow us to clean up the {@link ImageReader} when all background tasks using
* its {@link Image}s have completed.
*/
private RefCountedAutoCloseable<ImageReader> mRawImageReader;
/** /**
* Whether or not the currently configured camera device is fixed-focus. * Whether or not the currently configured camera device is fixed-focus.
*/ */
@ -323,11 +317,6 @@ public class Camera2RawFragment extends Fragment
*/ */
private final TreeMap<Integer, ImageSaver.ImageSaverBuilder> mJpegResultQueue = new TreeMap<>(); private final TreeMap<Integer, ImageSaver.ImageSaverBuilder> mJpegResultQueue = new TreeMap<>();
/**
* Request ID to {@link ImageSaver.ImageSaverBuilder} mapping for in-progress RAW captures.
*/
private final TreeMap<Integer, ImageSaver.ImageSaverBuilder> mRawResultQueue = new TreeMap<>();
/** /**
* {@link CaptureRequest.Builder} for the camera preview * {@link CaptureRequest.Builder} for the camera preview
*/ */
@ -411,20 +400,6 @@ public class Camera2RawFragment extends Fragment
}; };
/**
* This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
* RAW image is ready to be saved.
*/
private final ImageReader.OnImageAvailableListener mOnRawImageAvailableListener
= new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
dequeueAndSaveImage(mRawResultQueue, mRawImageReader);
}
};
/** /**
* A {@link CameraCaptureSession.CaptureCallback} that handles events for the preview and * A {@link CameraCaptureSession.CaptureCallback} that handles events for the preview and
* pre-capture sequence. * pre-capture sequence.
@ -513,9 +488,6 @@ public class Camera2RawFragment extends Fragment
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
long timestamp, long frameNumber) { long timestamp, long frameNumber) {
String currentDateTime = generateTimestamp(); String currentDateTime = generateTimestamp();
File rawFile = new File(Environment.
getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
"RAW_" + currentDateTime + ".dng");
File jpegFile = new File(Environment. File jpegFile = new File(Environment.
getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
"JPEG_" + currentDateTime + ".jpg"); "JPEG_" + currentDateTime + ".jpg");
@ -523,15 +495,12 @@ public class Camera2RawFragment extends Fragment
// Look up the ImageSaverBuilder for this request and update it with the file name // Look up the ImageSaverBuilder for this request and update it with the file name
// based on the capture start time. // based on the capture start time.
ImageSaver.ImageSaverBuilder jpegBuilder; ImageSaver.ImageSaverBuilder jpegBuilder;
ImageSaver.ImageSaverBuilder rawBuilder;
int requestId = (int) request.getTag(); int requestId = (int) request.getTag();
synchronized (mCameraStateLock) { synchronized (mCameraStateLock) {
jpegBuilder = mJpegResultQueue.get(requestId); jpegBuilder = mJpegResultQueue.get(requestId);
rawBuilder = mRawResultQueue.get(requestId);
} }
if (jpegBuilder != null) jpegBuilder.setFile(jpegFile); if (jpegBuilder != null) jpegBuilder.setFile(jpegFile);
if (rawBuilder != null) rawBuilder.setFile(rawFile);
} }
@Override @Override
@ -545,23 +514,15 @@ public class Camera2RawFragment extends Fragment
// Look up the ImageSaverBuilder for this request and update it with the CaptureResult // Look up the ImageSaverBuilder for this request and update it with the CaptureResult
synchronized (mCameraStateLock) { synchronized (mCameraStateLock) {
jpegBuilder = mJpegResultQueue.get(requestId); jpegBuilder = mJpegResultQueue.get(requestId);
rawBuilder = mRawResultQueue.get(requestId);
if (jpegBuilder != null) { if (jpegBuilder != null) {
jpegBuilder.setResult(result); jpegBuilder.setResult(result);
sb.append("Saving JPEG as: "); sb.append("Saving JPEG as: ");
sb.append(jpegBuilder.getSaveLocation()); sb.append(jpegBuilder.getSaveLocation());
} }
if (rawBuilder != null) {
rawBuilder.setResult(result);
if (jpegBuilder != null) sb.append(", ");
sb.append("Saving RAW as: ");
sb.append(rawBuilder.getSaveLocation());
}
// If we have all the results necessary, save the image to a file in the background. // If we have all the results necessary, save the image to a file in the background.
handleCompletionLocked(requestId, jpegBuilder, mJpegResultQueue); handleCompletionLocked(requestId, jpegBuilder, mJpegResultQueue);
handleCompletionLocked(requestId, rawBuilder, mRawResultQueue);
finishedCaptureLocked(); finishedCaptureLocked();
} }
@ -575,7 +536,6 @@ public class Camera2RawFragment extends Fragment
int requestId = (int) request.getTag(); int requestId = (int) request.getTag();
synchronized (mCameraStateLock) { synchronized (mCameraStateLock) {
mJpegResultQueue.remove(requestId); mJpegResultQueue.remove(requestId);
mRawResultQueue.remove(requestId);
finishedCaptureLocked(); finishedCaptureLocked();
} }
showToast("Capture failed!"); showToast("Capture failed!");
@ -612,6 +572,17 @@ public class Camera2RawFragment extends Fragment
// view.findViewById(R.id.info).setOnClickListener(this); // view.findViewById(R.id.info).setOnClickListener(this);
mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture); mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
view.findViewById(R.id.hdr).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
closeCamera();
// stopBackgroundThread();
// startBackgroundThread();
openCamera();
}
});
// Setup a new OrientationEventListener. This is used to handle rotation events like a // Setup a new OrientationEventListener. This is used to handle rotation events like a
// 180 degree rotation that do not normally trigger a call to onCreate to do view re-layout // 180 degree rotation that do not normally trigger a call to onCreate to do view re-layout
// or otherwise cause the preview TextureView's size to change. // or otherwise cause the preview TextureView's size to change.
@ -701,19 +672,23 @@ public class Camera2RawFragment extends Fragment
show(getFragmentManager(), "dialog"); show(getFragmentManager(), "dialog");
return false; return false;
} }
View rootView = getView();
Switch hdrSwitch = (Switch)(rootView.findViewById(R.id.hdr));
boolean hdrChecked = hdrSwitch.isChecked();
final String expectedCameraId = hdrChecked ? "1" : "0";
try { try {
// Find a CameraDevice that supports RAW captures, and configure state. // Find a CameraDevice that supports RAW captures, and configure state.
for (String cameraId : manager.getCameraIdList()) { for (String cameraId : manager.getCameraIdList()) {
CameraCharacteristics characteristics
= manager.getCameraCharacteristics(cameraId);
// We only use a camera that supports RAW in this sample. if (!TextUtils.equals(cameraId, expectedCameraId)) {
if (!contains(characteristics.get(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES),
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
continue; continue;
} }
CameraCharacteristics characteristics
= manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get( StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
@ -722,10 +697,6 @@ public class Camera2RawFragment extends Fragment
Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
new CompareSizesByArea()); new CompareSizesByArea());
Size largestRaw = Collections.max(
Arrays.asList(map.getOutputSizes(ImageFormat.RAW_SENSOR)),
new CompareSizesByArea());
synchronized (mCameraStateLock) { synchronized (mCameraStateLock) {
// Set up ImageReaders for JPEG and RAW outputs. Place these in a reference // Set up ImageReaders for JPEG and RAW outputs. Place these in a reference
// counted wrapper to ensure they are only closed when all background tasks // counted wrapper to ensure they are only closed when all background tasks
@ -738,14 +709,6 @@ public class Camera2RawFragment extends Fragment
mJpegImageReader.get().setOnImageAvailableListener( mJpegImageReader.get().setOnImageAvailableListener(
mOnJpegImageAvailableListener, mBackgroundHandler); mOnJpegImageAvailableListener, mBackgroundHandler);
if (mRawImageReader == null || mRawImageReader.getAndRetain() == null) {
mRawImageReader = new RefCountedAutoCloseable<>(
ImageReader.newInstance(largestRaw.getWidth(),
largestRaw.getHeight(), ImageFormat.RAW_SENSOR, /*maxImages*/ 5));
}
mRawImageReader.get().setOnImageAvailableListener(
mOnRawImageAvailableListener, mBackgroundHandler);
mCharacteristics = characteristics; mCharacteristics = characteristics;
mCameraId = cameraId; mCameraId = cameraId;
} }
@ -875,10 +838,6 @@ public class Camera2RawFragment extends Fragment
mJpegImageReader.close(); mJpegImageReader.close();
mJpegImageReader = null; mJpegImageReader = null;
} }
if (null != mRawImageReader) {
mRawImageReader.close();
mRawImageReader = null;
}
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera closing.", e); throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
@ -935,8 +894,7 @@ public class Camera2RawFragment extends Fragment
// Here, we create a CameraCaptureSession for camera preview. // Here, we create a CameraCaptureSession for camera preview.
mCameraDevice.createCaptureSession(Arrays.asList(surface, mCameraDevice.createCaptureSession(Arrays.asList(surface,
mJpegImageReader.get().getSurface(), mJpegImageReader.get().getSurface()), new CameraCaptureSession.StateCallback() {
mRawImageReader.get().getSurface()), new CameraCaptureSession.StateCallback() {
@Override @Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) { public void onConfigured(CameraCaptureSession cameraCaptureSession) {
synchronized (mCameraStateLock) { synchronized (mCameraStateLock) {
@ -1047,8 +1005,11 @@ public class Camera2RawFragment extends Fragment
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
// For still image captures, we always use the largest available size. // For still image captures, we always use the largest available size.
Size largestJpeg = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), Size[] resolutions = map.getHighResolutionOutputSizes(ImageFormat.JPEG);
new CompareSizesByArea()); if (resolutions == null) {
resolutions = map.getOutputSizes(ImageFormat.JPEG);
}
Size largestJpeg = Collections.max(Arrays.asList(resolutions), new CompareSizesByArea());
// Find the rotation of the device relative to the native device orientation. // Find the rotation of the device relative to the native device orientation.
int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
@ -1215,7 +1176,6 @@ public class Camera2RawFragment extends Fragment
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(mJpegImageReader.get().getSurface()); captureBuilder.addTarget(mJpegImageReader.get().getSurface());
captureBuilder.addTarget(mRawImageReader.get().getSurface());
// Use the same AE and AF modes as the preview. // Use the same AE and AF modes as the preview.
setup3AControlsLocked(captureBuilder); setup3AControlsLocked(captureBuilder);
@ -1238,7 +1198,6 @@ public class Camera2RawFragment extends Fragment
.setCharacteristics(mCharacteristics); .setCharacteristics(mCharacteristics);
mJpegResultQueue.put((int) request.getTag(), jpegBuilder); mJpegResultQueue.put((int) request.getTag(), jpegBuilder);
mRawResultQueue.put((int) request.getTag(), rawBuilder);
mCaptureSession.capture(request, mCaptureCallback, mBackgroundHandler); mCaptureSession.capture(request, mCaptureCallback, mBackgroundHandler);

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.example.android.camera2raw; package com.xypower.mppreview;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;

@ -17,15 +17,15 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.example.android.camera2raw.AutoFitTextureView <com.xypower.mppreview.AutoFitTextureView
android:id="@+id/texture" android:id="@+id/texture"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentTop="true" /> android:layout_alignParentTop="true"
android:layout_alignParentBottom="true" />
<FrameLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
@ -33,8 +33,8 @@
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_below="@id/texture" android:layout_below="@id/texture"
android:layout_toEndOf="@id/texture" android:layout_toEndOf="@id/texture"
android:background="#4285f4" android:background="#504285f4"
android:orientation="horizontal"> android:orientation="vertical">
<Button <Button
android:id="@+id/picture" android:id="@+id/picture"
@ -43,6 +43,18 @@
android:layout_gravity="center" android:layout_gravity="center"
android:text="@string/picture" /> android:text="@string/picture" />
</FrameLayout> <Switch
android:id="@+id/hdr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:text="HDR"
android:textOff="HDR"/>
</LinearLayout>
</RelativeLayout> </RelativeLayout>

@ -19,4 +19,4 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#000" android:background="#000"
tools:context="com.example.android.camera2raw.CameraActivity" /> tools:context="com.xypower.mppreview.CameraActivity" />

@ -17,28 +17,40 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.example.android.camera2raw.AutoFitTextureView <com.xypower.mppreview.AutoFitTextureView
android:id="@+id/texture" android:id="@+id/texture"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentTop="true" /> android:layout_alignParentTop="true" />
<FrameLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:orientation="horizontal"
android:background="#4285f4"> android:background="#504285f4">
<Button <Button
android:id="@+id/picture" android:id="@+id/picture"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:text="@string/picture" /> android:text="@string/picture" />
</FrameLayout> <Switch
android:id="@+id/hdr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:text="HDR"
android:textOff="HDR"/>
</LinearLayout>
</RelativeLayout> </RelativeLayout>

@ -16,7 +16,7 @@
--> -->
<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us --> <!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.camera2raw.tests" package="com.xypower.mppreview.tests"
android:versionCode="1" android:versionCode="1"
android:versionName="1.0"> android:versionName="1.0">
@ -34,7 +34,7 @@
--> -->
<instrumentation <instrumentation
android:name="android.test.InstrumentationTestRunner" android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.android.camera2raw" android:targetPackage="com.xypower.mppreview"
android:label="Tests for com.example.android.camera2raw" /> android:label="Tests for com.xypower.mppreview" />
</manifest> </manifest>

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.example.android.camera2raw.tests; package com.xypower.mppreview.tests;
import com.example.android.camera2raw.*; import com.xypower.mppreview.*;
import android.test.ActivityInstrumentationTestCase2; import android.test.ActivityInstrumentationTestCase2;
Loading…
Cancel
Save