Создание изображения в формате dng с использованием Camera2 API

Я создаю приложение, которое делает снимки в формате .dng для их обработки. Я использую API camera2. Мне удалось сделать снимки и сохранить их в телефоне, но в формате .jpg. Но когда я меняю свой код, чтобы сохранить их с расширением .dng, он компилируется, покажите мне предварительный просмотр на моем телефоне, но когда снимок сделан, я получаю сообщение об ошибке. Часть моего кода, которая берет и сохраняет изображение, выглядит следующим образом.

val reader = ImageReader.newInstance(1280, 720, ImageFormat.RAW_SENSOR, 1)

val outputSurfaces = ArrayList<Surface>(2)
outputSurfaces.add(reader.surface)
outputSurfaces.add(Surface(previewTextureView.surfaceTexture))

val captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
captureBuilder.addTarget(reader.surface)
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO)

val file = File("myPath/myImageName.dng")
var captureResult: CaptureResult? = null

И мои слушатели:

val readerListener = object : ImageReader.OnImageAvailableListener {
    override fun onImageAvailable(reader: ImageReader) {
        var image: Image? = null
        var output: OutputStream? = null
        val dngCreator = DngCreator(cameraManager.getCameraCharacteristics("0"), captureResult)

        try {
             image = reader.acquireLatestImage()
             output = FileOutputStream(file)
             dngCreator.writeImage(output, image)
         } catch (e: FileNotFoundException) {
             e.printStackTrace()
         } catch (e: IOException) {
             e.printStackTrace()
         } finally {
             output?.close()
             image?.close()
         }
    }
}

reader.setOnImageAvailableListener(readerListener, backgroundHandler)

val captureListener = object : CameraCaptureSession.CaptureCallback() {
    override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) {
        captureResult = result
        super.onCaptureCompleted(session, request, result)
    }
}

И, наконец, я фиксирую сеанс с помощью:

cameraDevice.createCaptureSession(outputSurfaces, object : CameraCaptureSession.StateCallback() {
    override fun onConfigured(session: CameraCaptureSession) {
        try {
             session.capture(captureBuilder.build(), captureListener, backgroundHandler)
         } catch (e: CameraAccessException) {
              e.printStackTrace()
         }
     }
     override fun onConfigureFailed(session: CameraCaptureSession) {}
}, backgroundHandler)

У меня есть одно предупреждение и одна ошибка, которых раньше не было, когда я сохранял изображение в формате jpeg:

W/CameraDevice-JV-0: Stream configuration failed due to: createSurfaceFromGbp:1106: Camera 0: No supported stream configurations with format 0x20 defined, failed to create output stream

E/CameraCaptureSession: Session 1: Failed to create capture session; configuration failed

Вещи, которые я изменил, чтобы сохранить файл dng:

  • Я заменил ImageFormat.JPEG на ImageFormat.RAW_SENSOR
  • Я изменил расширение файла с .jpg на .dng
  • Вместо использования dngCreator.writeImage(output, image) я использовал:
val buffer = image!!.planes[0].buffer
val bytes = ByteArray(buffer.capacity())
buffer.get(bytes)
output.write()

Поскольку информации по этому вопросу не так много, я не уверен, что моя реализация верна.


person NicoC    schedule 20.07.2019    source источник
comment
Не все устройства могут захватывать ImageFormat.RAW_SENSOR   -  person Alex Cohn    schedule 20.07.2019
comment
Мой аппарат может. Встроенное приложение камеры позволяет делать снимки в формате RAW и сохранять их в виде файла DNG.   -  person NicoC    schedule 21.07.2019
comment
Непонятно, что вы подразумеваете под Вместо использования dngCreator.writeImage(output, image) я использовал: … output.write(). Это то, что вы пытались сделать, чтобы проверить, не является ли причиной проблемы dngCreator, но ошибка не исчезла даже после этой попытки?   -  person Alex Cohn    schedule 21.07.2019
comment
Использовать фиксированное разрешение для захвата вредно. Никто не может гарантировать, что устройство может создавать изображения RAW_SENSOR с разрешением 1280x720.   -  person Alex Cohn    schedule 21.07.2019
comment
Я знаю, что это вредно, но я нацелен ровно на одно устройство, и это то, которое я использую. Но как вы собираетесь использовать динамическое разрешение.   -  person NicoC    schedule 21.07.2019
comment
Я имею в виду, что первое, что я попробовал, это сделать фотографии и сохранить их в формате jpeg. И как только я убедился, что это работает, я решил пойти к своей основной цели, сохраняя изображения с помощью dng. И что я изменил между моей успешной попыткой сохранения в формате jpeg и моей неудачной попыткой сохранения с использованием dng, так это 3 пули. Отсюда мой вывод, что я неправильно реализую dng   -  person NicoC    schedule 21.07.2019
comment
Несмотря на то, что родное приложение захватывает изображения в формате RAW, вы не можете быть уверены, поддерживается ли захват изображений в формате RAW. Я задал аналогичный вопрос здесь stackoverflow.com/questions/56817053/ Даже собственное приложение камеры RedmiNote 4 для моего устройства позволяет вручную управлять ISO и экспозицией, но при запросе через camera2 API оно не поддерживает ManualControl.   -  person Shivam Pokhriyal    schedule 21.07.2019
comment
Вы можете использовать этот API, чтобы проверить, поддерживается ли формат изображения. developer.android.com/reference/android/hardware/ camera2/params/ Я тоже сомневаюсь, что это будет правильно или нет :-( потому что я обнаружил, что большинство результатов, которые дает этот API, неверны.   -  person Shivam Pokhriyal    schedule 21.07.2019
comment
Я настоятельно рекомендую начать с официального примера, github.com/googlesamples/android-Camera2Raw. . Если это не работает на вашем устройстве, попробуйте открыть задачу на GitHub.   -  person Alex Cohn    schedule 21.07.2019


Ответы (2)


Это немного старый пост, но для необработанных изображений вы не можете установить разрешение на произвольное значение. Предполагая, что ваше устройство может выполнять чтение raw_sensor, оно должно быть установлено на размер сенсора. Вам нужно сделать что-то вроде этого.

val largestRaw = Collections.max(Arrays.asList(*map.getOutputSizes(ImageFormat.RAW_SENSOR)), CompareSizesByArea())

rawImageReader = ImageReader.newInstance(largestRaw.width, largestRaw.height, ImageFormat.RAW_SENSOR, /*maxImages*/ 5).apply { setOnImageAvailableListener(onRawImageAvailableListener, backgroundHandler) }

К сожалению, в Котлине я сейчас сталкиваюсь:

java.lang.IllegalArgumentException: отсутствуют поля метаданных для тега AsShotNeutral (c628)

Тем не менее, устаревший пример Java Camera2Raw, указанный выше, работает.

person draekko    schedule 25.04.2020

После некоторых исследований я нашел реализацию для сохранения изображения, снятого с помощью Camera2API, в файле .dng:

if (mImage.format == ImageFormat.RAW_SENSOR) {
    val dngCreator = DngCreator(mCharacteristics, mCaptureResult)
    var output: FileOutputStream? = null
    try {
        output = FileOutputStream(mFile)
        dngCreator.writeImage(output, mImage)
    } catch (e: IOException) {
         e.printStackTrace()
    } finally {
         mImage.close()
         closeOutput(output)
     }
}

Где :

  • mCharacteristics являются CameraCharacteristics, т.е. свойства, описывающие CameraDevice
  • mCaptureResult создается CameraDevice после обработки CaptureRequest
  • mImage — это изображение, полученное в функции dequeuAndSaveImage : image = reader.get()!!.acquireNextImage()
  • mFile — это файл, в котором будет сохранено изображение, например:
mFile = Environment
     .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
     "RAW_" + generateTimestamp()+ ".dng"

Возможно, это кому-то поможет, но, как сказал @Alex Cohn, рекомендуется начать с официального образца github.com /googlesamples/android-Camera2Raw. Он написан на Java, а не на Котлине, но при необходимости его не так уж сложно преобразовать.

person NicoC    schedule 24.07.2019