vendredi 17 avril 2015

custom camera preserve portrait/landscape orientation while saving image

So I've setup camera using following method -



private void configureCamera(int previewWidth, int previewHeight) {
if(null != camera && null != surfaceHolder.getSurface()) {
Camera.CameraInfo info = new Camera.CameraInfo();

Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
parameters = camera.getParameters();
parameters.set("jpeg-quality", 100);
parameters.setPictureFormat(ImageFormat.JPEG);

Camera.Size previewSize = getBestPreviewSize(parameters);
parameters.setPreviewSize(previewSize.width, previewSize.height);

Camera.Size pictureSize = getBestPictureSize(parameters);
parameters.setPictureSize(pictureSize.width, pictureSize.height);

if(isBackCamera && btnFlash.isSelected())
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
else
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);

if(parameters.isZoomSupported()) {
MAX_ZOOM_LEVEL = parameters.getMaxZoom();
parameters.setZoom(currentZoomLevel);
}

if (previewSize != null) {

Display display = getWindowManager().getDefaultDisplay();
/*switch (display.getRotation()) {
case Surface.ROTATION_0: // This is display orientation
cameraDisplayOrientation = 90; // This is camera orientation
break;
case Surface.ROTATION_90:
cameraDisplayOrientation = 0;
break;
case Surface.ROTATION_180:
cameraDisplayOrientation = 270;
break;
case Surface.ROTATION_270:
cameraDisplayOrientation = 180;
break;
default:
cameraDisplayOrientation = 90;
break;
}*/
int degrees = 0;
switch (display.getRotation()) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}


cameraDisplayOrientation= (info.orientation - degrees + 360) % 360;
Logger.debug("Angle : " + cameraDisplayOrientation);
Logger.debug("Display Orientation is " + display.getRotation());
Logger.debug("Info Orientation " + info.orientation);
if(!isBackCamera) {
cameraDisplayOrientation = 270;
}

camera.setDisplayOrientation(cameraDisplayOrientation);
parameters.setRotation(cameraDisplayOrientation);
camera.setParameters(parameters);
}
}
}


As you can see, I've used both setRoation() on camera parameters to actually specify image orientation and setDisplayOrientation() on camera itself to handle orientation changes in surface preview. ( Both commented and uncommented code doesn't seem to preserve orientation though. When I check Exif data it returns 0)


After doing that, in onPictureTaken callback, I even tried to save image with orientation using Matrix.



private void handlePictureFormation(byte[] data) {
stopCameraPreview();

String parentDirPath = null;
if(FileHelper.isExternalStorageWritable()) {

parentDirPath = myApp.getFileHelper().getDataDir();
} else {
File parentDir = getDir("MYAPP", MODE_PRIVATE);
parentDirPath = parentDir.getAbsolutePath();
}

boolean isWriteSuccess = false;
File pictureFile = new File(parentDirPath, new Date().getTime() + ".jpg");
if(null != pictureFile) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 2;
imageBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);

Matrix matrix = new Matrix();
matrix.postRotate(cameraDisplayOrientation);
imageBitmap = Bitmap.createBitmap(imageBitmap, 0, 0, imageBitmap.getWidth(), imageBitmap.getHeight(), matrix, true);

try {
FileOutputStream fos = new FileOutputStream(pictureFile);
imageBitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();

isWriteSuccess = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Logger.debug("FilePath: " + pictureFile.getAbsolutePath());
}

if(isWriteSuccess) {
Intent intent = new Intent(this, PreviewActivity.class);
intent.putExtra("IMAGE_FILE_PATH", pictureFile.getAbsolutePath());
startActivity(intent);
} else {
// TODO: Convey user that image file saving failed
startCameraPreview();
}
}


ACTUAL PROBLEM




  1. When I take picture in portrait mode, it's fine. It appears as is taken.




  2. But when I take picture in landscape mode ( turning phone 90 degress anti-clockwise). Now this image also get treated as portrait. It should rather in fact should be in landscape orientation. I checked Exif data, and image is not being saved with landscape mode.




Now what I expect to happen is If I capture image in landscape mode ( surface preview works well here) it should appear in landscape. ( To refer what I mean, if you capture image in Instagram in landscape mode, on next screen while applying effects it appears as in landscape. And if image is taken as portrait it appears as is portrait. I want similar thing.


Activity is supposed to be in portrait mode only. So that's been set in manifest.


What's missing here that's giving me so much trouble from last night. :(


Aucun commentaire:

Enregistrer un commentaire