I download photos from the Internet. have a site on the same page which has 18 photos (80x60 px ~ 10kb).
so I made a list which loads the new picture (sleduyuschuyuyu page)
the problem is when I load three or more pages, a memory error occurs
the question is how to get rid of?
Now I build an array of bitmaps
for (Element titles : title) {
if (titles.children().hasClass("btl")){
m = new HashMap<String, Object>();
m.put(MyActivity.ATTRIBUTE_NAME_TEXT, titles.select("a[href]").attr("abs:href"));
Picasso p = Picasso.with(MyActivity.context);
m.put(MyActivity.ATTRIBUTE_NAME_PHOTO,Bitmap.createScaledBitmap(p.load(titles.select("img").attr("abs:src")).get(),80,60, true) );
data.add(m);
}
}
and in adapter
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
final Map<String, Object> itemData = datas.get(position*2);
final Map<String, Object> itemData2 = datas.get(position*2+1);
Bitmap bitmap2 = null;
Bitmap bitmap = (Bitmap) itemData.get("img");
if(itemData2!=null)
bitmap2 = (Bitmap) itemData2.get("img");
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.items, null, true);
holder = new ViewHolder();
holder.ivImage = (ImageView) rowView.findViewById(R.id.imageView);
holder.ivImage2 = (ImageView) rowView.findViewById(R.id.imageView1);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
holder.ivImage.setImageBitmap(bitmap);
holder.ivImage2.setImageBitmap(bitmap2);
holder.ivImage.setTag(position*2);
holder.ivImage2.setTag(position*2+1);
holder.ivImage.setOnClickListener(this);
holder.ivImage2.setOnClickListener(this);
return rowView;
}
I was offered to save images in the cache and load them from there but do not know how to do it.
please help
Use disk cache... This article also has plenty of other useful tips for loading bitmaps
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html#disk-cache
The best way to load iomages is the picasso library at http://square.github.io/picasso/
You will read the images by using decoding the images to your desired size....
Convert the image into like this method....
It's used for drawable resources....
Bitmap bmap2 = decodeSampledBitmapFromResource(getResources(),
R.drawable.hydrangeas, width, height);
public static Bitmap decodeSampledBitmapFromResource(Resources res,
int resId, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and
// keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
Which the below method for decode by the use of streams....
public static Bitmap decodeSampledBitmapFromResource(InputStream in,
int reqWidth, int reqHeight) throws IOException {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
in.mark(in.available());
BitmapFactory.decodeStream(in, null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
in.reset();
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(in, null, options);
}
Suppose you will get fail in the all method You will try this logic you just need to add this line into your mainfest file...
You just need to add this line to your manifest file. It will allocate the large memory for your application.
android:largeHeap="true"
Related
I'm attempting to scale down a bitmap to load a smaller version into memory. I'm pretty much following Google's example (search Loading Large Bitmaps Efficiently), except that I'm loading from the image gallery instead of a resource. But I seem to be getting back a null bitmap after calculating dimensions. Here's my code:
/** OnActivityResult Method **/
final Uri imageUri = data.getData();
final InputStream imageStream = getActivity().getContentResolver().openInputStream(imageUri);
Bitmap bitmapToLoad = Util.decodeSampledBitmapFromResource(imageStream, 500, 500); // bitmapToLoad is null.
mIvScreenshot.setImageBitmap(bitmapToLoad);
/**Helper Methods **/
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromResource(InputStream is,
int reqWidth, int reqHeight) {
Rect rect = new Rect();
// First decode with inJustDecodeBounds = true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, rect, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(is, rect, options);
}
Can anyone catch what I'm doing wrong?
I managed to get it working. Thanks to Biraj Zalavadia (How to reduce an Image file size before uploading to a server) for the scaling logic, and the cursor code here (How to return workable filepath?). Here is my onActivityResult():
try {
final Uri imageUri = data.getData();
String[] filePath = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(imageUri, filePath, null, null, null);
cursor.moveToFirst();
String imagePath = cursor.getString(cursor.getColumnIndex(filePath[0]));
Uri newUri = Uri.parse(ScalingUtilities.scaleFileAndSaveToTmp(imagePath, 500, 500));
final Bitmap selectedImage = BitmapFactory.decodeFile(newUri.getEncodedPath());
mIvScreenshot.setImageBitmap(selectedImage);
} catch (Exception e) {
// Handle
}
I am currently pulling an image from the android gallery, which returns a uri to an activity for preview, then gets sent up to Parse database.
Images being sent up were far too big so I implemented the methods found in the android developer documentation
Here's what I'm working with
Uri selectedImage = data.getData();
InputStream imageStream = getContentResolver().openInputStream(selectedImage);
imageBitmap = getBitmapFromReturnedImage(imageStream, 800, 800);
// ByteArrayOutputStream stream = new ByteArrayOutputStream();
// LINE 2 imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
// byte[] byteArray = stream.toByteArray();
//
// parseFile = new ParseFile("location_image.jpg", byteArray);
mImage.setImageBitmap(imageBitmap);
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap getBitmapFromReturnedImage(InputStream inputStream, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(inputStream, null, options);
}
The commented "LINE 2", when that section isn't commented, returns a null pointer exception, which blows my mind. With that section commented, the imageview simply looks to be empty when I run the app.
Any clue what's going on?
You need to seek back to the start of the InputStream after reading the bounds before calling decodeStream for a second time, otherwise you will end up with an invalid Bitmap. The easiest way is just to close the stream and open it again.
Try this code (note function is no longer static to allow calling getContentResolver() and you have pass in a Uri not an InputStream):
public Bitmap getBitmapFromReturnedImage(Uri selectedImage, int reqWidth, int reqHeight) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(selectedImage);
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// close the input stream
inputStream.close();
// reopen the input stream
inputStream = getContentResolver().openInputStream(selectedImage);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(inputStream, null, options);
}
call like this
Uri selectedImage = data.getData();
imageBitmap = getBitmapFromReturnedImage(selectedImage, 800, 800);
I want to add a few ImageView in a linearLayout programmatically.
but application crashed for more than 2 images. its error is OutOfMemoryError.
String[] titleImages={"a","b","c","d","e","f","g"};
for (String title : titleImages){
InputStream inputStream = context.getAssets()
.open("titles"+"/"+title);
Drawable drawable = Drawable.createFromStream(inputStream, null);
inputStream.close();
ImageView imageView = new ImageView(_context);
imageView.setScaleType(ScaleType.FIT_XY);
imageView.setImageDrawable(drawable);
//more imageView set properties
LinearLayout shelf=findViewById(R.id.shelf);
//shelf is a LinearLayout
shelf.addView(imageView);
}
Use smaller images.
Or, use BitmapFactory.Options, an in particular its inSampleSize option, to downsample the images to something that is more appropriate for your screen size.
Or, use a third-party image-loading library, like Picasso, that can handle inSampleSize for you.
by using these methods you can resize the image as per your use.
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
In Xamarin, is it possible to get a thumbnail of a Bitmap that is hosted at a web address?
I have this code:
public static int CalculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
{
// Raw height and width of image
var height = (float)options.OutHeight;
var width = (float)options.OutWidth;
var inSampleSize = 1D;
if (height > reqHeight || width > reqWidth)
{
inSampleSize = width > height
? height/reqHeight
: width/reqWidth;
}
return (int) inSampleSize;
}
public static Bitmap DecodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight)
{
// First decode with inJustDecodeBounds=true to check dimensions
var options = new BitmapFactory.Options {
InJustDecodeBounds = true,
};
using (var dispose = BitmapFactory.DecodeResource(res, resId, options)) {
}
// Calculate inSampleSize
options.InSampleSize = CalculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.InJustDecodeBounds = false;
return BitmapFactory.DecodeResource(res, resId, options);
}
Can this code be modified to get a thumbnail of a Bitmap that is stored at a web address?
Thanks in advance
My code code is:
public Bitmap loadPhoto(Uri uri) {
Bitmap scaled = null;
try {
scalled = Bitmap.createBitmap(
MediaStore.Images.Media.getBitmap(getContentResolver(), uri),
0,0,90, 90);
if (scaled == null) { return null; }
} catch(Exception e) { }
return scaled;
}
After this. I display scaled in ImageView. Every image comes from the device camera.
Every time, I get error: out of memory after I display three photos from camera. How to solve this?
Answer of Praveen Katha will always return null. Here is the updated answer.
Here is the trick, close the input stream after every use. Input Stream means to be used one time. For more information, please follow this answer
private static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromUri(Context context, Uri imageUri, int reqWidth, int reqHeight) throws FileNotFoundException {
Bitmap bitmap = null;
try {
// Get input stream of the image
final BitmapFactory.Options options = new BitmapFactory.Options();
InputStream iStream = context.getContentResolver().openInputStream(imageUri);
// First decode with inJustDecodeBounds=true to check dimensions
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(iStream, null, options);
if (iStream != null) {
iStream.close();
}
iStream = context.getContentResolver().openInputStream(imageUri);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeStream(iStream, null, options);
if (iStream != null) {
iStream.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
Try using BitmapFactory to fix the problem http://developer.android.com/reference/android/graphics/BitmapFactory.html
The MediaStore.getBitmap method is a convenience method that does not specify a sample size when obtaining the bitmap. If you are using getBitmap(ContentResolver, Uri), and want to use a sample size, just use the ContentResolver to get the input stream, and decode the bitmap as you would normally (calculating sample size first, and then loading it with the appropriate sample size).
For those who are looking for code sample:
private static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap decodeSampledBitmapFromUri(Context context, Uri imageUri, int reqWidth, int reqHeight) throws FileNotFoundException {
// Get input stream of the image
final BitmapFactory.Options options = new BitmapFactory.Options();
InputStream iStream = context.getContentResolver().openInputStream(imageUri);
// First decode with inJustDecodeBounds=true to check dimensions
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(iStream, null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(iStream, null, options);
}