Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capture image without intent, Gives different output on different devices

My requirement is neither to display camera preview nor to use camera intent for image capture.

There for I find a way which is working for my first testing device (Galaxy tab 7").

My CaptureImage function is as below

private void CaptureImage() {
        int FrontCameraFound = getCameraID();
        if (FrontCameraFound != -1) {
            mCamera = Camera.open(FrontCameraFound);

            parameters = mCamera.getParameters();

            mCamera.setParameters(parameters);
            mCamera.startPreview();

            Camera.PictureCallback mCall = new Camera.PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera) {

                    bmp = BitmapFactory.decodeByteArray(data, 0, data.length);

                    // set bitmap tp image view just to check 
                    // if image capture proper, testing purpose
                    iv_image.setImageBitmap(bmp);

                    mCamera.stopPreview();
                    mCamera.release();
                    mCamera = null;
                }
            };
            mCamera.takePicture(null, null, mCall);
        }
    }

and getCameraID function as below

private int getCameraID() {
    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();

    for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); camIdx++) {
        Camera.getCameraInfo(camIdx, cameraInfo);
        // for capture image from back camera
        // If want to capture from front 
        // then change it to CAMERA_FACING_FRONT
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            try {
                return camIdx;
            } catch (RuntimeException e) {

            }
        }
    }
    return -1;
}

Now I am facing difficulty to run successfully above code on different devices.

  • Samsung Galaxy S+ (2.3.6) : Front camera always return green image but coding for Back camera working fine.
  • Samsung Galaxy Nexus (4.1) : coding doesn't work Neither for Front nor for Back camera & gives "takePicture" failed.
  • LG Optimus Net (2.3.4) : only back camera is there & working fine.
  • Samsung Galaxy Tab 7 " (2.3.3) : both camera working fine.
  • Motorola Xoom (3.1) : both camera working fine.

Logcat of Samsung Galaxy Nexus :

09-21 09:37:42.125: E/AndroidRuntime(4647): Caused by: java.lang.RuntimeException: takePicture failed
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.hardware.Camera.native_takePicture(Native Method)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.hardware.Camera.takePicture(Camera.java:1061)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.hardware.Camera.takePicture(Camera.java:1006)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at fortyonepost.com.pwop.TakePictureDemoActivity.CaptureImage(TakePictureDemoActivity.java:63)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at fortyonepost.com.pwop.TakePictureDemoActivity.onCreate(TakePictureDemoActivity.java:36)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.app.Activity.performCreate(Activity.java:5008)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
09-21 09:37:42.125: E/AndroidRuntime(4647):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)

It is not possible to check code for every devices , I just test my code on 5 devices and 2 device causes problem, so is there any standard way to fetch image from camera without intent & preview.

Please note that I include in manifest & set minimum sdk version to 9

Update : In 4.1 Nexus Galaxy takePicture Failed from Line number 1061 in Camera.java class, here is the class link which gives me information that native_takePicture(msgType); function in Camera.java did throw that

like image 226
rajpara Avatar asked Sep 21 '12 11:09

rajpara


People also ask

Why does an image captured using camera intent gets rotated on some devices on Android?

Answer: Most phone cameras are landscape, meaning if you take the photo in portrait, the resulting photos will be rotated 90 degrees. In this case, the camera software should populate the Exif data with the orientation that the photo should be viewed in.

How do you open camera through intent and display captured image?

This is done as follows: Intent camera_intent = new Intent(MediaStore. ACTION_IMAGE_CAPTURE); startActivityForResult(camera_intent, pic_id); Now use the onActivityResult() method to get the result, here is the captured image.

Which method of the camera class display the preview of the image captured?

SurfaceView. This class is used to present a live camera preview to the user. MediaRecorder.


3 Answers

Camera handling in android devices is major PITA - different devices ( and even android versions on same device) can and certainly will behave differently. Basically you are speaking with some demon process on device, and they are different from each other.

I do not have solution for all problems, but here are my findings so far

  • not all resolutions are working properly, even it they are advertised in camera parameters. You have to test them while setting up camera in case there are problems
  • preview data come to you via mmapped memory region
  • NV21 format is always supplied and shall be default, but I would query camera settings. When you open camera, it can have some settings from other application which used camera just before. ( it is said nowhere that camera will be reset to defaults when you open it )

I have developed some camera management stuff developed for JavaOCR Project, and it kind of works on most devices. Feel free to use this as inspiration:

http://sourceforge.net/p/javaocr/code/240/tree/trunk/demos/camera-utils/src/main/java/net/sf/javaocr/demos/android/utils/camera/CameraManager.java

like image 180
Konstantin Pribluda Avatar answered Oct 25 '22 03:10

Konstantin Pribluda


After several search, i found that preview of camera is necessary and i wonder how my code works well in some devices even it is faulty.

Any ways solution is that,

We require camera preview hold on surface view and we can hide that surface view behind any other view, I take surface view in framelayout(i know it is deprecated) and above it i take image view, for surface view i just take 80*80 dp surface view because small surface view like 30*30 dp didn't work and again through error.

like image 21
rajpara Avatar answered Oct 25 '22 05:10

rajpara


You need to use the Camera.setOneShotPreviewCallback method and then process the image

Try using YuvImage and compress it before passing it to the bitmapfactory, like so:

YuvImage yuvimage = new YuvImage(byteArr, ImageFormat.NV21, width, height, null);
    Rect rect = new Rect(0, 0, width, height);
    ByteArrayOutputStream outstr = new ByteArrayOutputStream();
    yuvimage.compressToJpeg(rect, 100, outstr);
    Bitmap bm = BitmapFactory.decodeByteArray(outstr.toByteArray(), 0, outstr.size());

EDIT:

You must use a surface view but the surface view can be hidden below another view so it's not visible on screen but still exists and active.

like image 25
tomas Avatar answered Oct 25 '22 04:10

tomas