I'm currently working on an application which requires users to upload a photo to the app from their gallery.
I've looked at a number of solutions including coming up with my own. However, I can't figure out why the ImageView, taking in the final Bitmap is blurred & the edges are jaggered.
As an example, I'm currently using this SO post (the marked answer): Quality problems when resizing an image at runtime
to work with.
The photo I'm testing on is taken on my LG G3, so the quality is pretty crisp.. if that helps.
I've had the same problem a few month ago. May be this this is the answer that you aro looking for. Give a try:
BitmapFactory.Options op = new BitmapFactory.Options();
op.inScaled = false;
Bitmap a = BitmapFactory.decodeFile(imgPath.getAbsolutePath(), op);
Related
I am developing a live wallpaper that reproduces an animation (like a short video) on background.
Does anyone know how to efficiently load various full screen size bitmaps and draw them on canvas?
I have tried 2 approaches and both are not very good.
Approach #1:
Load all bitmaps on wallpaper startup.
Problem: Memory excess limit (about 35MB) cant load more than 10 bitmaps. So animations lack of different images.
Approach #2:
Load only 2 bitmaps. On run time, paint bitmap, delete old bitmap, load new bitmap, repeat.
Problem: Consumes a lot of the system, (not memory, but slows down os in general), however it works because it doesn't exceed memory limit. But still, slows down the entire system.
example:
Drawer.drawAll(res,c,p);
res.removeOldBitmaps();
res.loadNewBitmaps(wpservice,display);
A different approach i thought about is load resource on a separete thread, what do you guys think of that? do you have any other solutions?
Cheers!
Solved, the solution I found was the following:
Load images on runtime, 1 by 1.
And use this options:
/**Effective image decoder by chelin**/
public static Bitmap decodeResource(WallpaperService wpservice,int id){
int scale=1;
Resources res = wpservice.getResources();
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inPreferredConfig = Bitmap.Config.ARGB_8888;
o2.inSampleSize=scale;
o2.inPurgeable = true;
o2.inInputShareable = true;
return BitmapFactory.decodeResource(res, id, o2);
}
Hope it works as it worked for me. Cheers!
This might sound like a strange/silly question. But hear me out.
Android applications are, at least on the T-Mobile G1, limited to 16
MB of heap.
And it takes 4 bytes per pixel to store an image (in Bitmap form):
public void onPictureTaken(byte[] _data, Camera _camera) {
Bitmap temp = BitmapFactory.decodeByteArray(_data, 0, _data.length);
}
So 1 image, at 6 Megapixels takes up 24MB of heap. (Cue Memory overflow).
Now I am very much aware of the ability to decode with parameters, to effectively reduce the size of the image. I even have a method which will scale it down to a desired size.
But what about in the scenario when I want to use the camera as a quality camera!
I have no idea how to get this image into the database. As soon as I decode, it errors.
Note: I need(?) to convert it to Bitmap so that I can rotate it before storing it.
So to sum it up:
Limited to 16MB of heap
Image takes up 24MB of heap
Not enough space to take and manipulate an image
This doesnt address the problem, but I Recommend it as a starting point for others who are just loading images from a location:
Displaying Bitmaps on android
I can only think of a couple of things that might help, none of them are optimal
Do your rotations server side
Store the data from the capture directly to the SDCARD without decoding it, then rotate it chunk by chunk using the file system, then send that to your DB. Lots of examples on the web (if your angles are simple, 90 180 etc) though this would be time consuming since IO operations against SDCARD's are not exactly fast.
When you decode drop the alpha channel, this may not solve you issue though and if you are using a matrix to rotate the image then you would need a target/source anyway
Options opt = new Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
// Decode the raw camera a bitmap with no alpha channel
bmp = BitmapFactory.decodeByteArray(raw, 0,raw.length, opt);
There may be a better way to do this, but since your device is so limited in heap etc. I can't think of any.
It would be nice if there was an optional file based matrix method (which in general is what I am suggesting as option 2) or some kind of "paging" system for Android but that's the best I can come up.
First save it to the filesystem, do your operations with the file from the filesystem...
I have this working just fine in our iPhone app, but am having problems in Android. I'm using the same urls/data in both apps. When I set my image in my ListView to the bitmap that came from the bytes, the image doesn't appear. The data is there. Here is the code where I assign the view:
if (camera.snapshot != null)
{
bMap = BitmapFactory.decodeByteArray(camera.snapshot, 0, camera.snapshot.length);
image.setImageBitmap(bMap);
}
This is where I convert the string data into bytes:
camera.snapshot = responseData.getBytes();
The images are PNG files. They come in about 4 times the size that I need them for the listview image but I would think they would size perfectly to the bounds I set the ImageView to be.
On iPhone I simply use NSData and then use a prebuilt method in ImageView to turn it into an image. It works perfectly! What am I missing here?
You probably need to use the 4-argument version of decodeByteArray: see http://developer.android.com/reference/android/graphics/BitmapFactory.html#decodeByteArray%28byte[],%20int,%20int,%20android.graphics.BitmapFactory.Options%29.
The options would depend on the type of PNG image, so that you might need to experiment with. For a generic PNG, maybe something like this?
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inDither = true;
opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
You can see http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html and http://developer.android.com/reference/android/graphics/Bitmap.Config.html for more detail.
Everything is fine here. So you need to debug to try and find where else is the issue. i.e. is Camera.snapshot = null ? i.e. you might not be getting the data properly. Or there could also be an issue in the layouts to show the imageview. Try setting a predefined image to imageview and see if it is shown. This way you would be able to track the problem.
Hey,
i wrote a small application, a client application which receives images from a server, and then display them on a rotating cube using openGL ES.
this works just fine in the emulator, but on real phone SGS , blank white images displayed instead.
what could be the problem ???
the photos are saved using
fos = openFileOutput(i+".jpg",MODE_WORLD_READABLE);
and then read and converted to Bitmap using
File myImage= context.getFilesDir();
String imgPath=myImage.getAbsolutePath();
BitmapDrawable bmd = new BitmapDrawable(imgPath+"/"+face+".jpg");
bitmap[face]= bmd.getBitmap();
The Rendering Code used is same as supposed in Example 6a: Photo-Cube , under MYGLRenderer.java
Thanks in Advance.
This sounds somewhat similar situation I faced some time ago. Reason was that I didn't resize Bitmap to size of power of two before sending it to GL context.
https://gamedev.stackexchange.com/questions/10829/loading-png-textures-for-use-in-android-opengl-es1
I read many discussions about the inSampleSize OutOfMemory dilemma.
Cannot get a good solution so i ask a question about it.
Im currently loading a bitmap with inSampleSize=4.
That will give me a Bitmap with the size 648x388.
Original On disk size is 2592x1592.
Im writing text on 648x388 bitmap and saving it back to disk.
Im writing on the 648x388 because the 2592x1592 give me OutOfMemory .
The way it works is that there can be 1-10 648x388 Bitmaps to be saved in a while loop.
I want to change this loop to save 1-10 2592x1592 Bitmaps.
How can i securely load the 2592x1592?
I don care about the resolution going down 60% or more.
As long as the Bitmap has the same size 2592x1592.
Is there a way to maybe keep the size but make Bitmap thinner,
removing color without making quality bad.
My first thought was going something like this to get the biggest bitmap i could get:
I have not tested this but get a feeling it's a bad way
boolean work = true;
int insample = 2;
BitmapFactory.Options options = new BitmapFactory.Options();
while(work){
try{
options.inSampleSize = insample;
bitmap = BitmapFactory.decodeFile(filePath,options);
work = false;
}catch(Exception e){
insample++;
}
}
any help would be grate.
Image processing requires a lot of memory. you cant use the whole bitmap and just modify it on your phone. use a web service for that. upload, process, download. sorry there is no other way a decoded bitmap just takes a lot of memory.
And by the way you cant catch an outOFMemory Exception. the app just crashes.
There's a hard limit on process size in Android and a 4 mega-pixel image at four bytes a pixel will hit it all by itself (on many devices), without any room for your program.
I think you are going to need to do one of two things: Create a web service to do the image processing on a server/in the cloud; or learn to do your image processing "on-the-fly" by manipulating the data directly instead of using a bitmap.