during a couple of days i've been looking here and on the Internet in many post for a solution on an issue im having loading or moving a large jpg image (located as a drawable reource by now) and I think it's time to ask myself altought there are many questions and solutions very related.
I'm developing a 3D terrain simulation with OpenGL and the problem is that I'm using as terrain texture a quite large jpg image ( 2048x2048 = 1,94 MB ).
Let's look at some workarround I Did:
1st:
Bitmap terrainBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.terrain, options);
This one crashes inmediately, probably because the image is too big
2nd:
Uri path = Uri.parse("android.resource://com.jgc.my_app/" + R.drawable.terrain);
URL ulrn;ulrn = new URL(path.getPath());
HttpURLConnection con = (HttpURLConnection)ulrn.openConnection();
InputStream is = con.getInputStream();
Bitmap bmp = BitmapFactory.decodeStream(is);
that one probably was a quite silly attempt
3rd:
Bitmap terrainBitmap = BitmapFactory.decodeFile("android.resource://com.jgc.my_app/terrain.jpg", options);
but I'm getting a very frustrating null bitmap as result...
Other workarrounds in mind are, as the drawable resources are "inside" the application, why not to move them to the sd card and decodefile form there, but, the solutions given to move a bitmap or a drawable to the sdcard that I've found always user BitmapFactory.decodeResource(getResources(), R.drawable.terrain, options);
I appreciate any suggestion, since then I'll be working arround other tasks in my proyect.
Thanks in advance
Ok, maybe I've been lucky, here is the n work-arround ind this workd for me:
private static BitmapFactory.Options terrainBitmapOptions = new BitmapFactory.Options();
...
// Set our bitmaps to 16-bit, 565 format.
terrainBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
...
InputStream is = getResources().openRawResource(R.drawable.terrain);
Bitmap terrainBitmap;
try {
terrainBitmap = BitmapFactory.decodeStream(is, null, terrainBitmapOptions);
} finally {
try {
is.close();
} catch (IOException e) {
// Ignore.
}
}
I hope it helps anyone else...
Related
I use the folowing to get a bitmap from my device and display it in a listview
pic1="Harris1.jpg"
pic2="Harris2.jpg"
pic3="Harris3.jpg"
Bitmap bmp = BitmapFactory.decodeFile("/storage/emulated/0/Pictures/" + pic1);
Bitmap bmp1 = BitmapFactory.decodeFile("/storage/emulated/0/Pictures/" + pic2);
Bitmap bmp2 = BitmapFactory.decodeFile("/storage/emulated/0/Pictures/" + pic3);
Bitmap[] image={bmp,bmp1,bmp2};
for(int i=0;i<text1.length;i++)
{
item_details.setImage(image[i]);
}
this works fine but is there a way to buildup the Bitmap {} image without having to put a line for each = BitmapFactory.decodeFile?
I want to be able to read the filenames from a database which I can do but sometimes there are just 3 pictures but other times here may by 50 and I want to be able for the routine to do the {bmp,bmp1,bmp2 etc...} automatically
Any ideas?
Your help appreciated
Mark
Based on your code sample. Using the String.format method is the simplest way to achieve your goal.
String picFormat="Harris%d.jpg";
for(int i=0;i<text1.length;i++)
{
String pic = String.format(picFormat, i+1);
Bitmap bmp = BitmapFactory.decodeFile("/storage/emulated/0/Pictures/" + pic);
item_details.setImage(bmp);
}
I am currently work on a magazine like apps. Since there is an option to zoom in(150%, 200%, 250% of original source) , I would prefer not to scale down the image. However , the app will force restart when I try to decode the image because of the out of memory. Are there any suggestion to fix that?
The image are local (SD card) , can be retrieve in any approach, but eventually need to be a bitmap as I use something like cavans.drawbitmap to display it. I tried, input stream-> bytes , input stream->bitmap etc... but are there any most efficient way or at least
I can sure the app does not force restart / close? Thanks
try {
InputStream is = (InputStream) new URL(url).getContent();
try {
return BitmapFactory.decodeStream(is);
} finally {
is.close();
}
} catch (Exception e) {
return BitmapFactory.decodeResource(context.getResources(), defaultDrawable);
}
You should consider using nostra's image loader, it deals with memory quite efficiently, you can specify lots of config stuffs, im using it and its working pretty well for large images aswell
This is what smartImageView(by loopj - you can find him on http://loopj.com/) uses to retrieve files from the drive/sd.
private Bitmap getBitmapFromDisk(String imgID) {
Bitmap bitmap = null;
if(diskCacheEnabled){
String filePath = getFilePath(imgID);
File file = new File(filePath);
if(file.exists()) {
bitmap = BitmapFactory.decodeFile(filePath);
}
}
return bitmap;
}
In my application i have to show list of videos,i have created image(thumb) from video and show that image in list.
I added code that i was used for create thumb-
Bitmap bitmap=ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.FULL_SCREEN_KIND);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
My problem is that when i run app on android api level below 4.0 thumb is generate but when i run same application on android 4.0 and above ThumbnailUtils.createVideoThumbnail() method returns null.
Please help me how to fix this issue.
Working from yesterday but still not getting solution.I have tried -
Bitmap bitmap=ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
and
Bitmap bitmap=ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MICRO_KIND);
but still returning null.
Thanks in advance.
createVideoThumbnail(String filePath, int kind) supports MINI_KIND or MICRO_KIND as kind only.
see http://developer.android.com/reference/android/media/ThumbnailUtils.html.
try one of those...
regards
note: May return null if the video is corrupt or the format is not supported.
You can use the following function to get a bitmap from a video URL.
public Bitmap retriveVideoFrameFromVideo(String videoPath){
Bitmap bitmap = null;
MediaMetadataRetriever mediaMetadataRetriever = null;
try {
mediaMetadataRetriever = new MediaMetadataRetriever();
if (Build.VERSION.SDK_INT >= 14)
// no headers included
mediaMetadataRetriever.setDataSource(videoPath, new HashMap<String, String>());
else
mediaMetadataRetriever.setDataSource(videoPath);
bitmap = mediaMetadataRetriever.getFrameAtTime();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mediaMetadataRetriever != null)
mediaMetadataRetriever.release();
}
return bitmap;
}
Some devices can't play and can't create thumbnails for videos, that placed on internal memory.
Check it, and move your video to SD Card before thumbnails creating.
Here is my solution to fix this problem-
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(filePath,
MediaStore.Images.Thumbnails.MINI_KIND);
Hope this will fix your problem.
If your video located on the external storage requires permission in manifest
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
There's a 2MB limit on the server where I need to upload an image.
I'm using this method to downsample a Bitmap Strange out of memory issue while loading an image to a Bitmap object
within this method
public InputStream getPhotoStream(int imageSizeBytes) throws IOException {
int targetLength = 1500;
ByteArrayOutputStream photoStream;
byte[] photo;
Bitmap pic;
final int MAX_QUALITY = 100;
int actualSize = -1;
do {
photo = null;
pic = null;
photoStream = null;
//this calls the downsampling method
pic = getPhoto(targetLength);
photoStream = new ByteArrayOutputStream();
pic.compress(CompressFormat.JPEG, MAX_QUALITY, photoStream);
photo = photoStream.toByteArray();
actualSize = photo.length;
targetLength /= 2;
} while (actualSize > imageSizeBytes);
return new ByteArrayInputStream(photo);
}
This throws OutOfMemoryError on the second iteration. How could I downsample the image below a certain size limit?
I think the problem is happening because you are compressing the image to a in memory representation, you need to free up that memory before you try to compress again.
You need call close() in the photoStream before trying again in order to free up resources.
Also toByteArray() makes a copy of the stream in memory that you have to free up later, why don't you just use the photoStream.size() to check for the file size?
I can post some code if you need.
Instead of this:
pic = null;
Do this:
if (pic!=null)
pic.recycle();
pic = null
If you simply set the bitmap object to null the memory it occupied isn't released immediately. In the second case you are explicitly telling the OS you are done with the bitmap and its okay to release its memory.
Also consider using a compression quality of 90 instead of 100, I believe that will reduce the resulting file size quite a bit.
I am downloading a bitmap from a website and then displaying it in my application. Whenever I download this image and set it into an ImageView, there is always a lot of extra space above or below the actual image. This extra space is part of the ImageView and is only there after I set the ImageBitmap to the downloaded bitmap.
So, this is making me think that the extra space is somehow part of the bitmap.
However, when I download the same image in a Webview, there is no extra space.
If you have any ideas on why this could be happening, please let me know! Let me know if you need any more information, thanks.
Edit: Here's my code getting the bitmap:
InputStream in = null;
Message msg = Message.obtain();
msg.what = 1;
try{
in = openHttpConnection(_url);
if (in != null)
{
Bitmap bit = BitmapFactory.decodeStream(in);
Bundle b = new Bundle();
b.putParcelable("bitmap", bit);
msg.setData(b);
in.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
_handle.sendMessage(msg);
And this is what I use to then for the ImageView, I get the bitmap from the code above and:
imageV.setImageBitmap(comic);
Edit 2:
After trying this with some other images from different website, I've found that this white space is not always there. Given that, and there's probably not anything wrong with the code, are there any suggestions on removing this extra space since it doesn't show up in the actual image online nor in a webview?
imageSize = din.readInt();
imageName = din.readUTF();
byte b[] = new byte[imageSize];
din.readFully(b);
bmImg = BitmapFactory.decodeByteArray(b,0,b.length);
//This works for me....
//din is DataInputStream object.