2013-05-07 3 views
0

Это может показаться очень конкретным ... И это любопытно.Как загрузить изображение 2048x2048 на Android 2.3?

Мне действительно нужно загрузить 32-битное изображение 2048x2048 на Android 2.3 (особенно Nexus One и Xperia Play, где приложение в его текущей форме выходит из строя с ошибкой вне памяти).

Android 2.2 загружает его в порядке, и все андроиды после 2.3 загружают его тоже, а некоторые 2.3 устройства (обычно с огромными кучами) также загружают его в порядке.

Xperia Play в частности сообщает (через OpenGL), что он может загружать изображения до 4096x4096, а с помощью Marmalade SDK я действительно мог загружать сумасшедшие огромные изображения, а многие из них легко использовали 150 МБ памяти.

Но я не могу понять, как загрузить 2048x2048 изображение с Java на этом устройстве, он просто бросает мне эту ошибку:

05-07 17: 41: 25,202: E/GraphicsJNI (27847): VM выиграл» т давайте выделить 30965760 байт

EDIT: Прекратите говорить мне использовать более низкое разрешение, я процитирую себя:

I really need to load a 2048x2048 32-bit image on Android 2.3

нижний образец изображения не является 2048x2048, ни более высокий один или масштабируется один , или версия mipmap, или что-нибудь еще ... Мне нужно загрузить эти снимки, ОНИ ОНИ, PE МСБОЗ.

+0

Можете ли вы снизить качество изображения (предположим, что это jpg), чтобы он не занимал столько памяти? – Renan

+1

Это png и 30 Мб памяти, которую он ест при несжатом. (сжато 500kb) – speeder

ответ

4

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

Поскольку вы не хотите уменьшать изображение, что вполне понятно, вы можете захотеть взглянуть на снижение качества/sizeInMbs изображения, которое вы загружаете в память.

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

Посмотрите на этот demo from Romain Guy, где он использует изображения размером 1280 * 752, и все же их размеры составляют всего несколько сотен фунтов. Несмотря на этот небольшой размер, изображения выглядят действительно четкими и четкими на working demo.


Прежде всего, загружая 2048 * 2048 изображение на экране небольшого устройства, например, тех устройств, которые вы упомянули это пустая трата ресурсов. Вот ссылка на fully detailed tutorial о том, как эффективно масштабировать и загружать большие изображения.

Имейте в виду, что вы должны попытаться масштабировать изображения, если это возможно, на сайте разработчика Android упоминается следующее: «Изображение с более высоким разрешением не дает никакой видимой пользы, но по-прежнему занимает драгоценную память и несет дополнительные служебные накладные расходы из-за дополнительного масштабирования на лету ».

Шаг первый, сначала снимите изображение, используя BitmapFactory.Опции:

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
BitmapFactory.decodeResource(getResources(), R.id.myimage, options); 
int imageHeight = options.outHeight; 
int imageWidth = options.outWidth; 
String imageType = options.outMimeType; 

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

public static int calculateInSampleSize(
     BitmapFactory.Options options, int reqWidth, int reqHeight) { 
// Raw height and width of image 
final int height = options.outHeight; 
final int width = options.outWidth; 
int inSampleSize = 1; 

if (height > reqHeight || width > reqWidth) { 

    // Calculate ratios of height and width to requested height and width 
    final int heightRatio = Math.round((float) height/(float) reqHeight); 
    final int widthRatio = Math.round((float) width/(float) reqWidth); 

    // Choose the smallest ratio as inSampleSize value, this will guarantee 
    // a final image with both dimensions larger than or equal to the 
    // requested height and width. 
    inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
} 

return inSampleSize; 
} 

Наконец, вы можете масштабировать его вниз с помощью:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
    int reqWidth, int reqHeight) { 

// First decode with inJustDecodeBounds=true to check dimensions 
final BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
BitmapFactory.decodeResource(res, resId, options); 

// Calculate inSampleSize 
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

// Decode bitmap with inSampleSize set 
options.inJustDecodeBounds = false; 
return BitmapFactory.decodeResource(res, resId, options); 
} 
+0

Изображение на самом деле является атласом изображения для анимации, я использую все его разрешение, на самом деле конечный результат (кадры) уже отображается с половиной разрешения, если я использовал правильное разрешение устройства , Мне понадобится 4096x4096 на Xperia Play и 8192x8192 на планшетах ... – speeder

+0

Взгляните на обновленный ответ –

-1

Вы придется уменьшить масштаб растрового изображения, чтобы уменьшить потребление памяти. Я советую вам посмотреть официальную документацию по этому вопросу Loading Large Bitmaps Efficiently.

В качестве дополнительного совета не забывайте перерабатывать все ваши неподтвержденные растровые изображения. Это поможет GC быстрее освободить память.

-1

Если вам нужно полное разрешение по какой-либо причине (в отличие от уменьшенного разрешения в ответ daniel_c05), и вы не можете использовать OpenGL (почему нет? Это идеально подходит для этого),

  1. Split его в плитки
  2. Загружать и отображать только несколько фрагментов за один раз
  3. Если вам нужно эффективное масштабирование, предварительно масштабируйте изображение (mipmap) и выровняйте каждый уровень.

Но на самом деле, вы должны использовать OpenGL, если работаете в этом масштабе и хотите скорость.

+0

OpenGL может загружать прямо из apk как-то? Пропустить кучу? – speeder

+0

Да и нет. Вы можете загружать активы из apk так же, как вы можете загрузить их в растровое изображение. Тем не менее, вы не можете использовать один и тот же тип сжатия, поэтому вы обычно застряли в несжатых ресурсах или используете собственную библиотеку png. Реальный раскол происходит потому, что 1) эти изображения никогда не ударяли землю Java без сжатия и 2) их можно было выгружать на графический процессор и даже не нужно было забирать какую-либо ОЗУ. Если вы делаете что-либо подобное, используйте хорошую 3D-библиотеку. Я от всей души рекомендую libgdx. – Delyan

+0

Я действительно не понял ... Как загрузить файл png прямо в OpenGL и пропустить кучу? – speeder

1

байт звучит довольно большой для разрешения 2048x2048.

Возможно ли, что изображение является 32-битным на канал вместо 8-бит на канал? Обычная ошибка, когда я спрашиваю людей о 32-разрядном PNG, заключается в том, что они выбирают режим 32-битного/канального (128-битного изображения) в такой программе, как Photoshop.

Красный (8-битный) + зеленый (8-битный) + синий (8-битный) + альфа (8-битный) = а 32-битное изображение.

0

Посмотрите, используя BitmapRegionDecoder, чтобы загрузить только части растрового изображения, которые будут видны (или будут видны в ближайшее время) в любой момент времени. См.: Using BitmapRegionDecoder to load large images