Этот ответ суммируется из Loading large bitmaps Efficiently , который объясняет, как использовать inSampleSize, чтобы загрузить вниз масштабируется версию растровый .
В частности, Pre-scaling bitmaps объясняет детали различных методов , как их сочетать и которые являются наиболее эффективными с точки зрения памяти.
Есть три доминирующих способа изменить размер растрового изображения на Android, которые имеют различные свойства памяти:
createScaledBitmap API
Этот API будет принимать в существующем растровом изображении, а также создать новое растровое изображение с точные размеры, которые вы выбрали.
С положительной стороны вы можете получить именно тот размер изображения, который вы ищете (независимо от того, как он выглядит). Но недостатком, является то, что этот API требует существующего растрового изображения, чтобы работать. Это означает, что изображение должно быть загружено, декодировано и создано растровое изображение, прежде чем сможет создать новую меньшую версию. Это идеально подходит для получения ваших точных измерений, но ужасно с точки зрения дополнительных издержек памяти. Таким образом, это добрейшей сделки прерыватель для большинства разработчиков приложений, которые, как правило, быть памятью сознательного
inSampleSize flag
BitmapFactory.Options
имеет свойство отмечен как inSampleSize
что будет изменить размер изображения при декодировании его, чтобы избежать необходимость декодировать временное растровое изображение. Это целочисленное значение, используемое здесь, будет загружать изображение с уменьшенным размером 1/x. Например, установка inSampleSize
в 2 возвращает изображение, которое в два раза меньше размера, а для параметра «4» - изображение, размер которого равен 1/4. В основном размеры изображений всегда будут немного меньше, чем ваш размер источника.
С точки зрения памяти, используя inSampleSize
, это очень быстрая операция. Фактически, он будет только расшифровывать каждый X-й пиксель вашего изображения в ваш полученный растровый рисунок. Там две основные проблемы, связанные с inSampleSize
хотя:
Это не дает вам точные решения. Это уменьшает размер вашего растрового изображения на некоторую мощность 2.
Он не производит наилучшее качество resize. Большинство фильтров изменения размера создают хорошие изображения, считывая блоки пикселей, а затем взвешивая их, чтобы создать размер пикселя, о котором идет речь.inSampleSize
избегает всего этого, просто считывая каждые несколько пикселей. Результат довольно впечатляющий, и низкая память, но качество страдает.
Если вы имеете дело только с сокращения изображения каким-то размером pow2, и фильтрация не является проблема, то вы не можете найти больше памятей эффективного (или производительности эффективно), чем метод inSampleSize
.
inScaled, inDensity, inTargetDensity flags
Если вам нужно масштабировать изображение до размера, это не равно степени двойки, то вы будете нуждаться в 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
Вы можете использовать этот флаг для первоначального декодирования размера, а затем рассчитать правильные значения для масштабирования до целевого разрешения.
Возможно, ваш сервер не отправит правильный размер, чтобы сохранить оперативную память и пропускную способность вашего клиента !? – James
Это справедливо только в том случае, если у меня был ресурс сервера, у него был доступный компонент вычисления, и во всех случаях он мог предсказать точные размеры изображений для пропорций, которые он еще не видел. Поэтому, если вы загружаете контент ресурсов из стороннего CDN (например, я), он не работает :( –