Weird preview on custom camera implementation - android

I've implemented a custom camera activity in my app. The camera works pretty well on my nexus 5. However on an Alcatel One Touch Star, when I stop the preview to show the snapshot, I get this preview
Furthermore, the byte array of the PictureCallback is correct. Infact, if I decode the array into a Bitmap, I can see it correctly.
Here is my implementation of the SurfaceView as camera preview.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private int mPhotoRotation;
public CameraPreview(Context context) {
super(context);
}
#SuppressLint("InlinedApi")
#SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
Camera.Parameters parameters = camera.getParameters();
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes != null && focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
else if (focusModes != null && focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
if (parameters.getSupportedFlashModes() != null && parameters.getSupportedFlashModes().contains(Parameters.FLASH_MODE_AUTO))
parameters.setFlashMode(Parameters.FLASH_MODE_AUTO);
camera.setParameters(parameters);
mHolder = getHolder();
mHolder.addCallback(this);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mCamera != null) {
mCamera.stopPreview();
Parameters parameters = mCamera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
Camera.Size size = getOptimalPreviewSize(previewSizes, width, height);
parameters.setPreviewSize(size.width, size.height);
mCamera.setParameters(parameters);
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mPhotoRotation = 0;
if (display.getRotation() == Surface.ROTATION_0) {
mPhotoRotation = 90;
} else if (display.getRotation() == Surface.ROTATION_270) {
mPhotoRotation = 180;
}
mCamera.setDisplayOrientation(mPhotoRotation);
mCamera.startPreview();
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
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;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public int getPhotoRotation() {
return mPhotoRotation;
}
}
When the user take the photo, this code is executed
mCamera.takePicture(null, null, mPictureCallback);
and the callback just keep a backup of the byte array and stop the preview.
mPictureCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
mPhotoJpeg = data;
mCamera.stopPreview();
}
};
So what is the cause of this behaviour? Why only on an alcatel and not on the nexus 5?

Related

preview is not stretching but when i click on start record preview stretching

When i try to record using my custom camera its preview showing normally and in good shape but when i click on start button preview changed and stretching.
public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder mHolder;
private Camera mCamera;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
private int mRatioWidth = 0;
private int mRatioHeight = 0;
public MyCameraSurfaceView(Context context, Camera camera) {
super(context);
mCamera = camera;
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
for(Camera.Size str: mSupportedPreviewSizes)
Log.e("Ji", str.width + "/" + str.height);
setKeepScreenOn(true);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int weight,
int height) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
// The Surface has been created, now tell the camera where to draw the preview.
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
Here is onMesuare method for calculations
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
if (0 == mRatioWidth || 0 == mRatioHeight) {
setMeasuredDimension(width, height);
} else {
if (width < height * mRatioWidth / mRatioHeight) {
setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
} else {
setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
}
}
And For getting Size of Screen here is method.
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
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.height / size.width;
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;
}
}
Thanks for help in advance...

Extending android surface view for camera to support all devices

I have created a CameraSurfaceView class which provides logic for implementing the camera preview. Everything works fine on the devices I have tried. Nexus 5, Nexus 5X, Nexus 6P and even a Samsung Galaxy S5.
But for some reason on the Samsung Galaxy S6 Edge, I get a Runtime exception of
android.hardware.Camera.native_setParameters(Native Method)
I have narrowed it down to the the following in class
parameters.setPictureSize(mPreviewSize.width, mPreviewSize.height);
Here is my class:
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private Camera mCamera;
private SurfaceHolder mSurfaceHolder;
private List<Camera.Size> mSupportedPreviewSizes;
private Camera.Size mPreviewSize;
public CameraSurfaceView(Context context, Camera camera) {
super(context);
mCamera = camera;
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mSurfaceHolder.getSurface() == null) {
// preview surface does not exist
return;
}
try {
// stop preview before making changes
mCamera.stopPreview();
} catch (Exception e) {
Timber.e(e, e.getMessage());
}
// set preview size and make any resize, rotate or reformatting changes here
// start preview with new settings
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setPictureSize(mPreviewSize.width, mPreviewSize.height);
if (parameters.getSupportedFocusModes()
.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
} catch (Exception e) {
Timber.e(e, "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
float ratio;
if (mPreviewSize.height >= mPreviewSize.width) {
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
} else {
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
}
// One of these methods should be used, second method squishes preview slightly
setMeasuredDimension(width, (int) (width * ratio));
// setMeasuredDimension((int) (width * ratio), height);
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double aspectTolerance = 0.1;
double targetRatio = (double) h / w;
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.height / size.width;
if (Math.abs(ratio - targetRatio) > aspectTolerance) {
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;
}
}
How do I set the picture size correctly for this device or any others with the same issue?
Does anyone have a good example of Camera SurfaceView logic that would work for most devices?
Thanks.
Turns out I was using the supportedPreviewSizes to set the picture size as opposed to the supportedPictureSizes in the camera parameters.
Below is my new CameraSurfaceView class:
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private Camera mCamera;
private SurfaceHolder mSurfaceHolder;
private List<Camera.Size> mSupportedPreviewSizes;
private List<Camera.Size> mSupportedPictureSizes;
private Camera.Size mPreviewSize;
private Camera.Size mPictureSize;
public CameraSurfaceView(Context context, Camera camera) {
super(context);
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
mCamera = camera;
Camera.Parameters parameters = mCamera.getParameters();
mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
mSupportedPictureSizes = parameters.getSupportedPictureSizes();
if (parameters.getSupportedFocusModes()
.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
mCamera.setParameters(parameters);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (mSurfaceHolder.getSurface() == null) {
// preview surface does not exist
return;
}
try {
// stop preview before making changes
mCamera.stopPreview();
} catch (Exception e) {
Timber.e(e, e.getMessage());
}
// set preview size and make any resize, rotate or reformatting changes here
// start preview with new settings
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setPictureSize(mPictureSize.width, mPictureSize.height);
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
} catch (Exception e) {
Timber.e(e, "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
if (mSupportedPictureSizes != null) {
mPictureSize = getOptimalPreviewSize(mSupportedPictureSizes, mPreviewSize.width,
mPreviewSize.height);
}
float ratio;
if (mPreviewSize.height >= mPreviewSize.width) {
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
} else {
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
}
setMeasuredDimension(width, (int) (width * ratio));
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double aspectTolerance = 0.1;
double targetRatio = (double) h / w;
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.height / size.width;
if (Math.abs(ratio - targetRatio) > aspectTolerance) {
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;
}
}

How to get full size image from custom front camera with full screen length

I am making an android app which is using the front camera of device and it has to take picture in portrait form also it would want to save picture in the same result as it is showing in the preview but when I take photo and save the bitmap the bitmap seems very awkward as it increases the size in length. It seems that I am doing something wrong which is squeezing the camera picture while saving.
I have searched many links and came to know that for this we have to set the aspect ratio. SO I did not get it. I want help in my coding because I have about to complete my app and it is working best on samsung grand and S4 but it is not Working good on Lg g3 and .
Here is what I am doing with surfaceview class . I am sharing the only surface view class As I know that there is something wrong here , rest of other classes are easy .
CameraPreview.java
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private Camera camera;
public static SurfaceHolder holder;
private Activity activity;
public CameraPreview(Context context, AttributeSet attrs, Activity activity) {
super(context, attrs);
}
public CameraPreview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CameraPreview(Context context) {
super(context);
}
public void init(Camera camera,Activity activity) {
this.camera = camera;
this.activity = activity;
initSurfaceHolder();
}
#SuppressWarnings("deprecation") // needed for < 3.0
private void initSurfaceHolder() {
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
initCamera(holder);
}
private void initCamera(SurfaceHolder holder) {
try {
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
Camera.Size previewSize = previewSizes.get(0); //480h x 720w
for(int i = 0 ; i<=6;i++){
Log.v("preview sizes"+previewSizes.get(i));
Camera.Size previewSizedemo = previewSizes.get(i);
Log.v("preview size are" +previewSizedemo.width+""+ previewSizedemo.height+"of"+i);
Camera.Size previewSizedemo1 = previewSizes.get(1);
Log.v("preview size of 0 is" +previewSizedemo1.width+""+ previewSizedemo1.height);
}
parameters.setPreviewSize(previewSize.width,previewSize.height);
parameters.setZoom(Camera.Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX);
camera.setParameters(parameters);
requestLayout();
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (Exception e) {
Log.d("Error setting camera preview", e);
}
}
#Override
public void surfaceChanged(SurfaceHolder mHolder, int format, int width, int height) {
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
Camera.Size previewSize = previewSizes.get(0); //480h x 720w
parameters.setPreviewSize(previewSize.width,previewSize.height);
requestLayout();
camera.setParameters(parameters);
Display display = ((WindowManager)activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0) {
camera.setDisplayOrientation(90);
parameters.setPreviewSize(previewSize.width, previewSize.height);
} else if(display.getRotation() == Surface.ROTATION_270) {
camera.setDisplayOrientation(180);
parameters.setPreviewSize(previewSize.width, previewSize.height);
}
camera.startPreview();
}// end surfaceChanged
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e("TABACT"+"surfaceDestroyed()");
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
this.getHolder().removeCallback(this);
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
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;
}
Keep in Mind I am only using front facing camera only. Please help me in it how can I take full length image from front camera with out getting inverted to any other angle then portrait.

SurfaceView stretches camera preview

I have added FrameLayout which display camera preview in it, but the preview is getting stretched.
I have tried solution given in https://stackoverflow.com/a/19592492/1597844 but that does not help either.
Can you help know what is wrong in my code?
Output that I am getting is
Upper Image gets skewed horizontally (portrait mode) and the below one gets stretched vertically (Landscape mode)
Code that I am using is
mCamera = Camera.open(findBackFacingCamera());
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("jpeg-quality", 100);
parameters.setPictureFormat(PixelFormat.JPEG);
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setParameters(parameters);
mPicture = getPictureCallback();
mPreview = new CameraPreview(myContext, mCamera);
backCameraPreview.removeAllViews();
backCameraPreview.addView(mPreview);
Method for getting optimal preview size
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.05;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (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 (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
My xml looks like this
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="2">
<FrameLayout
android:id="#+id/dual_camera_capture_activity_ll_back_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/white"
android:orientation="horizontal"
android:padding="10dp" />
<FrameLayout
android:id="#+id/dual_camera_capture_activity_fl_front_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_weight="1"
android:background="#android:color/white"
android:orientation="horizontal"
android:padding="10dp" />
</LinearLayout>
This is my CameraPreview class that is SurfaceView
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private final Context mContext;
private SurfaceHolder mHolder;
private Camera mCamera;
private static String TAG = "Dual Camera";
private float mDist;
public CameraPreview(Context context, Camera camera) {
super(context);
mContext = context;
mCamera = camera;
mHolder = getHolder();
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mHolder.addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surface created");
// The Surface has been created, now tell the camera where to draw the
// preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "surface destroyed");
this.getHolder().removeCallback(this);
}
public void refreshCamera(Camera camera) {
setCamera(camera);
if (mCamera != null) {
Display display = ((Activity) mContext).getWindowManager().getDefaultDisplay();
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
e.printStackTrace();
}
Camera.Parameters parameters = mCamera.getParameters();
if (display.getRotation() == Surface.ROTATION_0) {
mCamera.setDisplayOrientation(90);
}
if (display.getRotation() == Surface.ROTATION_90) {
}
if (display.getRotation() == Surface.ROTATION_180) {
}
if (display.getRotation() == Surface.ROTATION_270) {
}
mCamera.setParameters(parameters);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
refreshCamera(mCamera);
}
public void setCamera(Camera camera) {
mCamera = camera;
}
}
Can you tell me what I am doing wrong?
This is because of less resolution of preview size
Set preview size hard code parameters.setPreviewSize(1920, 720);

Preview Camera HTC-One cuts image

I'm using a custom camera preview on my app, it works fine in almost all devices, for HTC-One I'm getting a bad cut, the original photo doesn't match what the preview shows on the top.
It only happens on this device, this is the code of my preview camera and the picture about what's going on.
Thanks in advance for any help someone can give me.
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private final String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private Context context;
private Camera.Size mPreviewSize;
private List<Camera.Size> mSupportedPreviewSizes;
public CameraPreview(Context context) {
super(context);
this.context = context;
mHolder = getHolder();
mHolder.addCallback(this);
}
public void setCamera(Camera camera) {
mCamera = camera;
if (mCamera != null) {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
for (Camera.Size str : mSupportedPreviewSizes) {
Log.e(TAG, str.width + "/" + str.height);
}
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
float ratio;
if (mPreviewSize.height >= mPreviewSize.width) {
ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
} else {
ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;
}
setMeasuredDimension(width, (int) (width * ratio));
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or reformatting changes here
// start preview with new settings
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void setFlash(String flashMode) {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(flashMode);
mCamera.setParameters(params);
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) h / w;
if (sizes == null) {
return null;
}
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
double ratio = (double) size.height / size.width;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - h);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - h);
}
}
}
return optimalSize;
}
public void switchCamera(Camera camera) {
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
camera.setDisplayOrientation(90);
} else if (display.getRotation() == Surface.ROTATION_270) {
camera.setDisplayOrientation(180);
}
setCamera(camera);
try {
camera.setPreviewDisplay(mHolder);
} catch (IOException exception) {
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
}
Camera preview size and picture size are two different parameters, which you can update through setPictureSize() and setPreviewSize() APIs. But if user doesn't change these sizes, it will use default values.
In this case you are updating the preview size by calculating optimum preview size based on some aspect ratio. But you are not updating picture size, so it will be using default picture size.
If picture size and preview size aspect ratios are different, definitely the captured image looks different from preview. So update the picture size also by calculating optimum picture size with same aspect ratio as preview size.

Categories

Resources