Эффективно ли обрезать и масштабировать растровое изображение 2018? - PullRequest
0 голосов
/ 01 сентября 2018

У нас проблемы с растровыми изображениями в нашем продукте. Наша цель - сделать снимок быстро и немедленно отобразить его / обрезать. Проблема в том, что изображение должно быть хорошего качества, должно быть хорошо и быстро обрезано. Я лично попробовал приведенный ниже код, и он уменьшает использование памяти в ~ 2-3 раза. Тем не менее, мы хотели бы узнать более эффективный способ. Должны ли мы всегда передавать imageArray [] вместо реальных растровых изображений между нашей обработкой пользовательских кадров (используя библиотеку Fotoapparat, из-за ее способности эффективно отображать полноэкранный вид с камеры) и ImageViews? Мы открыты для использования Glide или любого другого инструмента для обрезки или загрузки растрового изображения, если это будет более эффективным. Наш текущий код для извлечения изображений из фреймов 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, Executors или любые другие способы обрезки / отображения растрового изображения? Лично я всегда использую RxJava, однако наш основной продукт должен быть максимально легким:)

1 Ответ

0 голосов
/ 02 сентября 2018

Альтернативы

Если вы находитесь на уровне API 10+, вы можете альтернативно использовать BitmapRegionDecoder, который выполняет обрезку и понижение частоты дискретизации за один шаг, возможно, на нативном языке.

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

качество

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

Ваш первый шаг, когда вы сжимаете до quality=50, вы теряете много информации. Затем, когда вы создаете новое растровое изображение, вы увеличиваете масштаб, что также влияет на качество; на мой взгляд, обрезка имеет смысл, только если результирующее изображение на самом деле меньше.

Эффективность

Затем мы обрезаем это растровое изображение с помощью метода ниже (это кажется неэффективным в 2018 году)

Подумайте над этим: вам действительно нужно, чтобы точечный размер был точным? Вероятно, гораздо лучше оставить растровое изображение в качестве обрезанного размера, иметь меньший растровое изображение в памяти, загрузить меньшее растровое изображение в графический процессор и позволить масштабированию с помощью рендеринга графического процессора. Возможно, View не будет соответствовать размеру Bitmap, поэтому это все равно произойдет.

Glide

Glide в основном делает то же самое, что и ваш код (кроме бита YUV). См. Downsampler, разница в том, что он работает со многими источниками ввода, форматами и уровнями API, отсюда и разница в размере.

наш основной продукт должен быть максимально легким:)

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

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

...