I tried several things to try to get the camera preview to show up in portrait on a SurfaceView. Nothing worked. I am testing on a Droid that has 2.0.1. I tried:
1) forcing the layout to be portrait by: this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
2) using
Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
parameters.setRotation(90);
camera.setParameters(parameters);
Is there something else I can try? If this a bug in Android or the phone how can I make sure that this is the case so that I have proof to inform the client?
Thanks,
Prasanna
As of API lvl 8, this is available:
public final void setDisplayOrientation (int degrees)
i.e. with portait in the manifest:
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
i have a working solution for portrait mode working in 2.1 (tested on Desire) maybe less.
Activity screen orientation is set to portrait.
(android:screenOrientation="portrait")
the camera parameters:
Camera.Parameters p = mCamera.getParameters();
p.set("jpeg-quality", 100);
p.set("orientation", "landscape");
p.set("rotation", 90);
p.setPictureFormat(PixelFormat.JPEG);
p.setPreviewSize(h, w);// here w h are reversed
mCamera.setParameters(p);
and the image will be portrait.
SurfaceHolder you use for camera must be at a size compatible with phone preview size
usualy screen resolution.
Funny on Desire 2.2 is not working...
Here is the fix:
At surfaceCreated(..) or when you have this line
camera = Camera.open();
add
camera.setDisplayOrientation(90);//only 2.2>
Camera.Parameters p = camera.getParameters();
p.set("jpeg-quality", 100);
p.setRotation(90);
p.setPictureFormat(PixelFormat.JPEG);
p.setPreviewSize(h, w);
camera.setParameters(p);
You can try this (good for 2.2 or below). Here I rotate the image before saving it to sd card. But it is only for portrait mode. If you had to make it for both mode then you should check camera orientation and put some check before capturing image.
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
imageFilePath = getFilename();
InputStream is = new ByteArrayInputStream(data);
Bitmap bmp = BitmapFactory.decodeStream(is);
// Getting width & height of the given image.
if (bmp != null){
int w = bmp.getWidth();
int h = bmp.getHeight();
// Setting post rotate to 90
Matrix mtx = new Matrix();
mtx.postRotate(90);
// Rotating Bitmap
Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, w, h, mtx, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
rotatedBMP.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
outStream = new FileOutputStream
(String.format(imageFilePath,System.currentTimeMillis()));
outStream.write(byteArray);
outStream.close();
} else {
outStream = new FileOutputStream
(String.format(imageFilePath,System.currentTimeMillis()));
outStream.write(data);
outStream.close();
}
preview.camera.startPreview();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
};
There's no way to do this on many current devices, including the G1 and Droid. Take a look at the relevant bug report here:
http://code.google.com/p/android/issues/detail?id=1193
Also see a comment from one of the Android engineers (Dave) here:
http://groups.google.com/group/android-developers/browse_thread/thread/24dfa452ffc0e049
The link Roman gave of the issue thread has a workable solution that I'm using now.
Find it here:
http://code.google.com/p/android/issues/detail?id=1193#c26
There is no need you have to set any parameters for the orientation until you need to do that explicitly. By Default, it supports this facility. In my case, i have a Activity and above that activity i have a camera view, so i didn't set any orientation for the camera properties, instead for the activity i set the orientation as portrait in the Manifest file. now the app looks and works good. Might be helpful for some one..
Thanks.
Related
What is the image format in the Preview Screen when Camera is enable?
Is it RGB? Or YUV? Or others?
So when I take a photo, I basically ask Andriod to convert whatever on screen from YUV format to JPEG?
And when I record a video, Android convert that format to mp4?
It is NV21. See the online document.
To save the data to JPEG, you can do this:
YuvImage im = new YuvImage(preview_data, ImageFormat.NV21, preview_width, preview_height, null);
int quality = 90;
Rect rect = new Rect(0, 0, preview_width, preview_height);
FileOutputStream output = new FileOutputStream("/sdcard/test.jpg");
im.compressToJpeg(rect, quality, output);
output.flush();
output.close();
There is a alternate way, how i am doing the same, may help you:
For taking picture:
init camera and set onPictureTaken method.
Camera camera = Camera.open();
if(camera != null)
{
camera.takePicture(null, null, jpeg);
}
now implement Camera.PictureCallback with name "jpeg", in which you will get captured image in JPEG format
set desired image format in onSurfaceChanged method
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
if (holder != null && camera != null)
{
camera.stopPreview();
Camera.Parameters parameters = camera.getParameters();
parameters.setPictureFormat(PixelFormat.JPEG);
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
camera.startPreview();
}
}
For Recording video
init camera.
Camera camera = Camera.open();
init Media recorder and set desired video format on recorder
if ( camera != null)
{
try{
camera.stopPreview();
MediaRecorder recorder = new MediaRecorder();
recorder.setCamera(camera);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.prepare();
}
Source: for Take picture, for Record video
Is there any way to acquire the preview frame directly in portrait inside onPreviewFrame method?
I've tried:
camera.setDisplayOrientation(90);
but this seems to work only for the display. The doc reports:
Set the clockwise rotation of preview display in degrees. This affects
the preview frames and the picture displayed after snapshot. This
method is useful for portrait mode applications.
This does not affect the order of byte array passed in onPreviewFrame(byte[], Camera), JPEG pictures, or recorded videos.
This method is not allowed to be called during preview.
I'm targetting API level >= 8, and I've a portrait locked app. I want to avoid manually rotating byte array of data passed as frame.
Many thanks in advance.
Try this it will work
public void takeSnapPhoto() {
camera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
int format = parameters.getPreviewFormat();
//YUV formats require more conversion
if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
// Get the YuV image
YuvImage yuv_image = new YuvImage(data, format, w, h, null);
// Convert YuV to Jpeg
Rect rect = new Rect(0, 0, w, h);
ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
yuv_image.compressToJpeg(rect, 100, output_stream);
byte[] byt = output_stream.toByteArray();
FileOutputStream outStream = null;
try {
// Write to SD Card
File file = createFileInSDCard(FOLDER_PATH, "Image_"+System.currentTimeMillis()+".jpg");
//Uri uriSavedImage = Uri.fromFile(file);
outStream = new FileOutputStream(file);
outStream.write(byt);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
});}
On Android,
Anyone have any idea what trick snapchat pulls to get such high fps on their camera preview? I have tried various methods:
using a textureview instead of surface view
forcing hardware acceleration
using lower resolutions
using different preview formats (YV12 , NV21 drops frames)
changing focusing mode
None have left me anywhere close to the constant 30fps or maybe even above that snapchat seems to get. I can just about get to the same fps as the stock google camera app, but this isn't great, and mine displays at much lower resolution.
EDIT:
The method used is the same as that used by the official android video recording app. The preview there is of the same image quality and is locked to 30fps.
try this it works
public void takeSnapPhoto() {
camera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
int format = parameters.getPreviewFormat();
//YUV formats require more conversion
if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
// Get the YuV image
YuvImage yuv_image = new YuvImage(data, format, w, h, null);
// Convert YuV to Jpeg
Rect rect = new Rect(0, 0, w, h);
ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
yuv_image.compressToJpeg(rect, 100, output_stream);
byte[] byt = output_stream.toByteArray();
FileOutputStream outStream = null;
try {
// Write to SD Card
File file = createFileInSDCard(FOLDER_PATH, "Image_"+System.currentTimeMillis()+".jpg");
//Uri uriSavedImage = Uri.fromFile(file);
outStream = new FileOutputStream(file);
outStream.write(byt);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
});}
I believed they used the android NDK. You can find more information in android developer.
Using pure C/C++ is faster than JAVA code in performance critical tasks such as image and video processing.
You can also try to improve the performance by compiling the application with another compiler, like the Intel compiler.
I tried several things to try to get the camera preview to show up in portrait on a SurfaceView. Nothing worked. I am testing on a Droid that has 2.0.1. I tried:
1) forcing the layout to be portrait by: this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
2) using
Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
parameters.setRotation(90);
camera.setParameters(parameters);
Is there something else I can try? If this a bug in Android or the phone how can I make sure that this is the case so that I have proof to inform the client?
Thanks,
Prasanna
As of API lvl 8, this is available:
public final void setDisplayOrientation (int degrees)
i.e. with portait in the manifest:
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
i have a working solution for portrait mode working in 2.1 (tested on Desire) maybe less.
Activity screen orientation is set to portrait.
(android:screenOrientation="portrait")
the camera parameters:
Camera.Parameters p = mCamera.getParameters();
p.set("jpeg-quality", 100);
p.set("orientation", "landscape");
p.set("rotation", 90);
p.setPictureFormat(PixelFormat.JPEG);
p.setPreviewSize(h, w);// here w h are reversed
mCamera.setParameters(p);
and the image will be portrait.
SurfaceHolder you use for camera must be at a size compatible with phone preview size
usualy screen resolution.
Funny on Desire 2.2 is not working...
Here is the fix:
At surfaceCreated(..) or when you have this line
camera = Camera.open();
add
camera.setDisplayOrientation(90);//only 2.2>
Camera.Parameters p = camera.getParameters();
p.set("jpeg-quality", 100);
p.setRotation(90);
p.setPictureFormat(PixelFormat.JPEG);
p.setPreviewSize(h, w);
camera.setParameters(p);
You can try this (good for 2.2 or below). Here I rotate the image before saving it to sd card. But it is only for portrait mode. If you had to make it for both mode then you should check camera orientation and put some check before capturing image.
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
imageFilePath = getFilename();
InputStream is = new ByteArrayInputStream(data);
Bitmap bmp = BitmapFactory.decodeStream(is);
// Getting width & height of the given image.
if (bmp != null){
int w = bmp.getWidth();
int h = bmp.getHeight();
// Setting post rotate to 90
Matrix mtx = new Matrix();
mtx.postRotate(90);
// Rotating Bitmap
Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, w, h, mtx, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
rotatedBMP.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
outStream = new FileOutputStream
(String.format(imageFilePath,System.currentTimeMillis()));
outStream.write(byteArray);
outStream.close();
} else {
outStream = new FileOutputStream
(String.format(imageFilePath,System.currentTimeMillis()));
outStream.write(data);
outStream.close();
}
preview.camera.startPreview();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
};
There's no way to do this on many current devices, including the G1 and Droid. Take a look at the relevant bug report here:
http://code.google.com/p/android/issues/detail?id=1193
Also see a comment from one of the Android engineers (Dave) here:
http://groups.google.com/group/android-developers/browse_thread/thread/24dfa452ffc0e049
The link Roman gave of the issue thread has a workable solution that I'm using now.
Find it here:
http://code.google.com/p/android/issues/detail?id=1193#c26
There is no need you have to set any parameters for the orientation until you need to do that explicitly. By Default, it supports this facility. In my case, i have a Activity and above that activity i have a camera view, so i didn't set any orientation for the camera properties, instead for the activity i set the orientation as portrait in the Manifest file. now the app looks and works good. Might be helpful for some one..
Thanks.
The code below is executed as the jpeg picture callback after TakePicture is called. If I save data to disk, it is a 1280x960 jpeg. I've tried to change the picture size but that's not possible as no smaller size is supported. JPEG is the only available picture format.
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream out = null;
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap sbm = Bitmap.createScaledBitmap(bm, 640, 480, false);
data.Length is something like 500k as expected. After executing BitmapFactory.decodeByteArray(), bm has a height and width of -1 so it appears the operation is failing.
It's unclear to me if Bitmap can handle jpeg data. I would think not but I have seem some code examples that seem to indicate it is.
Does data need to be in bitmap format before decoding and scaling?
If so, how to do this?
Thanks!
On your surfaceCreated, you code set the camara's Picture Size, as shown the code below:
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try {
camera.setPreviewDisplay(holder);
Camera.Parameters p = camera.getParameters();
p.set("jpeg-quality", 70);
p.setPictureFormat(PixelFormat.JPEG);
p.setPictureSize(640, 480);
camera.setParameters(p);
} catch (IOException e) {
e.printStackTrace();
}
}