3

I'm writing an Android application that saves a JPEG snapshot from the camera when the user clicks a button. Unfortunately, when I look at the JPEG file my code is saving looks corrupted. It appears to be caused by my call to parameters.setPreviewSize (see code snippet below) - if I remove that then the image saves fine; however without it I can't set the preview size and setDisplayOrientation also appears to have no effect without it.

My app is targeting API Level 8 (Android 2.2), and I'm debugging on an HTC Desire HD. Not quite sure what I'm doing wrong here... any help would be very much appreciated!

Cheers, Scottie

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = mCamera.getParameters();        
    Camera.Size size = getBestPreviewSize(w,h);

    // This next call is required in order for preview size to be set and
    // setDisplayOrientation to take effect...
    // Unfortunately it's also causing JPEG to be created wrong
    parameters.setPreviewSize(size.width, size.height);

    parameters.setPictureFormat(ImageFormat.JPEG);
    mCamera.setParameters(parameters);
    mCamera.setDisplayOrientation(90);

    mCamera.startPreview();

}

// This is the snapshot button event handler
public void onSnapshotButtonClick(View target) {
    //void android.hardware.Camera.takePicture(ShutterCallback shutter, 
    //                              PictureCallback raw, PictureCallback jpeg)
    mPreview.mCamera.takePicture(null, null, mPictureCallback);
}


// This saves the camera snapshot as a JPEG file on the SD card
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
    public void onPictureTaken(byte[] imageData, Camera c) {

        if (imageData != null) {
            FileOutputStream outStream = null;
            try {
                String myJpgPath = String.format(
                        "/sdcard/%d.jpg", System.currentTimeMillis());

                outStream = new FileOutputStream(myJpgPath);
                outStream.write(imageData);
                outStream.close();
                Log.d("TestApp", "onPictureTaken - wrote bytes: "
                        + imageData.length);

                c.startPreview();
                Toast.makeText(getApplicationContext(), String.format("%s written", myJpgPath), Toast.LENGTH_SHORT).show();

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
            }
        }
    }
};
Scottie
  • 545
  • 4
  • 14
  • 1
    Happens for me too, but only for the HTC Desire HD. The jpeg saves fine on the Samsung Galaxy S and the emulator. – jA_cOp May 14 '11 at 22:11
  • @jA_cOp - Thanks for that, at least I know it's not me that's wrong! The camera app in the Android source code works ok, so I'm going to have a study of that and spot the difference. – Scottie May 16 '11 at 10:14
  • Have you solved the problem? i've bumped into the same problem, only with HTC Desire HD – Ikky Jun 07 '11 at 13:15
  • @Ikky - I've not had a chance to come back to this project yet, will update here when I do – Scottie Jun 07 '11 at 22:27
  • If setPreviewSize not nessecary, try to remove the parameters.setPreviewSize, that worked for me. – Ikky Jun 15 '11 at 07:21

2 Answers2

4

Another workaround is to match the aspect ratio between preview and picture sizes (i.e. setPreviewSize(w1,h1); setPictureSize(w2,h2) with w1/h1 ~ w2/h2 (small differences seem to be ok)). E.g. for Desire HD S w1=800,h1=480, w2=2592,h2=1552 works as well as w1=960,h1=720,h2=2592,h2=1952 (if you don't mind distorted images ;-)

user995639
  • 41
  • 1
  • I can confirm this on my HTC Desire S device. By the way, on the native camera app on this device, you can define in the settings both the aspect ratio (4:3 or 5:3) and the resolution. The list of available resolutions depends on the aspect ratio because it seems they need to match. – guillaume-tgl Apr 25 '14 at 08:30
2

I assume that you are using a common implementation of the getBestPreviewSize(w,h) method that is floating about, where you cycle through the different getSupportedPreviewSizes() to find the best match. Although I am not certain as to why it causes the images to be distorted, I have found that calling the parameters.setPreviewSize(size.width, size.height) method with the output of the getBestPreviewSize method is what is causing the problem on the HTC Desire. I have also verified that by commenting it out, the distorted image issue goes away.

BluJ IT
  • 369
  • 3
  • 12
  • I have a similar issue with my app and removed the setPreviewSize, some users (Desire S) still got the issue. So this is not something only related to this portion of code. I have seen a lot of post around this and really like someone could explain the very details of why the picture appears like this – plus- Jul 08 '11 at 13:28
  • Great response ! I've been looking for exactly that for the last few hours while struggling with the distorted images I get from onFramePreview when converting to YUV. Thanks a lot ! – Muzikant Mar 10 '12 at 19:54