"Растровое изображение слишком велико, чтобы быть загруженным в текстуру"

Я загружаю растровое изображение в ImageView и вижу эту ошибку. Я понимаю, что это ограничение относится к пределу размера для аппаратных текстур OpenGL (2048x2048). Изображение, которое мне нужно загрузить, - это изображение с максимальным увеличением около 4000 пикселей.

Я попытался отключить аппаратное ускорение в манифесте, но не радость.

    <application
        android:hardwareAccelerated="false"
        ....
        >

Возможно ли загрузить изображение размером более 2048 пикселей в ImageView?

Ответ 1

Все рендеринг основан на OpenGL, поэтому вы не можете преодолеть этот предел (GL_MAX_TEXTURE_SIZE зависит от устройства, но минимум 2048x2048, поэтому любое изображение ниже 2048x2048 будет соответствовать).

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

Или вы можете масштабировать изображение перед его отображением (см. user1352407 ответ по этому вопросу).

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

Ответ 2

Это не прямой ответ на вопрос (загрузка изображений > 2048), но возможное решение для любого, кто испытывает ошибку.

В моем случае изображение было меньше, чем 2048 в обоих измерениях (точнее, 1280x727), и проблема была конкретно связана с Galaxy Nexus. Изображение находилось в папке drawable и ни одной из квалифицированных папок. Android предполагает выделение без спецификатора плотности mdpi и масштабирует их вверх или вниз для других плотностей, в этом случае масштабируется 2x для xhdpi. Перемещение изображения преступника в drawable-nodpi, чтобы предотвратить масштабирование, решило проблему.

Ответ 3

Я уменьшил изображение таким образом:

ImageView iv  = (ImageView)waypointListView.findViewById(R.id.waypoint_picker_photo);
Bitmap d = new BitmapDrawable(ctx.getResources() , w.photo.getAbsolutePath()).getBitmap();
int nh = (int) ( d.getHeight() * (512.0 / d.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(d, 512, nh, true);
iv.setImageBitmap(scaled);

Ответ 4

Вместо того, чтобы тратить часы на часы, пытаясь написать/отладить весь этот код понижающей выборки вручную, почему бы не использовать Picasso? Он был создан для обработки растровых изображений всех типов и/или размеров.
Я использовал эту единственную строку кода для удаления моей "растровой слишком большой..." проблемы:

Picasso.with(context).load(resourceId).fit().centerCrop().into(imageView);

Ответ 5

Мне удалось изменить файл изображения в папку drawable-nodpi из папки drawable.

Ответ 6

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

    public Point getDisplaySize(Display display) {
    Point size = new Point();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
        display.getSize(size);
    } else {
        int width = display.getWidth();
        int height = display.getHeight();
        size = new Point(width, height);
    }

    return size;
}

и используйте этот метод для загрузки изображения Picasso:

    final Point displySize = getDisplaySize(getWindowManager().getDefaultDisplay());
        final int size = (int) Math.ceil(Math.sqrt(displySize.x * displySize.y));
        Picasso.with(this)
                .load(urlSource)
                .resize(size, size)
                .centerInside()
                .into(imageViewd);

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

    public String reviseImageUrl(final Integer displayWidth,     final Integer displayHeight,
        final String originalImageUrl) {
    final String revisedImageUrl;

    if (displayWidth == null && displayHeight == null) {
        revisedImageUrl = originalImageUrl;
    } else {
        final Uri.Builder uriBuilder = Uri.parse(originalImageUrl).buildUpon();

        if (displayWidth != null && displayWidth > 0) {
            uriBuilder.appendQueryParameter(QUERY_KEY_DISPLAY_WIDTH, String.valueOf(displayWidth));
        }

        if (displayHeight != null && displayHeight > 0) {
            uriBuilder.appendQueryParameter(QUERY_KEY_DISPLAY_HEIGHT, String.valueOf(displayHeight));
        }

        revisedImageUrl = uriBuilder.toString();
    }

    return revisedImageUrl;
}

    final String newImageUlr = reviseImageUrl(displySize.x, displySize.y, urlSource);

а затем:

    Picasso.with(this)
                .load(newImageUlr)
                .resize(size, size)
                .centerInside()
                .into(imageViewd);

EDIT: getDisplaySize()

display.getWidth()/getHeight() устарел. Вместо Display используйте DisplayMetrics.

public Point getDisplaySize(DisplayMetrics displayMetrics) {
        int width = displayMetrics.widthPixels;
        int height = displayMetrics.heightPixels;
        return new Point(width, height);
}

Ответ 7

BitmapRegionDecoder делает трюк.

Вы можете переопределить onDraw (Canvas canvas), запустить новый поток и декодировать, видны пользователю.

Ответ 8

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

Ответ 9

Для меня работали следующие два атрибута в (AndroidManifest.xml):

  • Android: largeHeap = "истинный"
  • Android: hardwareAccelerated = "ложь"

Ответ 10

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

Bitmap myBitmap = BitmapFactory.decodeFile(image.getAbsolutePath());
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Log.e("Screen width ", " "+width);
Log.e("Screen height ", " "+height);
Log.e("img width ", " "+myBitmap.getWidth());
Log.e("img height ", " "+myBitmap.getHeight());
float scaleHt =(float) width/myBitmap.getWidth();
Log.e("Scaled percent ", " "+scaleHt);
Bitmap scaled = Bitmap.createScaledBitmap(myBitmap, width, (int)(myBitmap.getWidth()*scaleHt), true);
myImage.setImageBitmap(scaled);

Это лучше для любого размера экрана Android. сообщите мне, если это сработает для вас.

Ответ 11

Уменьшить изображение:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

// Set height and width in options, does not return an image and no resource taken
BitmapFactory.decodeStream(imagefile, null, options);

int pow = 0;
while (options.outHeight >> pow > reqHeight || options.outWidth >> pow > reqWidth)
    pow += 1;
options.inSampleSize = 1 << pow; 
options.inJustDecodeBounds = false;
image = BitmapFactory.decodeStream(imagefile, null, options);

Изображение будет уменьшено с размером reqHeight и reqWidth. Как я понимаю, inSampleSize принимает только 2 значения.

Ответ 12

Спасибо всем участникам здесь, но я пробовал все решения выше, один за другим, в течение довольно многих часов, и никто не работает! Наконец, я решил осмотреть официальный пример, касающийся захвата изображений с помощью камеры Android и отображения их. Официальный пример (здесь), наконец, дал мне единственный метод, который сработал. Ниже я представляю решение, которое я нашел в этом примере приложения:

public void setThumbnailImageAndSave(final ImageView imgView, File imgFile) {

            /* There isn't enough memory to open up more than a couple camera photos */
    /* So pre-scale the target bitmap into which the file is decoded */

    /* Get the size of the ImageView */
    int targetW = imgView.getWidth();
    int targetH = imgView.getHeight();

    /* Get the size of the image */
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(imgFile.getAbsolutePath(), bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    /* Figure out which way needs to be reduced less */
    int scaleFactor = 1;
    if ((targetW > 0) || (targetH > 0)) {
        scaleFactor = Math.min(photoW/targetW, photoH/targetH);
    }

    /* Set bitmap options to scale the image decode target */
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    /* Decode the JPEG file into a Bitmap */
    Bitmap bitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath(), bmOptions);

    /* Associate the Bitmap to the ImageView */
    imgView.setImageBitmap(bitmap);
    imgView.setVisibility(View.VISIBLE);
}

Хотел бы я знать это раньше... все эти часы: D

Ответ 13

Уровень просмотра

Вы можете отключить аппаратное ускорение для отдельного представления во время выполнения с помощью следующего кода:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Ответ 14

ЗАМЕЧАНИЕ ДЛЯ ТЕХ, КОТОРЫЕ ХОТЯТ ИЗМЕНИТЬ ИЗОБРАЖЕНИЯ МАЛОГО РАЗМЕРА:

Решение Pilot_51 (перемещение ваших изображений в папку drawable-nodpi) работает, но имеет другую проблему: Он отображает изображения СЛИШКОМ МАЛЫХ на экране, если изображение не будет изменено до очень большого (например, 2000 x 3800) разрешение, чтобы оно соответствовало экрану - тогда оно делает ваше приложение более тяжелым.

РЕШЕНИЕ: поместите ваши файлы изображений в drawable-hdpi - для меня это работало как прелесть.

Ответ 15

Используя правильную подпапку drawable, она решила это для меня. Мое решение состояло в том, чтобы поместить изображение с полным разрешением (1920x1200) в папку drawable-xhdpi вместо папки drawable.

Я также поместил уменьшенное изображение (1280x800) в папку drawable-hdpi.

Эти две резолюции соответствуют планам Nexus 7 2013 и 2012, которые я программирую. Я также тестировал решение на некоторых других планшетах.

Ответ 16

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);
    ///*
    if (requestCode == PICK_FROM_FILE && resultCode == RESULT_OK && null != data){



        uri = data.getData();

        String[] prjection ={MediaStore.Images.Media.DATA};

        Cursor cursor = getContentResolver().query(uri,prjection,null,null,null);

        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(prjection[0]);

        ImagePath = cursor.getString(columnIndex);

        cursor.close();

        FixBitmap = BitmapFactory.decodeFile(ImagePath);

        ShowSelectedImage = (ImageView)findViewById(R.id.imageView);

      //  FixBitmap = new BitmapDrawable(ImagePath);
        int nh = (int) ( FixBitmap.getHeight() * (512.0 / FixBitmap.getWidth()) );
        FixBitmap = Bitmap.createScaledBitmap(FixBitmap, 512, nh, true);

       // ShowSelectedImage.setImageBitmap(BitmapFactory.decodeFile(ImagePath));

        ShowSelectedImage.setImageBitmap(FixBitmap);

    }
}

Этот код работает

Ответ 17

Я использую webview для слишком большого разрешения.

1-) Создайте отзывчивый html файл, как показано ниже.

<!DOCTYPE html>
<html>
     <head>
        <meta charset="utf-8">
        <title></title>
        <style>
        html, body, img {
          margin: 0;
          padding: 0;
          height: 100%;
          display: block;
        }
        </style>
   </head>
        <body>
              <img src="img/program_first.png">
        </body>
</html>

2-) Я использую изображение 5708x1634 в папке "img", которая очень большая по горизонтали. 3-) Добавьте "webview" ваш макет и установите нагрузку следующим образом. "program1" - это имя переменной WebView.

program1.loadUrl("file:///android_asset/program/content.html");