ImageView not displaying Bitmap on real device - android

I get an Bitmap from internal storage or from the internet. When I try to display it in a ImageView, it works on different Emulator versions but not on my Galaxy S I9000. The Bitmap simply doesn't show up.
protected void onPostExecute (Bitmap bmp) {
progressBar.setVisibility(View.INVISIBLE);
if (bmp != null) {
imageView.setImageBitmap(bmp);
imageView.setVisibility(View.VISIBLE);
}
}

This is highly likely to be an underlying issue with openGL not accepting textures larger than 2400x2400. It doesn't cause crashes, but fails by not displaying the Bitmap in an ImageView.
You should always ensure that the Bitmap is smaller than 2400 in both dimensions and resize it before setting it on your view if it is larger.

I used this method to help me in displaying the image
public static Drawable ToDrawable(Resources r, byte[] encodedString)
{
if (encodedString == null)
return null;
Bitmap bmp = BitmapFactory.decodeByteArray(encodedString, 0, encodedString.length);
Drawable drawable = new BitmapDrawable(r, bmp);
// bmp.recycle();
return drawable;
}

Related

How to get bitmap from NetworkImageView?

In my project I used (Volley + NetworkImageView) to download some images and texts and showing them in a list view.. till here, I don't have any problem.
Now, I want to get bitmaps form NetworkImageView and I tried many methods like the following, but non of them worked for me.
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
Another method:
imageView.buildDrawingCache();
Bitmap bmap = imageView.getDrawingCache();
Non of them worked..
Any Help is appreciated,,
You cannot get the Bitmap reference as it is never saved in the ImageView.
however you can get it using :
((BitmapDrawable)this.getDrawable()).getBitmap();
beacuse when you set it with Volley u do this:
/**
* Sets a Bitmap as the content of this ImageView.
*
* #param bm The bitmap to set
*/
#android.view.RemotableViewMethod
public void setImageBitmap(Bitmap bm) {
// Hacky fix to force setImageDrawable to do a full setImageDrawable
// instead of doing an object reference comparison
mDrawable = null;
if (mRecycleableBitmapDrawable == null) {
mRecycleableBitmapDrawable = new ImageViewBitmapDrawable(
mContext.getResources(), bm);
} else {
mRecycleableBitmapDrawable.setBitmap(bm);
}
setImageDrawable(mRecycleableBitmapDrawable);
}
however if you set your default image or error image or any other image in any other way you may not get BitmapDrawable but NinePatchDrawable for example.
here is how to check:
Drawable dd = image.getDrawable();
if(BitmapDrawable.class.isAssignableFrom(dd.getClass())) {
//good one
Bitmap bb = ((BitmapDrawable)dd).getBitmap();
} else {
//cannot get that one
}

Why am I getting "Cannot draw recycled bitmaps"?

I am taking a bitmap, creating a new one from the original and then setting the new one to an ImageView, when I recycle the original I get that error, but I am not drawing the original? For more detail read my comments in my code. As you can see I recycle the bitmap that comes in which I do not draw, I always make a new bitmap called tile that I draw.
My Code:
public void tileImage(Bitmap bm){
if(bm==null){
Debug.out("Bitmap is null");
}
else{
Bitmap tile;
float tileWidth = bm.getWidth();
float tileHeight =1024;
//if my bitmap is too wide
if(bm.getWidth()>width){
Debug.out("Bitmap too wide: "+bm.getWidth());
//if this code runs I get no error, if not I get the error
bm = Bitmap.createScaledBitmap(bm,
(int)width,
(int)(bm.getHeight()*(float)(width/tileWidth)),
false
);
}
Debug.out("Bitmap height: "+bm.getHeight()+" adjusted width "+bm.getWidth());
//if my bitmap is too tall
if(bm.getHeight()>tileHeight){
for(int i = 0; tileHeight*i<bm.getHeight(); i++){
image = new ImageView(main);
//make tiles of the body
if((tileHeight*(i+1))<bm.getHeight()){
tile = Bitmap.createBitmap(
bm,
0,
(int)(tileHeight*i),
(int)bm.getWidth(),
(int)(tileHeight)
);
Debug.out("Tiling: "+i);
}
//tile the reaminder
else{
tile = Bitmap.createBitmap(
bm,
0,
(int)(tileHeight*i),
(int)bm.getWidth(),
(int)(bm.getHeight()%tileHeight)
);
Debug.out("Tiling: "+bm.getHeight()%tileHeight+" "+i);
}
image.setImageBitmap(tile);
tiles.addView(image);
}
}
//else its not too tall
else{
image = new ImageView(main);
Debug.out("No tiling");
tile = Bitmap.createBitmap(
bm,
0,
0,
(int)bm.getWidth(),
(int)bm.getHeight()
);
Debug.out("Bitmap too small height: "+bm.getHeight()+" width "+bm.getWidth());
image.setImageBitmap(tile);
tiles.addView(image);
}
}
//this is the trouble maker
bm.recycle();
}
Bitmap.createBitmap(params) Returns an immutable bitmap from the specified subset of the source bitmap. The new bitmap may be the same object as source, or a copy may have been made.
bitmap.recycle() method Frees the native object associated with this bitmap, and clear the reference to the pixel data. This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap.
onDraw() method takes some time to inflate the View. If you are passing the bitmap to draw a view and calling recycle() on the same reference then the bitmap is marked as "dead", meaning it will throw an exception if getPixels() or setPixels() is called, and will draw nothing.
You should call recycle() in onDestroy().
My Code:
public class MainActivity extends Activity {
private Bitmap mBitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView image1 = (ImageView) findViewById(R.id.image1);
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
image1.setImageBitmap(mBitmap);
tileImage();
}
private void tileImage() {
ImageView image2 = (ImageView) findViewById(R.id.image2);
Bitmap bm = Bitmap.createBitmap(mBitmap, 0, 0,
(int) mBitmap.getWidth(), (int) mBitmap.getHeight());
image2.setImageBitmap(bm);
}
#Override
protected void onDestroy() {
mBitmap.recycle();
super.onDestroy();
}
}
The answer above is not entirely correct. You should in fact not wait until onDestroy with recycle. Especially if you make heavy use of creating these bitmaps. You might not even get to onDestroy before you get an OOM error. What you should do is test the dimensions you're scaling it to to the dimensions of the bitmap. If they are equal, return the original bitmap and no recycle is necessary. Otherwise, you'll get a new bitmap object and you should immediately call recyle on the original bitmap.
see http://developer.android.com/training/displaying-bitmaps/manage-memory.html

Deletion of drawing cache

In my app I want to swap images at runtime when user clicks on it.
there are two imageviews when user click on first image and then click on second image at the same time I'm fetching bitmap of first imageview's image and assigning to second imageview for this I used following code:
public Bitmap createBitmap(ImageView imageview) {
imageview.setDrawingCacheEnabled(true);
imageview.buildDrawingCache(false);
if(imageview.getDrawingCache() != null) {
Bitmap bitmap = Bitmap.createBitmap(imageview.getDrawingCache());
imageview.setDrawingCacheEnabled(false);
return bitmap;
} else {
return null;
}
}
Code is working fine but the cache not cleared every time and the bitmap created with previous cache so how I can clear a bitmap cache?
This is a sample e.g. where i use to Free the native object associated with this bitmap.
Bitmap bitmap;
public Bitmap createBitmap(ImageView imageview) {
if (bitmap != null) {
bitmap.recycle();
bitmap = null;
}
bitmap = Bitmap.createBitmap(imageview.getDrawingCache());
// Your Code of bitmap Follows here
}
Before use of Bitmap just free the object.
use bitmap.recycle(); before valuating your bitmaps to clear their cache before recreating it.

OutOfMemoryError when displaying contacts' photos in Android (bitmap size exceeds VM budget)

I use the following function to retrieve a contact's photo in Android where the person's lookup key is given:
public Bitmap getContactPhoto(String lookup_key) {
Uri lookUpUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookup_key);
Uri contentUri = ContactsContract.Contacts.lookupContact(ctx.getContentResolver(), lookUpUri);
InputStream stream = null;
try {
stream = ContactsContract.Contacts.openContactPhotoInputStream(ctx.getContentResolver(), contentUri);
}
catch (Exception e) {
}
if (stream != null) {
return BitmapFactory.decodeStream(stream, null, bitmapOptions);
}
else {
return null;
}
}
When I display those contact photos in a list view, I sometimes read the following error in the developer console's crash reports:
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=6023KB, Allocated=3002KB, Bitmap Size=27152KB)
Does this mean that my app may use about 3MB of heap but a single bitmap had roughly 27MB?
I read a lot of questions here on Stack Overflow concerning OutOfMemory error but it was mainly about:
leaking contexts so that the garbage collector cannot free the resources
huge bitmaps that need to be scaled
But how can I prevent the error in my case? Since I only get the contacts' photos, I don't know if I have huge bitmaps that must be scaled. And leaking a context doesn't seem to be the case here.
This is how the images are displayed:
imageView.setVisibility(View.VISIBLE);
imageView.setBackgroundResource(R.drawable.background);
if (<BITMAP_OBJECT> != null) {
imageView.setImageBitmap(<BITMAP_OBJECT>);
}
else {
imageView.setImageBitmap(null);
}
When you are setting your Bitmap to an ImageView, try doing this:
Bitmap oldBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
imageView.setImageDrawable(null);
oldBitmap.recycle();
imageView.setImageBitmap(newBitmap);
It may not complete get rid of the problem, but it certainly makes it happen much more rarely.
Have you tried scaling your bitmap? Here is how you do it...
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile( filename, options );
options.inJustDecodeBounds = false;
options.inSampleSize = 2; // adjust sample size to whatever you want it to be
bitmap = BitmapFactory.decodeFile( filename, options );
if ( bitmap != null && exact ) {
bitmap = Bitmap.createScaledBitmap( bitmap, width, height, false );
}
Here in the method BitmapFactory.decodeFile, I create a scaled Bitmap so that it consumes lesser memory than it did before, it solved my problem, what about yours?

Bizarre ImageView Bitmap Handling

I've encountered totally bizarre behavior in the way Android loads bitmaps into ImageView. For example, I have a 500x313 image file called urimg_01.jpg. With this code:
img.setImageResource(R.drawable.urimg_01);
Bitmap bitmap = ((BitmapDrawable) img.getDrawable()).getBitmap();
Log.v(TAG,"---------------------> bitmap width = "+bitmap.getWidth());
Log.v(TAG,"---------------------> bitmap height = "+bitmap.getHeight());
the ImageView bitmap is 750x470. (I have a Nexus S with 480x800 display.)
With this code, which reads a copy of the same file located in getFilesDir():
Log.v(TAG,"image file is "+filelist[0].getAbsolutePath());
FileInputStream fis = new FileInputStream(filelist[0]);
FileDescriptor fd = fis.getFD();
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);
if (bitmap != null) {
Log.v(TAG,"---------------------> bitmap width = "+bitmap.getWidth());
Log.v(TAG,"---------------------> bitmap height = "+bitmap.getHeight());
img.setImageBitmap(bitmap);
fis.close();
}
the ImageView bitmap is 500x313, as expected.
In the case of setImageResource(), where the devil is it getting 750x470 from?? And how do I get it to use the correct dimensions for resources in drawable?
Your resource is being scaled up because it's probably stored in a medium density folder and you're using a high density device. See Bitmap getWidth returns wrong value for details.
here you get your bitmap
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);
now scale it according to device height and width
Display display=this.getWindowManager().getDefaultDisplay();
int w=display.getWidth();
int h=display.getHeight();
Bitmap newBitmap=Bitmap.createScaledBitmap(oldBitmap, w, h, false);
//now setImage to background with new Bitmap
One important thing "this" should be activity context
:) cheers

Categories

Resources