I'm building a custom camera application for Android. The Camera.Parameters API contains methods like setPreviewSize or setPictureSize, that are working well.
But I am trying to use setJpegQuality(int) parameter:
Camera cam = getCameraInstance();
if(cam == null){
setResult(INSTANCE_ERROR);
finish();
}
params = cam.getParameters();
params.setJpegQuality(jpegQuality);
cam.setParameters(params);
I am testing my application on 3 different devices : an HTC Desire Z, a Galaxy S2 and a Galaxy S4.
setJpegQuality is working on HTC (Android 2.2.1) and on Galaxy S2 (4.1.2), but fails on Galaxy S4 device (4.2.2).
So my question : Is this function deprecated ? Is there another way to set picture quality ? On the Developer documentation it doesnt seems to be a deprecated function so i am a little confused...
I also tried
params.set("jpeg-quality", jpegQuality);
But its the same :(
Thanks for the answers.
For S3 and S4, you can write device specific code to reduce the size of file.
If you search on google, Android dev team also mentioned that it all depends on the implementation by the manufacturer(https://code.google.com/p/android/issues/detail?id=8091). The implementation of the camera parameters and function totally depends on the hardware used I think.
I had used motion sensors for one of my apps. There also, I had to write device specific code, to get the required behaviour in the app.
I know its not what we expect as a developer, but i believe we, developers, can fix anything. :)
I use the CWAC-Camera library for my custom camera. I forked the main repository and added a jpegQuality parameter to the PictureTransaction:
https://github.com/cookbrite/cwac-camera/commit/65a0a2082194dfc8069f605f0191c43357bb0852
This ensures that the resulting picture is always compressed to the required quality.
One drawback with this approach is that it has to load and compress the full size image file in application code, whereas using setJpegQuality on the Camera.Parameters may be more optimized.
Sorry I didnt see answers finaly come :) I dont even use this not working parameters anymore
I found a solution to set the quality of my picture, when i save it as file :
FileOutputStream fos = new FileOutputStream(finalFilePath);
bmp.compress(Bitmap.CompressFormat.JPEG, jpegQuality, fos);
Hope it helps
Related
I have written a basic custom camera which I recently changed to use the flash (where available) on the device. Once I had made the change the code ran fine as before on my HTC One Mini 2, but no longer worked on my Galaxy S4. After stepping through I found my jpeg callback is never reached on the S4, instead the raw callback is run but with a null byte[] supplied.
I found this similar question:
S4 Flash Problem
Which seems to confirm there is an issue and solution on these devices but the solution has not been documented.
To re-iterate, the code works fine on the S4 so long as I don't turn on the flash with:
Camera.Parameters p = mCamera.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);//Or FLASH_MODE_ON
mCamera.setParameters(p);
Can anybody with experience on these devices provide the solution?
After a lot of trial and error over the last week I have stumbled upon two possible solutions to this problem, the first of which doesn't make any sense to me at all:
Force the zoom to be greater than x1. For some reason if I set the zoom to x1.2 etc. the camera works again as I would expect.
Ensure the aspect ratio of the selected picture size matches the native aspect ratio of the device. The S4 has a resolution of 1920x1080 so any picture size that matches this 16:9 ratio works with the flash on. This makes a bit more sense but why the flash makes the difference and why anything that isn't supported should be returned by getSupportedPictureSizes() I don't know (albeit they do seem to be without the flash.)
Currently I have chosen to use option 2 and am testing on my other devices.
Might also be worth mentioning that my next step on the S4 was to allow the user to turn the flash on/off/auto themselves but this required destroying and recreating the camera each time.
I was looking for a method to use the camera on android devices without a surfaceview or a preview. I found out that, it is impossible to take picture without that preview. However, I have found a tutorial which is actually working taking pictures without a preview. Here is the link: http://www.vogella.com/articles/AndroidCamera/article.html
After switching the camera in the code from front to back-facing the app didn't crashed but it gave me an error 100. So it is only working with the front cam at the moment.
I am using a Samsung Galaxy S3(4.1.2) and i will test it on a Galaxy S2 and a Galaxy S3 Mini.
Anyone a good explanation for this?
You cannot take a picture without starting preview.
While some Android devices are more flexible, and allow takePicture to be called without preview running, this is technically against the API specifications.
It won't work on a large number of devices, so please don't rely on it. That tutorial is wrong, and presumably tested only on one of the devices that allows this behavior.
If you don't want a visible preview, see this question for ways to do that in Android versions >= 3.0.
Actually the time interval of question and answer is large, but may help others.
You can try this library to take picture even from service:
https://github.com/kevalpatel2106/android-hidden-camera
It uses a feature to draw over other apps and create a fake surface. Hope it helps.
I'm trying to develop an app for Android, and I would need to get uncompressed pictures with a resolution as high as possible from the camera. I tried takePicture's rawCallback and postviewCallback, but they are not working.
Right now I'm trying with OpenCV (version 2.4) using VideoCapture, but I'm stuck in the default 960x720, which is poor for what I need; and my phone, a Samsung Galaxy S3, is able to provide, theoretically, up to 8Mpx (3,264×2,448 for pictures, and 1,920×1,080 for video, according to Wikipedia). VideoCapture.set(Highgui.CV_CAP_PROP_FRAME_WIDTH/HEIGHT, some number) makes the camera return a black image as far as I've found.
Is there any way to obtain a higher resolution, either through OpenCV or with the Android API, without compressing?
I'm really sorry if this has been asked before; I have been looking for days and I have found nothing.
Thank you for your time!
EDIT: Although it is not exactly what I was asking, I found that there is a way to do something very similar: if you set an OnPreviewCallback for the Camera, using setPreviewCallback, you do get the raw picture data from the camera (at least in the S3 I'm working with). I leave it here in case somebody finds it useful in the future.
EDIT: A partial solution is explained in an answer below. To sum up,
vc.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, desiredFrameWidth);
vc.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, desiredFrameHeight);
works under some conditions; please see below for further detail.
You have to get supported camera preview resoultions by calling getSupportedPreviewSizes.
After this you can set any resolution with method setPreviewSize. And don't forget to setParameters in the end. Actally many OpenCV Android examples contain this information (look at sample3).
In case anybody ever finds this useful, I found a (partial) solution: If your VideoCapture variable is called vc, this should work:
vc.set(Highgui.CV_CAP_PROP_FRAME_WIDTH, desiredFrameWidth);
vc.set(Highgui.CV_CAP_PROP_FRAME_HEIGHT, desiredFrameHeight);
Mind that the combination of width and height must be one of the supported picture formats for your camera, otherwise it will just get a black image. You can get those through Camera.Parameters.getSupportedPictureSizes().
However, setting a high resolution appears to exceed the YUV conversion buffer's capacity, so I'm still struggling with that. I'm going to make a new separate question for that, to keep everything clearer: new thread
setPreviewSize does not set picture resolution. setPictureSize does.
I'm working on an Android app that shows a camera preview. Ideally I'd like the app to work in portrait mode, which means I need to deal with rotation of the camera preview image.
I only need to support API level 8 (Android version 2.2) and up, so I can use Camera.setDisplayOrientation to set the orientation, and the API docs for that method include a setDisplayOrientation function that does what I want. The only problem is that it uses the API Level 9 Camera.CameraInfo to get the orientation of the camera with respect to the device (presumably to deal with landscape vs portrait devices).
So is it safe to assume that I can do setDisplayOrientation(90) for all level 8 devices and just use CameraInfo.orientation for newer devices?
I have tried the following on an HTC Evo Shift with a project set to API8 (worked great):
Configuration cfg = mContext.getResources().getConfiguration();
if (cfg.orientation == Configuration.ORIENTATION_PORTRAIT) {
mCamera.setDisplayOrientation(90);
}
As a follow up for anyone else finding this - I didn't find a definitive answer on this, so I did as I suggested above (setDisplayOrientation(90)) for 2.2 devices and released the app. It's had about 70,000 downloads and no reports of the camera display being wrongly rotated by 90 degrees, so it looks like this is a reasonable solution.
I'm posting the link to Android's developers help in the Camera matter:
http://developer.android.com/guide/topics/media/camera.html
About your question in specific, i took a look at the API and i guess, since the surfaceChanged method is called every time a change in surface is made and the equipment have only 2 position, you are probably right, since u implement the corrected methods in the surfaceChanged method. Try to implement it and if you can't get it to work post the problem and i'll try to help more.
I'm using this camera code to ask the camera to rotate the captured image data:
Camera.Parameters params = camera.getParameters();
params.set("rotation", 90);
camera.setParameters(params);
this seems to work on all phones, except the Droid. Has anyone else seen this? The image data is always landscape, however, the native camera app on the Droid produces portrait images ok.
I wonder if the Droid will only respect the new Camera.Parameters.setRotation() method, but this seems to only be available in API level 5?
setRotation also didn't seem to work for me on Nexus One, but I did get image rotation to work by following the example of the android Camera app itself.
The source code is available here:
https://android.googlesource.com/platform/packages/apps/Camera
Start with the Camera.java, but you'll also be looking at ImageManager.java, Util.java, and other files.
The basic idea is, you listen for orientation changes and capture what the orientation is at the time you snapped the picture. Then, when you get the picture bytes in the callback, you manipulate the bitmap, doing a rotation on the bitmap. Then convert the rotated bitmap back to jpeg. When you are done, you'll have had to copy a shocking amount of code from the camera app just for this rotation.
The rotation may just be stored in the jpeg exif header as explained in the setRotation document. On Droid that is actually the case. You can use jpeg header reading tools like jhead to verify this. You can also use the ExifInterface API to read the orientation tag in your program.
The Droid runs Android 2.0 (well, now 2.0.1) which are API levels 5 and 6, respectively.
So it's quite possible that the Droid only respects the (more sensible) 2.0+ API for rotation.
However, I guess your concern is compatibility across a range of device types and OS versions, so I imagine you would have to invoke the 2.0+ API via reflection after detecting the OS version (using android.os.Build.VERSION_CODES).