Reputation: 324
I have an app that takes picture in portrait mode and everything is working except that the preview is a different size than the image after the picture is take. The preview seems distorted and blurry but fills the entire screen. After the picture is taken, the image is clear but is either shorter than the device height or the width is smaller (depending on what device is being used).
Below are some image examples and some code that I'm using.
Camera Preview Code to Show in Portrait:
protected int getRotationDegrees() {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(0, info);
int rotation = ((WindowManager) mContext
.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
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;
}
int result = (info.orientation - degrees + 360) % 360;
return result;
}
Code to Rotate Image After Picture Taken:
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap pictureBitmap = null;
pictureBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
int rotationDegrees = mCameraPreview.getRotationDegrees();
//mRotation = setCameraDisplayOrientation(MainActivity.this, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);
Matrix matrix = new Matrix();
matrix.postRotate(rotationDegrees);
//Bitmap scaledBitmap = Bitmap.createScaledBitmap(pictureBitmap ,previewWidth ,previewHeight ,true);
//Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
Bitmap rotatedBitmap = Bitmap.createBitmap(pictureBitmap , 0, 0, pictureBitmap.getWidth(), pictureBitmap.getHeight(), matrix, true);
//rotatedBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
ImageView previewImage = (ImageView) findViewById(R.id.preview_image);
previewImage.setImageBitmap(rotatedBitmap);
mCameraPreview.setVisibility(View.INVISIBLE);
mButtonCapture.setVisibility(View.INVISIBLE);
//flCameraPreview.setVisibility(View.INVISIBLE);
}
};
Has anyone come across this issue before? I'm still trying to understand the camera API. Thanks in advance!
EDIT: Code that I use to select my preview and picture sizes.
private Camera.Size getOptimalSize(List<Camera.Size> sizes, int h, int w) {
final double ASPECT_TOLERANCE = 0.05;
double targetRatio = (double) w/h;
if (sizes == null) {
return null;
}
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
Upvotes: 3
Views: 4555
Reputation: 324
I found this comment in another post that solved my issue!
It changes the size of the view so that the image isn't stretched while always trying to fill the screen.
Upvotes: 2
Reputation: 57173
This situation is quite typical. The aspect ratio of preview frame may not be exactly the same as the captured image. You probably iterate through the supported preview sizes to choose one that best fits your SurfaceView (I hope you do this correctly). You need similar iteration through the supported picture sizes. If you cannot find a satisfactory pair where the aspect ratios are the same, you need to "crop" visually either the SurfaceView or the ImageView. The easiest way to achieve such crop is to overlay the unwanted parts of the view with some other non-transparent view.
It is also possible to force a view (SurfaceView or ImageView) to "hang out", be partially out of the screen.
Upvotes: 0