Самый эффективный способ изменить размер растровых изображений на android?



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



проблема в том, что с помощью createScaledBitmap заставляет меня столкнуться с большим количеством ошибок из памяти после изменения размера Орды миниатюр изображений.



каков наиболее эффективный способ изменения размера растровых изображений на Android?

655   2  

2 ответов:

этот ответ суммируется из загрузка больших растровых изображений эффективно что объясняет, как использовать inSampleSize для загрузки растрового изображения с уменьшенным масштабом версия.

в частности предварительное масштабирование растровых изображений объясняет детали различных методы, как их комбинировать, и какие из них наиболее эффективны для памяти.

есть три основных способа изменить размер растрового изображения на Android, которые имеют разную память свойства:

createScaledBitmap API

этот API будет принимать существующее растровое изображение и создавать новое растровое изображение с точными размерами, которые вы выбрали.

С другой стороны, вы можете получить именно тот размер изображения, который вы ищете (независимо от того, как он выглядит). Но есть и обратная сторона,это то, что этот API требует существующей растровое изображение для работы. Это означает, что изображение должно быть загружается, декодируется и создается растровое изображение, прежде чем можно будет создать новую, меньшую версию. Это идеально с точки зрения получения ваших точных размеров, но ужасно с точки зрения дополнительных накладных расходов памяти. Таким образом, это своего рода прерыватель сделки для большинства разработчиков приложений, которые, как правило, сознательны в памяти

флаг inSampleSize

BitmapFactory.Options имеет свойство отмечено как inSampleSize это изменит размер вашего изображения при его декодировании, чтобы избежать необходимости декодирование во временное растровое изображение. Это целочисленное значение, используемое здесь, будет загружать изображение с уменьшенным размером 1 / x. Например, установка inSampleSize to 2 возвращает изображение, которое является половиной размера, и установка его в 4 возвращает изображение, которое является 1/4 размера. В основном размеры изображений всегда будут немного меньше, чем ваш размер источника.

С точки зрения памяти, используя inSampleSize - это очень быстрая операция. Эффективно, он будет декодировать только каждый X-й пиксель вашего изображения в ваш результат растровый. Есть две основные проблемы, с inSampleSize но:

  • он не дает вам точных разрешений. Это только уменьшает размер вашего растрового изображения на некоторую степень 2.

  • он не производит лучшее качество изменения размера. Большинство фильтров изменения размера создают хорошо выглядящие изображения, считывая блоки пикселей, а затем взвешивая их для получения соответствующего размера пикселя. inSampleSize избегает всего этого, просто читая каждые несколько пикселей. Результат довольно производительный, и низкая память, но качество страдает.

если вы имеете дело только с уменьшением изображения на некоторый размер pow2, а фильтрация не является проблемой, то вы не можете найти более эффективный метод памяти (или производительности), чем inSampleSize.

inScaled, inDensity, inTargetDensity флаги

если вам нужно масштабировать изображение до размера, который не равен сила двух, тогда вам понадобится inScaled,inDensity и inTargetDensity флаги BitmapOptions. Когда inScaled флаг установлен, система выведет значение масштабирования для применения к вашему растровому изображению путем деления inTargetDensity на inDensity значения.

mBitmapOptions.inScaled = true;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity =  dstWidth;

// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeResources(getResources(), 
      mImageIDs, mBitmapOptions);

использование этого метода изменит размер вашего изображения, а также применит к нему "фильтр изменения размера", то есть конечный результат будет выглядеть лучше, потому что на этапе изменения размера была учтена некоторая дополнительная математика. Но будьте осторожны: , что дополнительный шаг, фильтра, занимает дополнительное время обработки, и может быстро складываться для больших изображений, что приводит к медленным размерам и дополнительным выделениям памяти для самого фильтра.

обычно не рекомендуется применять этот метод к изображению, которое значительно больше, чем ваш желаемый размер, из-за дополнительных накладных расходов на фильтрацию.

Волшебная Комбинация

С точки зрения памяти и производительности, вы можете объединить эти варианты для достижения наилучших результатов. (установка inSampleSize,inScaled,inDensity и inTargetDensity флаги)

inSampleSize сначала будет применен к изображению, получив его в следующей степени два больше, чем ваш целевой размер. Тогда,inDensity & inTargetDensity используются для масштабирования результата до точных размеров, которые вы хотите, применяя операцию фильтра для очистки изображения.

объединение этих двух является гораздо более быстрой операцией, так как inSampleSize шаг уменьшит количество пикселей что полученный шаг на основе плотности должен будет применить фильтр изменения размера.

mBitmapOptions.inScaled = true;
mBitmapOptions.inSampleSize = 4;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity =  dstWidth * mBitmapOptions.inSampleSize;

// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeFile(fileName, mBitmapOptions);

Если вам нужно подогнать изображение к определенным размерам,и некоторая более приятная фильтрация, тогда этот метод является лучшим мостом для получения нужного размера, но выполняется в быстрой операции с низким объемом памяти.

получение размеров изображения

получение размера изображения без декодирования всего изображения Для того, чтобы изменить размер растровое изображение, вам нужно будет знать входящие размеры. Вы можете использовать inJustDecodeBounds флаг, чтобы помочь вам получить размеры изображения, без необходимости фактически декодировать данные пикселей.

// Decode just the boundaries
mBitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fileName, mBitmapOptions);
srcWidth = mBitmapOptions.outWidth;
srcHeight = mBitmapOptions.outHeight;


//now go resize the image to the size you want

вы можете использовать этот флаг для декодирования размера, а затем вычислить правильные значения для масштабирования до целевого разрешения.

как хороший (и точный), как этот ответ, это также очень сложно. Вместо того, чтобы заново изобретать колесо, рассмотрим библиотеки, такие как скольжения,Пикассо,Уил,Иона, или любое количество других, которые реализуют эту сложную и подверженную ошибкам логику для вас.

сам Кольт даже рекомендует взглянуть на Glide и Picasso в предварительное масштабирование растровых изображений Шаблоны производительности видео.

с помощью библиотеки, вы можете получить каждый бит эффективности, упомянутый в ответе Colt, но с гораздо более простыми API, которые работают последовательно в каждой версии Android.

Comments

    Ничего не найдено.