Bitmap.copy failing where createScaledBitmap works - android

I'm having a problem with the Bitmap.copy function. This code works okay,
Bitmap tempBM = Bitmap.createScaledBitmap(sourceBitmap, sourceBitmap.getWidth(), sourceBitmap.getHeight(), false);
//Ensure that the bitmap is mutable and not copied from the original in the case where no scaling is required
m_bwBitmap = tempBM.copy(tempBM.getConfig(), true);
if (tempBM!=sourceBitmap)
{
tempBM.recycle();
}
But this doesn't...
m_bwBitmap = sourceBitmap.copy(sourceBitmap.getConfig(), true);
sourceBitmap starts as immutable and I want m_bwBitmap to be mutable.
It doesn't crash as such but it does break the debugger as if something has gone wrong in the android function somewhere. The application then crashes later on. If I replace it with the top code, everything works fine.
However, I have now started getting crash reports from JellyBean, throwing a null pointer exception on the line with the tempBM.copy on it. So, I have to sort this out but currently the top code is the only source that will work at all. I'm testing it on an Android 4.0 device.
Any ideas?

Okay, I think I have answered this (well at least halfway anyway).
It is something to do with the Bitmap.Config. If I change the line to
m_bwBitmap = sourceBitmap.copy(Bitmap.Config.ARGB_8888, true);
then it works fine.
Note, the original source bitmap comes from a line like this...
Bitmap sourceBitmap = BitmapFactory.decodeFile(pictureFile);
pictureFile is a GIF.
However, I don't really know why decodeFile is producing something with a seemingly invalid Config. If I check the config of sourceBitmap, it returns null ?!?

Related

Android WallpaperManager.setBitmap(Bitmap bitmap) sometimes sets the default wallpaper

I am using WallpaperManager.setBitmap to set the device's wallpaper.
I have the permissions set correctly. It works fine for 99% of the times however sometimes it simply sets the default instead of mine.
There is no exception (I have try-catch and I have logs. No exception. No crashes. Nothing).
The method is void so there is also nothing to check after calling it.
It is just being called and instead of setting the given bitmap - it sets the default.
http://developer.android.com/reference/android/app/WallpaperManager.html#setBitmap(android.graphics.Bitmap)
Here's the code:
WallpaperManager.getInstance(context).setBitmap(bitmap);
The bitmap is not recycled (I am checking for it before reaching this line of code).
Any ideas what can go wrong or what alternative to use?
Using a resource is not an option as the bitmap is dynamically generated in memory.
The generated bitmap size, in my device's case (Nexus 5) is always the same: 2160x1920, regardless the successful or failure results.
Also - it is a PNG.
I will meanwhile run some tests with setStream instead:
http://developer.android.com/reference/android/app/WallpaperManager.html#setStream(java.io.InputStream)
Hopefully it works better ...
Try this method instead, to directly reference the bitmap as a drawable resource:
WallpaperManager.getInstance(context).setResource(R.drawable.myImageId);
The method call assumes your bitmap is in a drawable resource folder (and not e.g. assets).
See API docs for more details.

Skewed images in ImageView on Android 4.1.2

I have an app that displays an image in an ImageView, and am experiencing problem specifically for Android 4.1.2. It is confirmed to not work on three separate 4.1.2 devices, while working on 2.3.7, 4.2.1, 4.3 and 4.4.2. The error occurs for several different images, but not all. There seems to be something about some specific JPEG-files that doesn't work as intended.
How it actually looks, and how it shows on Android 4.1.2:
The above image (left) is one such problematic image file.
A summary of the code behind setting the displayed image is:
Bitmap bitmap, background;
ImageView imageView = (ImageView)findViewById(R.id.imageView);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inPurgeable = true;
options.inInputShareable = true;
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dog, options);
background = bitmap.copy(Bitmap.Config.RGB_565, true);
Canvas canvas = new Canvas(background);
canvas.drawBitmap(bitmap, 0, 0, null);
// Some calls to canvas.drawText(....) here, but doesn't have to happen for the error to occur
imageView.setImageBitmap(background);
I've figured that I am able to resize and re-save the above photo in Photoshop to make it work, without knowing why. Since I have several I'd prefer not having to do so.
I am wondering what is the source of this error on Android 4.1.2, and if there might be some programmatic way of fixing it?
I've tried my luck on Google view "skewed", "tilted", "distorted" and similar, but there are very few mentions of it and no fixes. This is the mention with screenshot I've found:
Anyone else getting distorted album art in Play Music? (Screenshot)
Based on the comment of rupps I changed from:
bitmap.copy(Bitmap.Config.RGB_565, true)
To:
bitmap.copy(Bitmap.Config.ARGB_8888, true)
This did in fact solve the problem for 4.1.2 devices, while remaining similar in functionality for all other tested devices. This does programatically solve my issue. Note however that it does require double the memory, as each pixel is stored on 4 bytes instead of 2 bytes.
As for the source of the problem, I read from the documentation of RGB_565 that:
This configuration can produce slight visual artifacts depending on the configuration of the source.
I think this mostly relates to banding/color/dithering issues and this does not explain the version specific problem, but perhaps why this setting is troublesome.

Android: Rotating large image crashes without throwing an error

I have searched and found simple code to rotate an image. I am pulling the image out of an ImageView object into a bitmap, rotating it then putting it back. I realize this is not the most effective method but I don't think it should crash without giving an error message in the CATCH block.
Here is my code. The only value passed in is "r" or "l" depending on which direction I want to rotate. Smaler images (1500x1500 or smaller) work just fine. Things go bad around the 2500x2500 size.
public void rotate(String dir)
{
try
{
float angle = (dir.equals("r") ? 90 : -90);
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
Matrix matrix = new Matrix();
matrix.reset();
matrix.postRotate(angle);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
imageView.setImageBitmap(bitmap);
}
catch(Exception e)
{
Utilities.logError(e.toString());
}
}
Any clue as to why it is crashing and why it doesn't thow an exception? I just get a message "Unfortuantly process .... has stopped" and I get kicked back to the welcome screen of my app.
Oh, for kicks I set the angle to ZERO (hard coded) and it didn't crash. I suspect that it is just taking too long to rotate and Android is having a fit. But I am not sure how to confirm that as the problem or how to tell Android to wait a little longer.
Even if I reduce the preview image for the rotation, when I go to save I will have to rotate the full size image at least once and will hit this same issue. Won't I?
I can more or less guarantee without looking at the logs that you're getting an Out Of Memory Exception.
You need to use smaller images, or use a different method to rotate that doesn't use up so much memory (you're allocating 2 2500x2500 bitmaps at the same time here! that's tons!).
Try using a RotateAnimation to get your effect instead.
Hope this helps :)

getDrawingCache return null when run monkey

I have the follow code to get the screenshot
View screen = getWindow().getDecorView();
screen.setDrawingCacheEnabled(true);
screen.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
screen.buildDrawingCache();
Bitmap bitmap = screen.getDrawingCache();
The code is in onOptionsItemSelected in UI thread.
It runs fine when I test it manually. However, when I run the app with monkey, bitmap is nullI am not sure if it always null in monkey mode or just occasionally since monkey's randomness.
Any ideas that why monkey could behave differently? I do not want to blindly add a null pointer checker in later code.
Thanks
you should use buildDrawingCache(true) because buildDrawingCache() is same as buildDrawingCache(false).Make sure to copy bitmap to another one before using getDrawingCache() like below.
Bitmap bt=Bitmap.createBitmap(screen.getDrawingCache());
because its copy our bitmap before recycle() if you call setDrawingCacheEnabled(false).

Android Bitmap too heavy error

I have the following problem that some of you must know on my android app :
3288-byte external allocation too large for this process.
Out of memory: Heap Size=5959KB, Allocated=3922KB, Bitmap Size=18614KB
VM won't let us allocate 3288 bytes
Facts :
I'm creating a bitmap of the screen (so quite huge) and I manipulate it (changing size etc ...) for doing a flipping page animation.
It crashes only on a desire HTC : on galaxy s2 and kindle fire, no problems.
I'm already desallocating the current Bitmap everytime I create a new one with the following code :
Bitmap old = this.bitmap;
this.bitmap = bitmap;
this.invalidate();
if(old != null)
old.recycle();
I also tryied to call this function :
public void recycle() {
if (this.bitmap!=null)
this.bitmap.recycle();
System.gc();
Runtime.getRuntime().gc();
}
Severals time in my code, and sometimes it gets slightly better (like it crashes a little later), but that's still not good.
I spent a lot of time on this problem, and I don't really get how to fix it. It's like on forum there is a lot of misinformation, so I'm kinda lost.
Thanks, ask for more precision.
Edit :
Here is a code called a lot :
//set the foreground image with the current day
Bitmap b = Bitmap.createBitmap(visibleLayout.getWidth(), visibleLayout.getHeight(),Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
visibleLayout.draw(c);
viewBitmapNext.setBitmap(b);
viewBitmapNext.setVisibility(View.VISIBLE);
Where viewBitmapNext is an overwritted element of the View class. The setBitmap function is described above.
About the resizement, I do this line of code :
viewBitmapPrevious.setLayoutParams(new RelativeLayout.LayoutParams((int) (iterator - ((totalWidth - iterator) - activity.getResources().getDimension(R.dimen.margin_right))/2), RelativeLayout.LayoutParams.WRAP_CONTENT));
Again, tell me if you you want to know more.
I found out what was the problem. It will not be interresting for anyone, because it's a dumb error closely related to my project, but I say it anyway.
I actually had 2 errors :
one loop creating elements infinitly.
Two big pictures I put as a background after a certain action performed on a cheap phone ( I'm still on it but it should be easy to solve). I'll edit this answer when it's done.
To everyone that helped me, you couldn't find out the problem's solution (wasn't related to the bitmap-screen I do), but still it was helpful on it's way.
Thanks.

Categories

Resources