Подтвердить что ты не робот

Изображение камеры для растрового изображения приводит к испорченному изображению

Это мой код, который я использую для сохранения изображения в 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 напрямую с помощью FileOutputStream создавало правильный образ JPEG. Поэтому проблема должна быть с BitmapFactory и тем, как я создаю Bitmap.

Это растровое изображение, которое производит этот код:

Broken image

EDIT (24.03.2013):

Проведя несколько часов, пытаясь исправить это, у меня до сих пор нет реального решения. Все, что я узнал, заключается в том, что проблема возникает, когда я устанавливаю размер изображения (используя Camera.Parameters.setPictureSize(int width, int height)) с максимально возможным разрешением, которое доступно для фронтальной камеры, которое я получил, вызывая Camera.Parameters.getSupportedPictureSizes().

Разрешение, вызывающее проблему, составляет 1280x960. Как я уже говорил ранее, это самое высокое разрешение. Второй самый высокий - 1280x720, и когда я использую это, выходное изображение прекрасное. Я проверил формат, который выкачивает камера, и он ImageFormat.JPEG все время, поэтому я не думаю, что формат пикселей здесь является проблемой...

EDIT (08.03.2013): Вызов toPicture:

private class XyzAutoFocusCallback implements Camera.AutoFocusCallback {

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

}
4b9b3361

Ответ 1

Высота и ширина не поддерживаются для этой камеры. Вот почему это выглядит так и почему работает настройка 1280x720. Это так же, как если бы вы установили, что ваш Starcraft запускается с разрешением, не поддерживаемым вашим монитором.

Ответ 2

Попробуйте это

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

ByteArrayOutputStream bos = new ByteArrayOutputStream();
bmp.compress(CompressFormat.JPEG, 70, bos);

Ответ 3

Вы пытались поместить 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();
    }
}

Ответ 4

Я бы предложил не устанавливать размер изображения в коде и позволить камере вернуть наилучший снимок, который он может захватить. Проверьте код, указанный в ответе здесь. fooobar.com/questions/235634/...

Ответ 5

Вы устанавливаете параметры с задней камеры на переднюю камеру? Еще одно, что нужно проверить для передней камеры, сначала не пытайтесь установить какой-либо параметр, просто используйте настройки по умолчанию, чтобы увидеть, будет ли он работать. Я столкнулся с аналогичными проблемами на устройствах Samsung, но это было для задней камеры. Кроме того, вам может потребоваться повернуть изображения, сделанные с передней камеры (для камеры Samsung также нужна задняя камера)

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);
    }

Ответ 6

Я должен, вероятно, также упомянуть, что сохранение данных напрямую с помощью FileOutputStream создавал правильное изображение в формате JPEG. Поэтому проблема должна быть с BitmapFactory и тем, как я создаю Bitmap.

Выходы камеры полностью обрабатываются данными JPEG (надеюсь), и вы можете записать их на диск. Теперь, что вы должны попробовать:

  • файл dump на диск.
  • Проверьте этот файл с помощью средства проверки или какого-либо редактора изображений на ПК.
  • Если редактор изображений отлично отображает изображение, сохраните копию из этого редактора изображений, используя стандартный профиль JPEG.
  • Попросите BitmapFactory обработать исходный файл и файл, сохраненные редактором изображений, посмотрите, не получается ли вы получить растровое изображение в обоих случаях.

Если изображение верное JPEG и BitmapFactory все еще создает неправильную растровую карту, проблема связана с BitmapFactory (менее вероятно), если файл, выданный камерой, является недопустимым JPEG, проблема связана с камерой (более вероятно).

Ответ 7

Это мой код, который я использую для съемки и сохранения их в базе данных без изменения его качества.

Сначала вам нужны эти переменные:

 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();

Затем установите запрос, с помощью кнопки, активности или фрагмента, в зависимости от вашего приложения (Mine использует кнопку)

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, как вы можете видеть, при созданииScaledBitmap, я размещаю размеры рисунка, до 400 400 вы можете поместить размеры рисунка, который вы хотите получить, обязательно поверните растровое изображение, чтобы вы могли получить изображение вправо, даже если вы снимаете фотографию в портретном режиме.

Наконец, методы поворота и получения изображения с Пути, которые камера сохраняет.

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;
}

Надеюсь, это может вам помочь.