RedApparat / Fotoapparat

Making Camera for Android more friendly. 📸
Apache License 2.0
3.82k stars 407 forks source link

Unable to create Bitmap from preview Frame #279

Closed claudiu-bele closed 5 years ago

claudiu-bele commented 6 years ago

What are you trying to achieve or the steps to reproduce?

I want to save the last preview Frame to a file instead of the result of photoApparat.takePicture(), and in that process i need to make a Bitmap object from the Frame. BitmapFactory calls return null, I've been trying to following

BitmapFactory.decodeByteArray(frame.image, 0, frame.size.area)
// and
BitmapFactory.decodeStream(ByteArrayInputStream(frame.image))
// and
val bitmap = Bitmap.createBitmap(frame.size.width, frame.size.height, Bitmap.Config.ARGB_8888)
val byteBuffer = ByteBuffer.wrap(frame.image)
bitmap.copyPixelsFromBuffer(byteBuffer)

The first 2 attempts return null, last one returns exception Buffer not large enough for pixels. Is there any other option to save the preview Frame to file or getting a bitmap for it?

Otherwise, the library works as intended

Context:

leicht-io commented 6 years ago

I have the same problem.

leicht-io commented 6 years ago

I managed to fix it. I checked the source code and it seems that the image format is NV21 which BitmapFactory doesn't support.

I wrote the below code which converts the YUV image to a Bitmap.

YuvImage yuvImage = new YuvImage(frame.image, ImageFormat.NV21, width, height, null);
ByteArrayOutputStream os = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, os);
byte[] jpegByteArray = os.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.length);
murgupluoglu commented 6 years ago

Also this can be made with RenderScript like this:

    val rs = RenderScript.create(CONTEXT_HERE)
    val yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs))

    val yuvType = Type.Builder(rs, Element.U8(rs)).setX(byteArray.size)
    val inData = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT)

    val rgbaType = Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height)
    val outData = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT)

    inData.copyFrom(byteArray)

    yuvToRgbIntrinsic.setInput(inData)
    yuvToRgbIntrinsic.forEach(outData)

    val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    outData.copyTo(bitmap)
dmitry-zaitsev commented 5 years ago

@ChristianLJ that is exactly correct, frames are in NV21 format which is not supported by BitmapDecoder. Thanks for sharing your solution 👍