In my Application the camera preview is working properly in both in potrait and in landscape mode .No crashes are occuring.but the users are complainting that the crashes are occuring when they are using the same. what is the problem with this? please anyone help me to solve this issue
Make sure you are requesting a supported camera preview resolution.
See Camera.Parameters.getSupportedPreviewSizes for details on how to query for supported resolutions and request a supported resolution with Camera.Parameters.setPreviewSize.
Maybe you have to disable restarting camera on rotation by fixing layout in your activity, like this:
public void onCreate(Bundle savedInstanceState) {
...
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
The problem is the device is unable to set preview parameters.
You can use following code for setting preview parameters which will work in any device.
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (isPreviewRunning) {
camera.stopPreview();
}
try{
Camera.Parameters p = camera.getParameters();
if(p!=null){
List<Size> sizes = p.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
p.setPreviewSize(optimalSize.width, optimalSize.height);
camera.setParameters(p);
camera.setPreviewDisplay(holder);;
camera.startPreview();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
isPreviewRunning = true;
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
// TODO Auto-generated method stub
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;
// Try to find an size match aspect ratio and size
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);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
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;
}
try this.
Related
I'm using code inside this book "Pro Android Media
Developing Graphics, Music, Video, and Rich Media Apps for Smartphones and Tablets", and i have problem with preview of camera
and I used camera API in my app
I face some problem :
1) The display appear in the case of stretched, in the case of the lowest link shows the difference between the camera original phone and custom camera
here video for my problem i face
OR here video for my problem i face
The following code which I found somewhere helped me.
You essentially have to scale the preview in accordance with your screen size and for that this method should suffice,
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;
}
Now you are to Override the onMeasure in your preview Activity which I presume is extending the SurfaceView like this,
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if(mCamera != null) {
List<Camera.Size> mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
if (mSupportedPreviewSizes != null) {
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
}
and finally start the preview with the tuned PreviewSize calculated in onMeasure like this,
// start preview with new settings
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
isSafeToTakePicture = true;
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
I'm trying to use a SurfaceView to preview the camera in portrait mode. I'm initializing the camera correctly, and everything is working fine.
However, my SurfaceView has a fixed size, something like this:
<SurfaceView android:id="#+id/surface_view"
android:layout_width="match_parent"
android:layout_height="250dp" />
and I can't get it to preview with the correct ratio, the preview is always stretched.
I'm calculating the preview camera resolution with the following method:
private Point findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution, Rect surfaceFrame) {
// Sort by size, descending
List<Camera.Size> supportedPreviewSizes = new ArrayList<Camera.Size>(parameters.getSupportedPreviewSizes());
Collections.sort(supportedPreviewSizes, new Comparator<Camera.Size>() {
#Override
public int compare(Camera.Size a, Camera.Size b) {
int aPixels = a.height * a.width;
int bPixels = b.height * b.width;
if (bPixels < aPixels) {
return -1;
}
if (bPixels > aPixels) {
return 1;
}
return 0;
}
});
int w;
int h;
if(surfaceFrame == null) {
w = screenResolution.x;
h = screenResolution.y;
} else {
w = surfaceFrame.width();
h = surfaceFrame.height();
}
Log.i(TAG, "Surface resolution is " + new Point(w, h));
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (supportedPreviewSizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : supportedPreviewSizes) {
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 : supportedPreviewSizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
Point p = new Point(optimalSize.width, optimalSize.height);
Log.i(TAG, "Camera resolution is "+ p.toString());
return p;}
Is there a way to show the camera preview with the correct aspect ratio without modifying the size of the SurfaceView?
Thanks in advance
We implemented the custom camera functionality in my app. This was working fine in all the devices like nexus4,5,samsung s3,s4 etc except in Samsung galaxy S4 mini. The issue is image was stretching in front camera only but it's working good in back camera of that device.
For Samsung galaxy s4 mini, we are getting the screen size is 540X960 and we got supported preview size is 1280x720. The aspect ratio also same but we are facing image stretching issue. I was tried a lot but i am unable to solve this issue especially in front camera of samsung galaxy s4 mini. Please can anyone help me.
Code
int currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
Camera camera = Camera.open(currentCameraId);
try {
camera.setPreviewDisplay(surfaceHolder);
Camera.Parameters parameters = camera.getParameters();
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.set("orientation", "portrait");
camera.setDisplayOrientation(90);
parameters.setRotation(270);
Display display = getWindowManager().getDefaultDisplay();
int widthd = display.getWidth(); // deprecated
int heightd = display.getHeight();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
Camera.Size mPreviewSize = getOptimalPreviewSize(previewSizes, widthd, heightd);
Camera.Size mpicSize = getOptimalPreviewSize(pictureSizes, widthd, heightd);
parameters.setPreviewSize(mPreviewSize.width,mPreviewSize.height);
parameters.setPictureSize(mpicSize.width,mpicSize.height);
camera.setParameters(parameters);
} catch (IOException exception) {
camera.release();
}
camera.startPreview();
Please refer the following code for computing the optimal size.
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;
}
I am developing a custom camera app and I am facing the problem with setting the preview size for the camera. The problem is that the camera preview does not persist the aspect ration so the preview looks stretched to the sides.
The code I use to calculate the best size:
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 1;
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;
Log.d("Test", "Ration: " + Math.abs(ratio - targetRatio));
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) {
Log.d("Test", "MATCFH!");
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
I have been struggling with this for a day now and cannot find an optimal solution. Any suggestions will be greatly appreciated!
You are right, changing camera preview size may not preserve aspect ratio. To keep the preview display look nice, you should resize the preview surfaceView accordingly.
I have an android project that works fine on my DroidX but doesn't work on the Galaxy tablet. I get a log message saying camera type 1200x728 not supported. I am not setting the camera resolution anywhere, and i believed it is just grabbing the default settings from the device. Why it's crashing when i try to load it on a Galaxy Tab?
From my main activity i load my camera class like so:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// requesting to turn the title OFF
//requestWindowFeature(Window.FEATURE_NO_TITLE);
// making it full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//Set Screen Orientation
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
try{
//Create Intance of Camera
camPreview = new CamLayer(this.getApplicationContext());
//Create Instance of OpenGL
glView = new GLLayer(this);
//FrameLayOut for holding everything
FrameLayout frame = new FrameLayout(this);
// set as main view
setContentView(frame);
// add Camera to view
frame.addView(camPreview, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
frame.addView(glView);
} catch(Exception e){}
}
Then my camera class looks like this:
package com.eliddell.AR;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CamLayer extends SurfaceView {
Camera camera;
SurfaceHolder previewHolder;
public CamLayer(Context context)
{
super(context);
previewHolder = this.getHolder();
previewHolder.setType
(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
previewHolder.addCallback(surfaceHolderListener);
}
SurfaceHolder.Callback surfaceHolderListener = new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
camera=Camera.open();
try {
camera.setPreviewDisplay(previewHolder);
}
catch (Throwable e){ }
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Parameters params = camera.getParameters();
params.setPreviewSize(width, height);
params.setPictureFormat(PixelFormat.JPEG);
camera.setParameters(params);
camera.startPreview();
}
public void surfaceDestroyed(SurfaceHolder arg0)
{
camera.stopPreview();
camera.release();
}
};
public void onResume() {
camera.startPreview();
}
public void onPause() {
// TODO Auto-generated method stub
camera.stopPreview();
}
}
I think there should be some problem with setting preview parameters. Try below.
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (isPreviewRunning) {
camera.stopPreview();
}
try{
Camera.Parameters p = camera.getParameters();
if(p!=null){
List<Size> sizes = p.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
p.setPreviewSize(optimalSize.width, optimalSize.height);
camera.setParameters(p);
camera.setPreviewDisplay(holder);;
camera.startPreview();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
isPreviewRunning = true;
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
// TODO Auto-generated method stub
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;
// Try to find an size match aspect ratio and size
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);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
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;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (isPreviewRunning) {
camera.stopPreview();
}
try{
Camera.Parameters p = camera.getParameters();
if(p!=null){
List<Size> sizes = p.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
p.setPreviewSize(optimalSize.width, optimalSize.height);
camera.setParameters(p);
camera.setPreviewDisplay(holder);;
camera.startPreview();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
isPreviewRunning = true;
}
private Size getOptimalPreviewSize(List sizes, int w, int h) {
// TODO Auto-generated method stub
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;
// Try to find an size match aspect ratio and size
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);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
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;
}
Put this code in your surfaceChanged(). getOptimalPreviewSize() is used to set preview parameters according to device resolution.