Android Camera参数setPictureSize导致图片出现条纹

标签 android image-processing android-camera

我正在尝试使用 Android 相机拍照。我需要捕获 1600 (w) x 1200 (h) 图像(第 3 方供应商要求)。我的代码似乎适用于许多手机摄像头,但 setPictureSize 会导致某些手机(三星 Galaxy S4、三星 Galaxy Note)崩溃,并导致其他手机(Nexus 7 平板电脑)出现条纹图片。至少在 Nexus 上,我想要的尺寸显示在 getSupportPictureSizes 列表中。

我试过指定方向,但没用。使用默认图片尺寸拍照效果很好。

这是一个裸奔的例子:

enter image description here

对于我的图像捕获,我需要 1600x1200、jpg、30% 的压缩率,因此我正在捕获一个 JPG 文件。

我想我有三个选择: 1) 弄清楚如何捕捉 1600x1200 尺寸而不会出现崩溃或条纹,或者 2) 弄清楚如何将默认图片大小更改为 1600x1200 的 JPG。 3) 我目前还不知道的其他事情。

我发现其他一些帖子也有类似的问题,但不完全相同。我在尝试事情的第二天,但没有找到解决方案。这是一个接近的帖子:

Camera picture to Bitmap results in messed up image (没有一个建议对我有帮助)

这是我的代码部分,在我遇到 S4/Note/Nexus 7 之前一直运行良好。我现在添加了一些调试代码:

Camera.Parameters parameters = mCamera.getParameters();
Camera.Size size = getBestPreviewSize(width, height, parameters);

if (size != null) {
    int pictureWidth = 1600;
    int pictureHeight = 1200;

    // testing
    Camera.Size test = parameters.getPictureSize();
    List<Camera.Size> testSizes = parameters.getSupportedPictureSizes();
    for ( int i = 0; i < testSizes.size(); i++ ) {
        test = testSizes.get(i);
    }

    test = testSizes.get(3);
    // get(3) is 1600 x 1200
    pictureWidth = test.width;
    pictureHeight = test.height;

    parameters.setPictureFormat(ImageFormat.JPEG);
    parameters.setPictureSize(pictureWidth, pictureHeight);
    parameters.setJpegQuality(30);
    parameters.setPreviewSize(size.width, size.height);

    // catch any exception
    try {
        // make sure the preview is stopped
        mCamera.stopPreview();

        mCamera.setParameters(parameters);
        didConfig = true;
    catch(Exception e) {
        // some error presentation was removed for brevity
        // since didConfig not set to TRUE it will fail gracefully
    }
}

这是我保存 JPG 文件的代码部分:

PictureCallback jpegCallback = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
        if ( data.length > 0 ) {

            String fileName = "image.jpg";

            File file = new File(getFilesDir(), fileName);
                String filePath = file.getAbsolutePath();

             boolean goodWrite = false;
             try {
                 OutputStream os = new FileOutputStream(file);
                 os.write(data);
                 os.close();

                goodWrite = true;
            } catch (IOException e) {
                 goodWrite = false;
             }

             if ( goodWrite ) {
                // go on to the Preview
             } else {
                // TODO return an error to the calling activity
             }

        }

        Log.d(TAG, "onPictureTaken - jpeg");
    }
};

关于如何正确设置拍照相机参数或如何裁剪或调整生成的照片大小的任何建议都很棒。特别是如果它适用于旧相机(API 级别 8 或更高版本)!基于需要图片的整个宽度,我只能裁剪掉顶部。

谢谢!

编辑:这是我最后做的:

我首先处理 Camera.Parameters getSupportedPictureSizes 以使用第一个高度和宽度均大于我想要的尺寸且宽度与高度比率相同的参数。我将相机参数设置为该图片尺寸。

然后一旦拍照:

BitmapFactory.Options options = new BitmapFactory.Options();;
options.inPurgeable = true;

// convert the byte array to a bitmap, taking care to allow for garbage collection
Bitmap original = BitmapFactory.decodeByteArray(input , 0, input.length, options);
// resize the bitmap to my desired scale 
Bitmap resized = Bitmap.createScaledBitmap(original, 1600, 1200, true);

// create a new byte array and output the bitmap to a compressed JPG
ByteArrayOutputStream blob = new ByteArrayOutputStream();
resized.compress(Bitmap.CompressFormat.JPEG, 30, blob);

// recycle the memory since bitmaps seem to have slightly different garbage collection
original.recycle();
resized.recycle();

byte[] desired = blob.toByteArray();

然后我将所需的 jpg 写到文件中以供上传。

最佳答案

test = testSizes.get(3);
// get(3) is 1600 x 1200

没有要求数组有4个以上的元素,更不用说第四个元素是1600x1200。

1) Figure out how to capture the 1600x1200 size without a crash or streaking

无法保证每台设备都能以该精确分辨率拍摄照片。您不能为分辨率指定任意值——它必须是受支持的图片尺寸之一。 一些 设备支持任意值,而其他设备会给你损坏的输出(就像这里的情况一样)或者会完全崩溃。

2) Figure out how to change the size of the default picture size to a JPG that is 1600x1200

我不知道有一个“默认图片尺寸”,除此之外,这样的尺寸将是不可变的,因为它是默认尺寸。更改图片大小是上面的选项 #1。

3) Something else that is currently unknown to me.

对于支持在两个轴上都更大的分辨率的设备,请以该分辨率拍摄照片,然后裁剪为 1600x1200。

对于所有其他设备,其中一个或两个轴都小于所需的尺寸,请以适合您的任何分辨率拍摄照片(最大、最接近 4:3 纵横比等),然后拉伸(stretch)/裁剪以获得1600x1200。

关于Android Camera参数setPictureSize导致图片出现条纹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22865598/

相关文章:

android - 像 360 全景一样自动捕捉图像

android - 无法使用前置摄像头 2 拍照

android - 相机原生代码底层逻辑

android - 来自 C 的 dlopen C++ lib,然后将 std::string 与函数一起使用

android - 第二次调用 setActive(true) 时,App 不会成为首选的 MediaButtonReceiver

c++ - 相机校准结果 : why it is similar to input?

opencv - 使用 OpenCV 从 YUV 颜色空间转换为 RGB

android - 如何将对话框定位到底部

java - 当我单击recyclerView时如何从Firestore中获取数据?

image-processing - 如何以编程方式检测屏幕撕裂?