Search code examples
androidaffdex-sdk

Bitmap is null when tried to fetch image from frame affective


I have integrated affectiva library and trying to fetch emotions using camera stream. I tried to fetch the bitmap from the frame returned but it always returns null.Below is the code.

  byte[] imageBytes = ((Frame.ByteArrayFrame) frame).getByteArray();

We have some 518 kb of data but when converted to image it returns null.

 Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
    previewImage.setImageBitmap(bitmap);

I even tried the below code but again null bitmap

Bitmap bmp=frame.getOriginalBitmapFrame();

Could you please help me to fetch bitmap from the frame?


Solution

  • There are some sample conversion methods in Affectiva's affdexme-android sample app:

    https://github.com/Affectiva/affdexme-android/blob/a0c732fb0378b9c0883d30fa21eaa9cf22b57eed/app/src/main/java/com/affectiva/affdexme/ImageHelper.java#L221

    public static Bitmap getBitmapFromFrame(@NonNull final Frame frame) {
        Bitmap bitmap;
    
        if (frame instanceof Frame.BitmapFrame) {
            bitmap = ((Frame.BitmapFrame) frame).getBitmap();
        } else { //frame is ByteArrayFrame
            switch (frame.getColorFormat()) {
                case RGBA:
                    bitmap = getBitmapFromRGBFrame(frame);
                    break;
                case YUV_NV21:
                    bitmap = getBitmapFromYuvFrame(frame);
                    break;
                case UNKNOWN_TYPE:
                default:
                    Log.e(LOG_TAG, "Unable to get bitmap from unknown frame type");
                    return null;
            }
        }
    
        if (bitmap == null || frame.getTargetRotation().toDouble() == 0.0) {
            return bitmap;
        } else {
            return rotateBitmap(bitmap, (float) frame.getTargetRotation().toDouble());
        }
    }
    
    public static Bitmap getBitmapFromRGBFrame(@NonNull final Frame frame) {
        byte[] pixels = ((Frame.ByteArrayFrame) frame).getByteArray();
        Bitmap bitmap = Bitmap.createBitmap(frame.getWidth(), frame.getHeight(), Bitmap.Config.ARGB_8888);
        bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(pixels));
        return bitmap;
    }
    
    public static Bitmap getBitmapFromYuvFrame(@NonNull final Frame frame) {
        byte[] pixels = ((Frame.ByteArrayFrame) frame).getByteArray();
        YuvImage yuvImage = new YuvImage(pixels, ImageFormat.NV21, frame.getWidth(), frame.getHeight(), null);
        return convertYuvImageToBitmap(yuvImage);
    }
    
    /**
     * Note: This conversion procedure is sloppy and may result in JPEG compression artifacts
     *
     * @param yuvImage - The YuvImage to convert
     * @return - The converted Bitmap
     */
    public static Bitmap convertYuvImageToBitmap(@NonNull final YuvImage yuvImage) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()), 100, out);
        byte[] imageBytes = out.toByteArray();
        try {
            out.close();
        } catch (IOException e) {
            Log.e(LOG_TAG, "Exception while closing output stream", e);
        }
        return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
    }
    
    public static Bitmap rotateBitmap(@NonNull final Bitmap source, final float angle) {
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
    }