13

这是我用来将图像保存到Bitmap. 这段代码是基于 CyanogenMod 的相机应用程序的代码,所以我认为它可以正常工作,但不是。关于这个问题最重要的一点是,在 Nexus 4 上进行测试时,Bitmap可以为使用后置摄像头拍摄的照片正确创建,但使用前置摄像头会导致您在下面看到的内容。

我用来创建的代码Bitmap

private class XyzPictureCallback implements Camera.PictureCallback {

    @Override
    public void onPictureTaken (byte [] data, Camera camera) {
        Options options = new Options();
        options.inDither = false;
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;

        Bitmap image = BitmapFactory.decodeByteArray(data, 0, data.length, options);
    }
}

我尝试使用不同的Options(根本没有),但没有帮助。这可能与两个不同相机返回的像素格式有关,但是当我运行getSupportedPictureFormats()它们时它们都返回了ImageFormat.JPEG......

我的想法不多了...

我可能还应该提到data直接使用 a保存FileOutputStream是创建正确的 JPEG 图像。所以问题一定出BitmapFactory在我创建Bitmap.

这是此代码生成的位图:

损坏的图像

编辑(24.03.2013):

在花了几个小时试图解决这个问题后,我仍然没有真正的解决方案。我发现只有当我将图片大小(使用Camera.Parameters.setPictureSize(int width, int height))设置为前置摄像头可用的最高分辨率时才会出现问题,我通过调用Camera.Parameters.getSupportedPictureSizes().

导致问题的分辨率是 1280x960。正如我之前提到的,它是最高分辨率。第二高的是 1280x720,当我使用这个时,输出图片很好。我确实检查了相机吐出的格式,它一直是 ImageFormat.JPEG 所以我不认为像素格式是这里的问题......

编辑(2013 年 3 月 8 日): 调用图片:

private class XyzAutoFocusCallback implements Camera.AutoFocusCallback {

            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                    if (takingPicture) {
                            camera.takePicture(null, null, myPictureCallback);
                    } else {
                    ...
            }

}
4

7 回答 7

3

该相机不支持高度和宽度。这就是为什么它看起来像这样以及为什么 1280x720 设置有效。就像您将星际争霸设置为以显示器不支持的分辨率运行一样。

于 2013-03-30T18:03:15.830 回答
0

尝试这个

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

ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 70, bos);
于 2013-03-14T08:48:07.687 回答
0

我可能还应该提到直接使用 FileOutputStream 保存数据正在创建正确的 JPEG 图像。所以问题一定出在 BitmapFactory 和我创建 Bitmap 的方式上。

相机输出完全处理的 JPEG 数据(希望如此),您可以将其写入磁盘。现在你应该尝试什么:

  1. 将文件转储到磁盘。
  2. 使用验证工具或 PC 上的某些图像编辑器检查该文件。
  3. 如果图像编辑器可以正常打开图像,请使用标准 JPEG 配置文件从该图像编辑器保存一份副本。
  4. 已经BitmapFactory处理了图像编辑器保存的原始文件和文件,看看你是否得到了一个坏的位图。

如果图像是有效的 JPEG 并且BitmapFactory仍然产生错误的位图,则问题出在BitmapFactory(不太可能),如果相机输出的文件是无效的 JPEG,则问题出在相机(更有可能)。

于 2013-03-31T07:09:57.063 回答
0

您是否尝试将 null 放在您的选项中?试试看:

@Override
public void onPictureTaken(final byte[] data, Camera camera) {
    Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length, null);
    try {
        FileOutputStream out = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/image.jpg");
        bm.compress(Bitmap.CompressFormat.JPEG, 95, out);
        out.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
于 2013-03-28T18:24:58.973 回答
0

你是在设置后置摄像头到前置摄像头的参数吗?还有一点要测试的是前置摄像头,先试试不设置任何参数,用默认设置看看能不能用。我在三星设备上遇到了类似的问题,但那是后置摄像头。此外,您可能需要旋转使用前置摄像头拍摄的图像(三星设备的后置摄像头也需要)

public static Bitmap rotate(Bitmap bitmap, int degree) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        Matrix mtx = new Matrix();
        mtx.postRotate(degree);

        return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
    }
于 2013-03-31T02:54:34.227 回答
0

我建议不要在代码中设置图片大小,让相机返回它可以捕获的最佳图片。检查此处答案中给出的代码。 https://stackoverflow.com/a/9745780/2107118

于 2013-03-30T18:17:49.990 回答
0

这是我的代码,我用来拍照,并将它们保存在数据库中,而不改变其质量。

首先你需要这个变量:

 private static final int CAMERA_PIC_REQUEST = 2500;
private Rect Padding = new Rect(-1,-1,-1,-1);
private Matrix matrix = new Matrix();
private Bitmap rotatedBitmap = null;
private Bitmap bm = null;
private Bitmap scaledBitmap= null;
private ExifInterface exif ;
private int rotation=0;
private final BitmapFactory.Options options = new BitmapFactory.Options();

然后根据您的应用程序从按钮、活动或片段设置请求(我的使用按钮)

btn_camera.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View view) {

              Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
              startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);

          }
    }
    );

现在,当我从片段请求 CAMERA _PIC_REQUEST 时,我在 OnActivityResult() 上实现此代码

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAMERA_PIC_REQUEST)
        if (data != null) {
        imageuri = data.getData();
        //Bitmap image = (Bitmap) data.getExtras().get("data");

        try {
            options.inSampleSize = 2;
            exif = new ExifInterface(getRealPathFromURI(imageuri));
            rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            rotation = exifToDegrees(rotation);

            bm = BitmapFactory.decodeStream(
                    getActivity().getContentResolver().openInputStream(imageuri),Padding,options);

            scaledBitmap = Bitmap.createScaledBitmap(bm, 400,400, true);

            if (rotation != 0)
            {matrix.postRotate(rotation);}
            //matrix.postRotate(180);
            rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap .getWidth(), scaledBitmap .getHeight(), matrix, true);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        mIvFoto.setImageBitmap(rotatedBitmap);


     }
 }

旋转和矩阵用于将拍摄的图片缩放到 ImageView,因此我可以在保存之前预览照片。这不影响图片的质量。它仅用于预览位图。所以在ScaledBitmap变量中你可以看到,在CreatingScaledBitmap的时候,我把图片的尺寸设置为400400,你可以放置你想要的图片的尺寸,一定要旋转位图,这样你才能得到正确的图片,即使您以纵向模式拍摄照片。

最后是从相机保存的路径中旋转和获取图片的方法。

private static int exifToDegrees(int exifOrientation) {
    if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; }
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {  return 180; }
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {  return 270; }
    return 0;
}

private String getRealPathFromURI(Uri contentURI) {
    String result;
    Cursor cursor =getActivity().getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) { // Source is Dropbox or other similar local file path
        result = contentURI.getPath();
    } else {
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

我希望这可以帮助你。

于 2015-05-14T14:37:00.017 回答