I'm trying to use camera features as part of my application and I'm stuck on camera preview step.
I want to understand why the preview image remains dark if there are no bright light.
Here is what params I set before start previewing:
mParameters = mCamera.getParameters();
List<Camera.Size> mSupportedPreviewSizes = mParameters.getSupportedPreviewSizes();
Camera.Size optimalSize = CameraHelper.getOptimalPreviewSize(mSupportedPreviewSizes, DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT);
// Use the same size for recording profile.
mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
mProfile.videoFrameWidth = optimalSize.width;
mProfile.videoFrameHeight = optimalSize.height;
// likewise for the camera object itself.
mParameters.setPreviewSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);
// Set correct video width and height according to screen rotation
transformMatrixHelper.setVideoDimensions(optimalSize.width, optimalSize.height);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
transformMatrixHelper.setVideoDimensions(optimalSize.height, optimalSize.width);
}
transformMatrixHelper.clearInitTextureDimension();
mParameters.setPreviewFpsRange(MAX_FPS, MAX_FPS);
mParameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
// Auto-focus
if (mParameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
// Auto-exposure
if (mParameters.isAutoExposureLockSupported()) {
mParameters.setAutoExposureLock(false);
}
mCamera.setParameters(mParameters);
I'm not calling any camera.autoFocus(callback) method after preview stared.
I will be very grateful if someone help me, thanks.
Related
To reduce the capacity of the picture, I used setPictureSize as shown below to size the picture, but after doing camera.takePicture() there was nothing else.
What can I do to reduce the size of the pictures taken from the camera?
Camera camera = getCameraInstance();
final Camera.Parameters parameters = camera.getParameters();
parameters.setPictureSize(640,320);
You also have set the parameters after you have set the picture size.
And you can also reduce jpeg quality if you want to reduce the image size even more.
this is how I did it
mCamera = getCameraInstance();
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPictureSizes();
Camera.Size size = sizes.get(0);
for(int i=0;i<sizes.size();i++)
{
if(sizes.get(i).width >= 800 && sizes.get(i).width<=1000){
size = sizes.get(i);
}
}
params.setJpegQuality(30);
params.setPictureSize(size.width,size.height);
mCamera.setParameters(params);
I have a problem for my application, specifically, when I want to take a picture (from android Camera API) and send it to my server, I got some strange pictures like following example:
which contain many noise points and actually the size/resolution are very small (176*144 pixels). And this is my original code for surfaceChanged:
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// start preview with new settings
try {
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.e(LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
mCamera.startPreview();
}
And I tried to ask some classmates for this issue, they don't know but one of them give the following code:
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
try {
// camera.stopPreview();
// Camera.Parameters mParameters = camera.getParameters();
Camera.Parameters parameters = mCamera.getParameters();
Camera.Size optiSize = getBestPreviewSize(720, 720);
if (optiSize != null) {
parameters.setPreviewSize(optiSize.width, optiSize.height);
parameters.setPictureSize(optiSize.width, optiSize.height);
}
parameters.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
mCamera.setParameters(parameters);
// mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
// camera.setParameters(mParameters); // apply the changes
} catch (Exception e) {
// older phone - doesn't support these calls
}
mCamera.startPreview();
}
private Camera.Size getBestPreviewSize(int width, int height) {
List<Camera.Size> sizes = mCamera.getParameters()
.getSupportedPreviewSizes();
if (sizes == null)
return null;
Camera.Size optimalSize = null;
int tmpSize;
int minWidthDiff = 1000;
for (Camera.Size size : sizes) {
if (size.width > size.height)
tmpSize = size.height;
else
tmpSize = size.width;
if (Math.abs(tmpSize - width) < minWidthDiff) {
minWidthDiff = Math.abs(tmpSize - width);
optimalSize = size;
}
}
return optimalSize;
}
And this one works pretty well, it can store the original picture with the full resolution. Although I modify a little bit of my other codes to make the new codes compatible with my system, (add AutoFocus, for example). But I think the problem occurs because the method surfaceChanged because if I take image only with Autofocus, it still not work.
Therefore my question is: why this method will influence the quality of my image. I thought this method is only called when we "change" the surface, something like rotate the screen. But apparently it do something more than that?
Can anybody give me some help? Or some posts to explain this fact? Thank you very much in advance.
This method is called when the surface is changed, e.g. it is resized. It is common to adjust some of the camera's parameters to better fit the new configurations (such as setting an appropriate preview size).
What you are doing in the first code is you're getting the camera's Camera.Parameters, set a key-value pair (by the way, the documentation does not mention any parameter with the key "orientation" - it probably has no meaning). What you forgot to do is to apply the new parameters to the camera using Camera.setParameters(). Then again, without actually setting any valid parameters, this would have no effect.
This leads to the low-quality picture issue. You should use the Camera.Parameters object to set a desired preview and picture size. In the second block of code, this is done inside getBestPreviewSize(). A list of available preview sizes is got and the most fitting one is chosen based on the preview's size. It might be helpful to set a satisfactory picture size, too.
The thing is, different devices have different set of supported values for the parameters. If you want to provide a consistent functionality, you should check the supported values using Camera.Parameters.getSupported* methods and set them accordingly.
For my application I am using android native camera and previewing the image using surface view. in my case everything is working except the camera orientation. When I open the camera by setting screenOrientation="landscape on manifest file I am getting the preview without any problem in landscape mode. But I need to take image in portrait mode, for this I changed my manifest like android:screenOrientation="portrait" and change my code like mCamera.setDisplayOrientation(90), params.set("orientation", "landscape"),params.set("rotation", 90), but still I am getting 90 degree rotated image.
And my code is
public void setupCamera(int width, int height) {
Log.i(TAG, "setupCamera");
synchronized (this) {
if (mCamera != null) {
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
List<Camera.Size> imgsize=params.getSupportedPictureSizes();
mFrameWidth = width;
mFrameHeight = height;
// mCamera.setDisplayOrientation(90);
params.set("orientation", "landscape");
params.set("rotation", 90);
// selecting optimal camera preview size
{
int minDiff = Integer.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - height) < minDiff) {
mFrameWidth = size.width;
mFrameHeight = size.height;
minDiff = Math.abs(size.height - height);
}
}
}
params.setPreviewSize(getFrameWidth(), getFrameHeight());
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
{
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
mCamera.startPreview();
}
}
}
I am using Micromax A 52 model...
Any one please help.....
If your application runs on v2.2 or above you can rotate camera orientation to portrait using camera.setDisplayOrientation(90).
For others:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//After opening camera - call via reflection
Method rotateMethod = android.hardware.Camera.class.getMethod("setDisplayOrientation", int.class);
rotateMethod.invoke(mCamera, 90);
for more details please refer this link and this Hope this will be helpful
I have built a custom Camera App and I am trying to change the resoloution of the image that is took. I have read around that this could depend on the phone or version of Android?
I know they are set using the setParameters but just dont know how to set the actuall resoloution to work on all phones. I am wanting it to be kind of small as my app force closes otherwise. When I use a test picture at 640x348 this works so around that size/resoloution would be perfect.
It may be easier to use setPictureSize?
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
try {
Camera.Parameters parameters = camera.getParameters();
if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
parameters.set("orientation", "portrait");
camera.setDisplayOrientation(90);
// Uncomment for Android 2.0 and above
parameters.setRotation(90);
} else {
parameters.set("orientation", "landscape");
camera.setDisplayOrientation(0);
// Uncomment for Android 2.0 and above
parameters.setRotation(0);
}
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
} catch (IOException exception) {
camera.release();
}
camera.startPreview();
}
There is no setResolution(), only setPictureSize(). Use getSupportedPictureSizes() on Camera.Parameters to find the size you want, or use that information to populate a ListView or Spinner or something for the user to choose the desired size. Here is a sample project recently updated to use getSupportedPictureSizes() to find the smallest supported resolution and use that.
It's too easy to capture image with high quality, here you can set your own resolution:
mCamera = Camera.open();
Camera.Parameters params = mCamera.getParameters();
// Check what resolutions are supported by your camera
List<Size> sizes = params.getSupportedPictureSizes();
// Iterate through all available resolutions and choose one.
// The chosen resolution will be stored in mSize.
Size mSize;
for (Size size : sizes) {
Log.i(TAG, "Available resolution: "+size.width+" "+size.height);
mSize = size;
}
}
Log.i(TAG, "Chosen resolution: "+mSize.width+" "+mSize.height);
params.setPictureSize(mSize.width, mSize.height);
mCamera.setParameters(params);
Hope this will help you all.
I copied the code from the answer here and I still am getting a RuntimeException: setParameters failed error on my nexus one. My manifest file has camera and wake_lock permissions. This works on the emulator, and on the droid I don't get the error but it does have a rotation problem.
You're most likely requsting an invalid preview size. If you check the results of adb logcat you'll probably see something like this:
E/QualcommCameraHardware(22732): Invalid preview size requested: 480x724
The solution is to request the closest available preview size to the one you'd like; you can get a list of available preview sizes by calling getSupportedPreviewSizes in the Camera.Parameters object returned by Camera.getParameters.
I corrected this by doing what Roman said, with the code:
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
Camera.Size cs = sizes.get(0);
parameters.setPreviewSize(cs.width, cs.height);
camera.setParameters(parameters);
For what it's worth, the source of my issue ended up being that I was trying to call parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); without first verifying that flash modes were supported by checking that parameters.getFlashMode() != null.
There's more than one cause for this poorly documented exception, so check all of your parameters and not just that you're using a supportedPreviewSize.
None of the above solved this for me. Adding this code before setting the parameters did though.
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
//now set your parameters
For me this would happen after taking a photo and the preview would freeze, until I updated my call for parameters to be the following. It is always important with this error to make sure you check all of the parameters that the camera is asking to set to make sure that every parameter you are asking the camera to set itself to is possible for the camera.
Camera.Parameters parameters = myCamera.getParameters();
With the preview size:
if (myCamera.getParameters().getSupportedPreviewSizes() != null){
Camera.Size previewSize = getOptimalPreviewSize(myCamera.getParameters().getSupportedPreviewSizes(), width, height);;
parameters.setPreviewSize(previewSize.width, previewSize.height);
}
With the flash/focus modes:
if(parameters.getSupportedFocusModes() != null && parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)){
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
if (parameters.getSupportedFlashModes() != null && parameters.getSupportedFlashModes().contains(Camera.Parameters.FLASH_MODE_AUTO)){
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
}
myCamera.setParameters(parameters);
etc. All of this wrapped in a nice try{}catch(){} works great. Good luck.
Here is the getOptimalPreview Size from this great tutorial:
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height)
{
// Source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails
Camera.Size optimalSize = null;
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) height / width;
// Try to find a size match which suits the whole screen minus the menu on the left.
for (Camera.Size size : sizes){
if (size.height != width) continue;
double ratio = (double) size.width / size.height;
if (ratio <= targetRatio + ASPECT_TOLERANCE && ratio >= targetRatio - ASPECT_TOLERANCE){
optimalSize = size;
}
}
// If we cannot find the one that matches the aspect ratio, ignore the requirement.
if (optimalSize == null) {
// TODO : Backup in case we don't get a size.
}
return optimalSize;
}
the solution from Sam is correct but the output image is still zoomed a little bit on several tablet devices. One of the best practices that I found on Internet, we should set in Camera host so that the properties will be re-used each time the camera is resumed. Here is implemented method in CameraHost:
#Override
public Parameters adjustPreviewParameters(Parameters parameters) {
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
Camera.Size cs = sizes.get(0);
parameters.setPreviewSize(cs.width, cs.height);
return super.adjustPreviewParameters(parameters);
}
Some open source camera project like opencamera always use try-catch to call Camera.setParameters:
private void setCameraParameters(Camera.Parameters parameters) {
if( MyDebug.LOG )
Log.d(TAG, "setCameraParameters");
try {
camera.setParameters(parameters);
if( MyDebug.LOG )
Log.d(TAG, "done");
} catch (RuntimeException e) {
// just in case something has gone wrong
if( MyDebug.LOG )
Log.d(TAG, "failed to set parameters");
e.printStackTrace();
count_camera_parameters_exception++;
}
}
in addition,always get the latest getParameters before you call setParameters like this:
void setRotation(int rotation) {
Camera.Parameters parameters = this.getParameters();
parameters.setRotation(rotation);
setCameraParameters(parameters);
}