Ця відповідь підсумована із завантаження великих растрових зображень. Ефективно
пояснює, як використовувати inSampleSize для завантаження зменшеної версії растрових зображень.
Зокрема, растрові зображення попереднього масштабування пояснюють деталі різних методів, способи їх поєднання та які є найбільш ефективними в пам'яті.
Існує три домінуючі способи змінити розмір растрової карти на Android, які мають різні властивості пам'яті:
createScaledBitmap API
Цей API візьме наявну растрову карту та створить НОВУ растрову карту із точними вибраними розмірами.
З іншого боку, ви можете отримати саме той розмір зображення, який ви шукаєте (незалежно від того, як воно виглядає). Мінусом є те, що для роботи цього API потрібна наявна растрова карта . Це означає, що зображення доведеться завантажувати, розшифровувати та створювати растрові карти, перш ніж мати можливість створити нову, меншу версію. Це ідеально з точки зору отримання точних розмірів, але жахливо з точки зору додаткових витрат на пам'ять. Таким чином, для більшості розробників додатків це вимикач укладення угод, який, як правило, має пам'ять
inSampleSize прапор
BitmapFactory.Options
має властивість, яка зазначає, inSampleSize
що дозволить змінити розмір зображення під час його розшифровки, щоб уникнути необхідності декодування до тимчасової растрової карти. Це ціле значення, яке тут використовується, завантажить зображення у зменшеному розмірі на 1 / х. Наприклад, якщо встановити inSampleSize
значення 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
Ви можете використовувати цей прапор, щоб спершу розшифрувати розмір, а потім обчислити належні значення масштабування до цільової роздільної здатності.