Open utterances-bot opened 2 years ago
Good stuff, I'm trying to use the output of ExoPlayer to create JPEG/WEBP thumbs. It's a similar problem.
If you only need Q+, you can convert to Bitmap instantly. Further, if you convert to RGBA you can use Bitmap.compress() to output any supported format.
Notes:
Tested on Pixel 3a, Android S. toRGBA, 5-7 ms, toJPEG=32-40ms
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
long start = SystemClock.uptimeMillis();
HardwareBuffer hardwareBuffer = image.getHardwareBuffer();
final Bitmap hardware = Bitmap.wrapHardwareBuffer(hardwareBuffer, null);
final ImageReader rgbaImageReader = ImageReader.newInstance(hardware.getWidth(),
hardware.getHeight(), PixelFormat.RGBA_8888, 1,
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
final Surface surface = rgbaImageReader.getSurface();
final Canvas canvas = surface.lockHardwareCanvas();
canvas.drawBitmap(hardware, 0f, 0f, null);
surface.unlockCanvasAndPost(canvas);
rgbaImageReader.setOnImageAvailableListener(reader -> {
final Image rgbaImage = rgbaImageReader.acquireNextImage();
final Bitmap rgb = Bitmap.wrapHardwareBuffer(rgbaImage.getHardwareBuffer(), null);
Log.d("TAG", "toRGBA ms=" + (SystemClock.uptimeMillis() - start));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
rgb.compress(Bitmap.CompressFormat.JPEG, 90, out);
Log.d("TAG", "toJPEG ms=" + (SystemClock.uptimeMillis() - start));
}, mImageView.getHandler());
}
That was with a 720p image. Numbers at 8MP (3264x2448). toRGBA=15ms, toJPEG=(180-15)=165. Still crushing it on the toRGBA side. I would like to avoid C++, so I'm thinking about using a hybrid RenderScript/Bitmap.wrapBuffer() approach.
How to use RenderScript to convert YUV_420_888 YUV Image to Bitmap | Minhaz’s Blog
RenderScript turns out to be one of the best APIs for running computationally-intensive code on the CPU or GPU (that too, without having to make use of the NDK or GPU-specific APIs). We can use some existing intrinsics or create our new kernels that describe the computation and the framework takes care of scheduling & execution. In this code I have explained how to useScriptIntrinsicYuvToRGB intrinsic that is available in Android APIs to convert an android.media.Image in YUV_420_888 format to Bitmap.
https://blog.minhazav.dev/how-to-use-renderscript-to-convert-YUV_420_888-yuv-image-to-bitmap/