简体   繁体   English

Android Camera为一些用户提供了多行的错误图片

[英]Android Camera takes multi lined bugged picture for some users

1) Some users of my app are taking some bugged pictures that look like that: 1)我的应用程序的一些用户正在拍摄一些看起来像这样的错误图片:

http://lh3.ggpht.com/i_VKS_Z1Ike5V8gEySiscQRRNkLwZMvv1a6u9diJrkWWGgYXUS-kqqxvAylhLIEJ1gs3MMZSEYIJJ4hX http://lh3.ggpht.com/i_VKS_Z1Ike5V8gEySiscQRRNkLwZMvv1a6u9diJrkWWGgYXUS-kqqxvAylhLIEJ1gs3MMZSEYIJJ4hX

The only thing I do is standard bitmap API in jpegCallback: 我唯一做的是jpegCallback中的标准位图API:

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 4;
bm = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
bm = Bitmap.createScaledBitmap(bm , 640, 480,  true);

and then write it on the disk 然后将其写在磁盘上

 imageFile = new File("/sdcard/app_dir/upload.jpg");
 FileOutputStream outStream = new FileOutputStream(imageFile);
 bm.compress(CompressFormat.JPEG, 75, outStream);
 outStream.flush();
 outStream.close();

2) edit: I've removed a call to setPreviewSize like explain there: Android: Jpeg saved from camera looks corrupted 2)编辑:我已经删除了对setPreviewSize的调用,就像在那里解释一样: Android:从相机中保存的Jpeg看起来已损坏

I think it did help for some users (Desire HD), but I can tell others still got the issue (Desire S). 我认为这对一些用户(Desire HD)有帮助,但我可以告诉其他人仍然有问题(Desire S)。

I really wish someone could explain the reason why pics looks distorded in the first place. 我真的希望有人可以解释为什么pics首先看起来像dindrded。

Well, it looks like you made some mistake with image size while decoding bitmap from byte array. 好吧,看起来你在从字节数组中解码位图时出现了图像大小的错误。 Can you post code you are using for: - setting up camera - setting up decode parameters - retrieval of image data 您可以发布用于以下的代码: - 设置相机 - 设置解码参数 - 检索图像数据

I can't tell you why you're getting garbled data from some devices and not others, but I can suggest a workaround that seems to be working successfully for my app. 我不能告诉你为什么你从某些设备而不是其他设备获得乱码数据,但我可以建议一个似乎在我的应用程序中成功运行的解决方法。

Your example code scales the camera's JPEG down to 640x480 before saving it off to the SD card. 您的示例代码将相机的JPEG缩小到640x480,然后将其保存到SD卡。 So I'm guessing you don't require the full-sized camera image. 所以我猜你不需要全尺寸的相机图像。

If this assumption is true, you can skip Camera's takePicture() API entirely, and just save a preview frame to SD card. 如果这个假设成立,你可以完全跳过Camera的takePicture() API,只需将预览帧保存到SD卡。 The easiest way to do this is with setOneShotPreviewCallback() : 最简单的方法是使用setOneShotPreviewCallback()

mCamera.setOneShotPreviewCallback( new StillPictureCallback() );

This will invoke once, and hand you back a buffer of data from the camera: 这将调用一次,并从摄像机返回数据缓冲区:

private class StillPictureCallback implements Camera.PreviewCallback {
    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        mPictureTask = new SaveStillPictureTask();
        byte[] myData = null;
        if ( data != null ) {
            myData = data.clone();
        }
        mPictureTask.execute(myData);
    }
}

The callback invokes a background task to compress the data and save it to the file. 回调调用后台任务来压缩数据并将其保存到文件中。 The only bit of code I'm leaving out is the part that queries the camera for the preview frame format, width and height via getCameraInfo() . 我遗漏的唯一代码是通过getCameraInfo()查询相机的预览帧格式,宽度和高度的部分。 Note also that the Android YUVImage class was introduced with Froyo, so if you need to support earlier versions of Android, you will need to roll your own conversion code (there are examples here on StackOverflow). 另请注意,Android YUVImage类是随Froyo引入的,因此如果您需要支持早期版本的Android,则需要滚动自己的转换代码(StackOverflow上有示例)。

/**
 * Background task to compress captured image data and save to JPEG file.
 * 
 */
private class SaveStillPictureTask extends AsyncTask<byte[], Void, Void> {

    private static final String TAG="VideoRecorder.SaveStillPictureTask";

    @Override
    protected Void doInBackground(byte[]... params) {
        byte[] data = params[0];
        FileOutputStream out = null;
        Bitmap bitmap = null;
        if ( data == null ) {
            Log.e(TAG, "doInBackground: data is null");
            return null;
        }

        try {
            out = new FileOutputStream(mSnapshotFilePath);

            // Use the preview image format, as documented in Android SDK javadoc
            if ( (mPreviewImageFormat == ImageFormat.NV21) || (mPreviewImageFormat == ImageFormat.YUY2) ) {
                saveYUVToJPEG( mCamera, out, data );
            } else if (mPreviewImageFormat == ImageFormat.JPEG) {
                Log.d(TAG, "directly write JPEG to storage");
                out.write(data);
            } else {
                Log.d(TAG, "try decoding to byte array");
                bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                if ( bitmap != null ) {
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
                } else {
                    Log.e(TAG, "decodeByteArray failed, no decoded data");
                }
            }
        } 
        catch (FileNotFoundException ignore) {;} 
        catch (IOException ignore) {;}
        finally {
            if ( out != null ) {
                try {
                    out.close();
                } catch (IOException ignore) {;}
                out = null;
            }
            if ( bitmap != null ) {
                bitmap.recycle();
                bitmap = null;
            }
            data = null;
        }

        return null;
    }
}

/**
 * Save YUV image data (aka NV21 or YUV420sp) data to JPEG file.
 * 
 * @param camera
 * @param out
 * @param data
 */
protected void saveYUVToJPEG( Camera camera, FileOutputStream out, byte[] data ) {
    YuvImage yuvimg = null;
    try {
        int width = mPreviewWidth;
        int height = mPreviewHeight;

        Rect rect = new Rect();
        rect.left   = 0;
        rect.top    = 0;
        rect.right  = width  - 1;       
        rect.bottom = height - 1;       // The -1 is required, otherwise a buffer overrun occurs
        yuvimg = new YuvImage(data, mPreviewImageFormat, width, height, null);
        yuvimg.compressToJpeg(rect, 90, out);
    } finally {
        yuvimg = null;
    }
}

I had the exact same problem on an HTC Desire S. 我在HTC Desire S上遇到了完全相同的问题。

I updated the mobile system per Settings -> About phone -> software updates 我按照设置更新了移动系统 - >关于手机 - >软件更新

I also implemented the following code: 我还实现了以下代码:

       Camera.Parameters parameters = mCamera.getParameters();
       parameters.setPictureFormat(PixelFormat.JPEG);
       mCamera.setParameters(parameters);

Worked for me. 为我工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM