I try to do some ImageProcessing on the current frame of the Preview in Android. In case of every other smartphone, it works pretty good. But now, I have to make the app accessible for the Nexus 5x.
There I get a 180 degree turned Image from the Preview. How can I fix that? Here my code for setting up my camera and the Preview:
private void resetCamera(int width, int height){
Log.d(TAG, "Reset Camera!");
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
for (String cameraId : cameraManager.getCameraIdList()) {
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
mSensorOrientation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
mImageReader = ImageReader.newInstance(width,
height,
ImageFormat.YUV_420_888,
10);
mImageReader.setOnImageAvailableListener(mOnImageAvailableTrack,
mBackgroundHandler);
mPreviewSize = getPreferredPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height);
mCameraId = cameraId;
return;
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
Preview:
private void createTrackingPreviewSession(){
try{
SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
mPreviewCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewCaptureBuilder.addTarget(previewSurface);
mPreviewCaptureBuilder.addTarget(mImageReader.getSurface());
int rotation = getWindowManager().getDefaultDisplay().getRotation();
mPreviewCaptureBuilder.set(CaptureRequest.JPEG_ORIENTATION,
getOrientation(rotation));
mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback(){
@Override
public void onConfigured(CameraCaptureSession session) {
if(mCameraDevice == null){
return;
}
try{
Toast.makeText(getApplicationContext(), "Create Tracking Session", Toast.LENGTH_SHORT).show();
mPreviewCapture = mPreviewCaptureBuilder.build();
mCaptureSession = session;
mCaptureSession.setRepeatingRequest(
mPreviewCapture,
mSessionCaptureCallback,
mBackgroundHandler
);
} catch(CameraAccessException e){
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
Toast.makeText(
getApplicationContext(),
"create Camera session failed!",
Toast.LENGTH_SHORT
).show();
}
}, null);
} catch(CameraAccessException e){
e.printStackTrace();
}
}
As you can see, I tried to use the fix for capturing a Image, but it didn't help I still get a turned Image from the Preview.
If it is possible, I would like a Solution, which tries to change the settings of the camera. I don't want to turn the Image by myself after I get it through the bound ImageReader.
After understanding your question properly I would try to do the following, if you aren't already. I think your problem does not reside in your previewCaptureSession but rather in your code to take a picture.
I guess you are using a different CaptureRequest.Builder with the CameraDevice.TEMPLATE_STILL_CAPTURE template properly.
For this Builder you have to set the JPEG orientation. As I already said in the comments, some camera devices have 90° and others a 270° rotation.
To set the proper Orientation, implement the following two snippets.
private static SparseIntArray ORIENTATIONS = new SparseIntArray();
static{
ORIENTATIONS.append(Surface.ROTATION_0, 0);
ORIENTATIONS.append(Surface.ROTATION_90, 90);
ORIENTATIONS.append(Surface.ROTATION_180, 180);
ORIENTATIONS.append(Surface.ROTATION_270, 270);
}
private int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics, int deviceOrientation){
int sensorOrientation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
deviceOrientation = ORIENTATIONS.get(deviceOrientation);
return (sensorOrientation + deviceOrientation + 360) % 360;
}
Or use your own logic / implementation.
For your captureRequestBuilder, which you use to capture your images, set the JPEG_ORIENTATION as follows:
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, sensorToDevice(cameraCharacteristics, rotation));
This is how I capture my images in my App, and my saved Images are properly rotated! If this is how you do it, I would suggest you add your code to actually take a picture, not only your preview Session.
Hope that helps!