Android: Можем ли мы на самом деле сохранить функцию ImageLader acquLatestImage ()? - PullRequest
0 голосов
/ 21 февраля 2019

В настоящее время я работаю с Camera2 API и создал новый объект ImageReader.OnImageAvailableListener.Конечно, он должен реализовывать метод onImageAvailable(ImageReader reader).Единственное, чего я хочу, - это получить последнее изображение из этого ридера и сохранить его, но, к сожалению, я просто не могу его получить.Я прочитал много исходных кодов, посетил разные Topcis StackOverflow, но не смог найти ответ.Я сейчас нахожусь в тот момент, когда мне нужно спросить: может ли этот Image объект действительно сохраняться как файл изображения в памяти телефона?Вот метод:

@Override
public void onImageAvailable(ImageReader reader) {

    Image image = reader.acquireLatestImage();

    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
    buffer.rewind();
    byte[] bytes = new byte[buffer.capacity()];
    buffer.get(bytes);

    save(bytes);

    image.close();

}

Метод save () открывает только FileOutputStream и записывает в него байты, он работает.Проблема в том, что я получаю только черное изображение, и оно имеет очень маленький размер.

Формат изображения - JPEG, именно так я ранее настроил свой экземпляр ImageReader.

Iдаже пытался конвертировать его в разные форматы, например, от NV21 до JPEG и прочее, но ничего не вышло.Что мне здесь не хватает?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Вы пробовали пример приложения camera2, Camera2Basic ?Он сохраняет JPEG с кодом, очень похожим на ваш, и должен нормально работать.

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

0 голосов
/ 21 февраля 2019

Вот класс, который я использовал для извлечения Bitmap из Image.

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.media.Image
import java.io.IOException
import java.io.InputStream
import java.nio.ByteBuffer
import kotlin.experimental.and

class ImagePreprocessor {
    private var rgbFrameBitmap = Bitmap.createBitmap(IMAGE_WIDTH, IMAGE_HEIGHT,
            Bitmap.Config.ARGB_8888)

    fun preprocessImage(image: Image?): Bitmap? {
        if (image == null) {
            return null
        }

        check(rgbFrameBitmap!!.width ==  image.width, { "Invalid size width" })
        check(rgbFrameBitmap!!.height == image.height, { "Invalid size height" })

        if (rgbFrameBitmap != null) {
            val bb = image.planes[0].buffer
            rgbFrameBitmap = BitmapFactory.decodeStream(ByteBufferBackedInputStream(bb))
        }

        return rgbFrameBitmap
    }

    private class ByteBufferBackedInputStream(internal var buf: ByteBuffer) : InputStream() {

        @Throws(IOException::class)
        override fun read(): Int {
            return if (!buf.hasRemaining()) {
                -1
            } else (buf.get() and 0xFF.toByte()).toInt()
        }

        @Throws(IOException::class)
        override fun read(bytes: ByteArray, off: Int, len: Int): Int {
            var len = len
            if (!buf.hasRemaining()) {
                return -1
            }

            len = Math.min(len, buf.remaining())
            buf.get(bytes, off, len)
            return len
        }
    }
}

Я использовал это для установки растрового изображения непосредственно на ImageView, но оно должно бытьможно использовать метод compress на Bitmap, чтобы сохранить его в файл.Обратите внимание, что это работает только для JPEG, поскольку данные находятся в одной плоскости.

...