Intereting Posts
Как правильно подключить приложение Android к сокету RFCOMM на микроконтроллере Arduino с поддержкой Bluetooth? Xamarin создает приложение для Android, не получая DeviceToken Parse SDK Сервер ADB не ACK на macOS Как указать правильный размер диалогового окна в файле макета XML для диалогового окна Android? Как предотвратить множественные экземпляры активности при ее запуске с разными намерениями Поля по умолчанию FloatingActionButton не работают в леденец После изменения свойства объекта LayoutParams мне нужно снова вызвать setLayoutParams? Доступны ли значения, определенные в MANIFEST.MF программно? Программное создание и привязка Android Spinners в MvvmCross Где android.os.SystemProperties? Установка MinDate в DatePicker перемещает CalendarView на 1964 Установка LongClickListener на карте Маркер Что такое setContentView (R.layout.main)? Общий дизайн приложения (IntentService / ContentProvider / AsyncTask) Как получить список доступных сетевых провайдеров?

Декодирование растровых изображений в Android с нужным размером

Я декодирую растровые изображения с SD-карты с помощью BitmapFactory.decodeFile . Иногда растровые изображения больше, чем того требует приложение или что куча позволяет, поэтому я использую BitmapFactory.Options.inSampleSize для запроса подвыборки (меньшего) растрового изображения.

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

Из http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize :

Примечание: декодер попытается выполнить этот запрос, но результирующая растровая карта может иметь разные размеры, которые точно были запрошены. Кроме того, полномочия 2 часто бывают быстрее / проще для декодера.

Как мне декодировать растровые изображения с SD-карты, чтобы получить растровое изображение точного размера, которое мне нужно, потребляя как можно меньше памяти для его декодирования?

Редактировать:

Текущий исходный код:

 BitmapFactory.Options bounds = new BitmapFactory.Options(); this.bounds.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, bounds); if (bounds.outWidth == -1) { // TODO: Error } int width = bounds.outWidth; int height = bounds.outHeight; boolean withinBounds = width <= maxWidth && height <= maxHeight; if (!withinBounds) { int newWidth = calculateNewWidth(int width, int height); float sampleSizeF = (float) width / (float) newWidth; int sampleSize = Math.round(sampleSizeF); BitmapFactory.Options resample = new BitmapFactory.Options(); resample.inSampleSize = sampleSize; bitmap = BitmapFactory.decodeFile(filePath, resample); } 

Solutions Collecting From Web of "Декодирование растровых изображений в Android с нужным размером"

Вы на правильном пути, но вы пытаетесь сделать сразу две вещи: прочитайте файл и масштабируйте его до нужного размера.

Первый шаг – прочитать файл в Bitmap немного больше, чем вам нужно, используя BitmapFactory.Options.inSampleSize, чтобы убедиться, что вы не потребляете чрезмерную память, читающую большую растровую карту, когда все, что вам нужно, – это изображение с уменьшенным изображением или разрешением экрана.

Второй шаг – вызвать Bitmap.createScaledBitmap () для создания нового растрового изображения с требуемым требуемым разрешением.

Убедитесь, что вы очистили после временного растрового изображения, чтобы восстановить его память. (Либо пусть переменная выходит из сферы действия и позволяет GC справиться с ней, либо вызывается на нее .recycle (), если вы загружаете большое количество изображений и плотно работаете в памяти.)

Вы можете использовать inJustDecodeBounds . Установите его в TRUE и загрузите файл так, как он есть.

Изображение не будет загружено в память. Но свойства outheight и outwidth BitmapFactory.Options будут содержать фактические параметры размера указанного изображения. Рассчитайте, сколько U хотите подзапросить его. Т.е. 1/2 или 1/4 или 1/8 и т. Д., И назначить 2/4/8 и т. Д. Соответственно для параметра inSampleSize .

Теперь установите inJustDecodeBounds в FALSE и вызовите BitmapFactory.decodeFile() чтобы загрузить изображение точного размера, как вычислено выше.

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

 // This function taking care of sampling backImage =decodeSampledBitmapFromResource(getResources(),R.drawable.back, width, height); // This will scale it to your screen width and height. you need to pass screen width and height. backImage = Bitmap.createScaledBitmap(backImage, width, height, false); 

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

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

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

 ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filesPath), THUMBSIZE, THUMBSIZE)) 

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

Для тех, кто ищет точный размер изображения из ресурсов.

Для точной ширины pass reqHight = 0 и для точного прохода высоты reqWidth = 0

 public static Bitmap decodeBitmapResource(Context context, int resId, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(context.getResources(), resId, options); float scale = 1; if (reqWidth != 0 && reqHeight == 0) { options.inSampleSize = (int) Math.ceil(options.outWidth / (float) reqWidth); scale = (float) options.outWidth / (float) reqWidth; } else if (reqHeight != 0 && reqWidth == 0) { options.inSampleSize = (int) Math.ceil(options.outHeight / (float) reqHeight); scale = (float) options.outHeight / (float) reqHeight; } else if (reqHeight != 0 && reqWidth != 0) { float x = (float) options.outWidth / (float) reqWidth; float y = (float) options.outHeight / (float) reqHeight; scale = x > y ? x : y; } reqWidth = (int) ((float) options.outWidth / scale); reqHeight = (int) ((float) options.outHeight / scale); options.inJustDecodeBounds = false; Bitmap tmp = BitmapFactory.decodeResource(context.getResources(), resId, options); Bitmap out = Bitmap.createScaledBitmap(tmp, reqWidth, reqHeight, false); tmp.recycle(); tmp = null; return out; } 

Поскольку я использую inSampleSize, я больше не сталкиваюсь с проблемами памяти. Поэтому inSampleSize работает довольно стабильно для меня. Я бы рекомендовал вам дважды проверить проблему. Размер может быть не таким же, как вы просили. Но это все равно должно быть уменьшено, и не должно быть больше «вне памяти». Я также рекомендую опубликовать фрагмент кода здесь, возможно, что-то не так.

Как сказал 100rabh, если вы используете BitmapFactory, у вас действительно нет большого выбора. Однако растровое декодирование действительно простое, и в зависимости от алгоритма масштабирования, который вы хотите использовать, обычно довольно просто масштабировать его «на лету» без необходимости считывать большие части исходного растрового изображения в память (в общем, вы будете Требуется только удвоить объем памяти, необходимый для 1-2 строк исходного растрового изображения).

Когда установлен флаг inScaled (по умолчанию он имеет значение ИСТИНА), если inDensity и inTargetDensity не равны 0, растровое изображение будет масштабироваться для соответствия inTargetDensity при загрузке, вместо того, чтобы полагаться на графическую систему, масштабируя ее каждый раз, когда она нарисована на Canvas. Поэтому просто установите значение inScaled в false.

 BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; 

Я смог приблизительно получить «правильный размер», изменив размер файла декодированного изображения до 70% его растрового размера.

 Bitmap myBitmap = BitmapFactory.decodeFile(path); if(myBitmap != null) { //reduce to 70% size; bitmaps produce larger than actual image size Bitmap rescaledMyBitmap = Bitmap.createScaledBitmap( myBitmap, myBitmap.getWidth()/10*7, myBitmap.getHeight()/10*7, false); image.setImageBitmap(rescaledMyBitmap); } 

Надеюсь, это поможет вам как-нибудь! Мир!