"Bitmap too large to be uploaded into a texture"

AndroidAndroid ImageviewAndroid ImageAndroid Bitmap

Android Problem Overview


I'm loading a bitmap into an ImageView, and seeing this error. I gather this limit relates to a size limit for OpenGL hardware textures (2048x2048). The image I need to load is a pinch-zoom image of about 4,000 pixels high.

I've tried turning off hardware acceleration in the manifest, but no joy.

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

Is it possible to load an image larger than 2048 pixels into an ImageView?

Android Solutions


Solution 1 - Android

This isn't a direct answer to the question (loading images >2048), but a possible solution for anyone experiencing the error.

In my case, the image was smaller than 2048 in both dimensions (1280x727 to be exact) and the issue was specifically experienced on a Galaxy Nexus. The image was in the drawable folder and none of the qualified folders. Android assumes drawables without a density qualifier are mdpi and scales them up or down for other densities, in this case scaled up 2x for xhdpi. Moving the culprit image to drawable-nodpi to prevent scaling solved the problem.

Solution 2 - Android

I have scaled down the image in this way:

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);

Solution 3 - Android

All rendering is based on OpenGL, so no you can't go over this limit (GL_MAX_TEXTURE_SIZE depends on the device, but the minimum is 2048x2048, so any image lower than 2048x2048 will fit).

With such big images, if you want to zoom in out, and in a mobile, you should setup a system similar to what you see in google maps for example. With the image split in several pieces, and several definitions.

Or you could scale down the image before displaying it (see user1352407's answer on this question).

And also, be careful to which folder you put the image into, Android can automatically scale up images. Have a look at Pilot_51's answer below on this question.

Solution 4 - Android

Instead of spending hours upon hours trying to write/debug all this downsampling code manually, why not use Picasso? It was made for dealing with bitmaps of all types and/or sizes.

I have used this single line of code to remove my "bitmap too large...." problem:

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

Solution 5 - Android

Addition of the following 2 attributes in (AndroidManifest.xml) worked for me:

android:largeHeap="true"
android:hardwareAccelerated="false"

Solution 6 - Android

Changing the image file to drawable-nodpi folder from drawable folder worked for me.

Solution 7 - Android

I used Picasso and had the same problem. image was too large at least in on size, width or height. finally I found the solution here. you can scale the large image down according to display size and also keep the aspect ratio:

    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;
}

and use this method for loading image by 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);

also for better performance you can download the image according to width and height of the display screen, not whole the image:

    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);

and then:

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

EDIT: getDisplaySize()

display.getWidth()/getHeight() is deprecated. Instead of Display use DisplayMetrics.

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

Solution 8 - Android

BitmapRegionDecoder does the trick.

You can override onDraw(Canvas canvas), start a new Thread and decode the area visible to the user.

Solution 9 - Android

As pointed by Larcho, starting from API level 10, you can use BitmapRegionDecoder to load specific regions from an image and with that, you can accomplish to show a large image in high resolution by allocating in memory just the needed regions. I've recently developed a lib that provides the visualisation of large images with touch gesture handling. The source code and samples are available here.

Solution 10 - Android

View level

You can disable hardware acceleration for an individual view at runtime with the following code:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Solution 11 - Android

I ran through same problem, here is my solution. set the width of image same as android screen width and then scales the height

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);

This is better for any size android screen. let me know if it works for you.

Solution 12 - Android

Scale down image:

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);

The image will be scaled down at the size of reqHeight and reqWidth. As I understand inSampleSize only take in a power of 2 values.

Solution 13 - Android

Use Glide library instead of directly loading into imageview

Glide : https://github.com/bumptech/glide

Glide.with(this).load(Uri.parse(filelocation))).into(img_selectPassportPic);

Solution 14 - Android

I tried all the solutions above, one-after-the-other, for quite many hours, and none seemed to work! Finally, I decided to look around for an official example concerning capturing images with Android's camera, and displaying them. The official example (here), finally gave me the only method that worked. Below I present the solution I found in that example app:

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);
}

Solution 15 - Android

NOTE FOR THOSE WHO WANT TO PUT IMAGES OF SMALL SIZE:

Pilot_51's solution (moving your images to drawable-nodpi folder) works, but has another problem: It makes images TOO SMALL on screen unless the images are resized to a very large (like 2000 x 3800) resolution to fit screen -- then it makes your app heavier.

SOLUTION: put your image files in drawable-hdpi -- It worked like a charm for me.

Solution 16 - Android

Using the correct drawable subfolder solved it for me. My solution was to put my full resolution image (1920x1200) into the drawable-xhdpi folder, instead of the drawable folder.

I also put a scaled down image (1280x800) into the drawable-hdpi folder.

These two resolutions match the 2013 and 2012 Nexus 7 tablets I'm programming. I also tested the solution on some other tablets.

Solution 17 - Android

@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);
        
    }
}

This code is work

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOllie CView Question on Stackoverflow
Solution 1 - AndroidPilot_51View Answer on Stackoverflow
Solution 2 - Androiduser1352407View Answer on Stackoverflow
Solution 3 - AndroidjptsetungView Answer on Stackoverflow
Solution 4 - AndroidPhileo99View Answer on Stackoverflow
Solution 5 - AndroidSachin LalaView Answer on Stackoverflow
Solution 6 - AndroidAsha AntonyView Answer on Stackoverflow
Solution 7 - AndroidSherryView Answer on Stackoverflow
Solution 8 - AndroidLarchoView Answer on Stackoverflow
Solution 9 - AndroiddiegocarloslimaView Answer on Stackoverflow
Solution 10 - AndroidmarvesonView Answer on Stackoverflow
Solution 11 - AndroidAbhijit GujarView Answer on Stackoverflow
Solution 12 - AndroidvtlinhView Answer on Stackoverflow
Solution 13 - Androidsaigopi.meView Answer on Stackoverflow
Solution 14 - AndroidJWLView Answer on Stackoverflow
Solution 15 - AndroidmakeasyView Answer on Stackoverflow
Solution 16 - AndroidsteveputzView Answer on Stackoverflow
Solution 17 - AndroidAlobaidiView Answer on Stackoverflow