我们对产品中的位图有困难。我们的目标是快速拍照并立即显示/裁剪。问题是-图像必须有一个良好的质量,必须裁剪好和快速。我亲自尝试了下面的代码,它确实将内存使用减少了2-3倍。不过,我们仍然想知道更有效的方法。我们应该始终在自定义帧处理(使用Fotoapparat库,因为它能够高效地显示全屏摄像机视图)和ImageViews?之间传输ImageViews而不是实际位图。如果这样做效率更高,我们可以使用幻灯片或任何其他工具进行裁剪,或者加载位图。是我们当前从cameraView框架检索图像的代码(这样可以减少使用2-3倍):
ByteArrayOutputStream out = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, width, height, null);
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 50, out);
byte[] imageBytes = out.toByteArray();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options);
options.inSampleSize = calculateInSampleSize(options, (int)(width/1.5),(int)(height/1.5));
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options);然后我们用下面的方法来裁剪这个位图(在2018年,这看起来效率很低):
resizedbitmap = Bitmap.createBitmap(original, 0,0,width, height);还有,线程呢?我们应该使用AsyncTask、执行器或任何其他方式来裁剪/显示位图吗?我个人一直使用RxJava,但是我们的核心产品必须尽可能轻量级:)
发布于 2018-09-02 00:19:28
备选方案
如果您在API级别的10+上,您也可以使用BitmapRegionDecoder,它可以在一步内完成裁剪和下采样,很可能是本地的。
作为一种完全不同的方法,您还可以尝试将data直接转换为Bitmap,然后使用Canvas将原始位图的一部分绘制到新的裁剪版本上,通过画布的转换矩阵进行缩放。
质量
图像必须有一个良好的质量,必须裁剪好和快速。
在压缩到quality=50的第一步中,您将丢失大量信息。然后,当你创建新的位图时,你会做一个向上缩放,这也会影响到质量;在我看来,剪裁只有在结果图像实际上更小的时候才有意义。
效率
然后我们用下面的方法来裁剪这个位图(在2018年,这似乎是低效的)
考虑一下:你真的需要位图的大小吗?最好是将位图保留为裁剪后的大小,在内存中保留较小的位图,将较小的位图上传到GPU,并让GPU呈现进行缩放。有可能View与Bitmap大小不匹配,所以无论如何都会发生这种情况。
滑行
与代码( YUV位除外)在其核心部分几乎做了相同的事情。请参阅Downsampler,不同之处在于它适用于许多输入源、格式和API级别,因此大小不同。
我们的核心产品必须尽可能轻量级:)
包括一个图像加载库,并强迫用户将其也包括在内,这与此背道而驰。但同时,你真的想重新发明轮子,写你自己的图像加载库吗?例如,幻灯片有很多可以替换为自定义行为的部分。
在我的应用程序中,我有一个摄像头,->,用户的作物选择,->裁剪更小的位图流。我做了一些与您类似的事情,除了使用磁盘而不是ByteArrayOutputStream之外,因为输入可能很大,而且需要两次进入内存,这是无法保证的。
https://stackoverflow.com/questions/52130586
复制相似问题