Increase image sizes get from cache android - android

Hi I download images from url & save them in cache. Then load those images from cache into carousel view.
but the problem is when phone resolution(720X1124) is high image size become small.
Here I give the code of images save & show them from cach...
private Bitmap getBitmap(String url)
{
File f=fileCache.getFile(url);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
//from web
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(300000000);
conn.setReadTimeout(300000000);
conn.setInstanceFollowRedirects(true);
InputStream inputstream=conn.getInputStream();
OutputStream outputstream = new FileOutputStream(f);
Utils.CopyStream(inputstream, outputstream);
outputstream.close();
conn.disconnect();
bitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex){
ex.printStackTrace();
if(ex instanceof OutOfMemoryError)
memoryCache.clear();
return null;
}
}
public void getDimension(int width,int height){
widthScreen=width;
heightScreen=height;
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
final int IMAGE_MAX_SIZE = 120000000; // 1.2MP
BitmapFactory.Options scaleOptions = new BitmapFactory.Options();
scaleOptions.inJustDecodeBounds = true;
FileInputStream stream1=new FileInputStream(f);
BitmapFactory.decodeStream(stream1,null,scaleOptions);
stream1.close();
// find the correct scale value as a power of 2.
int scale = 1;
while (scaleOptions.outWidth / scale / 2 >= widthScreen
&& scaleOptions.outHeight / scale / 2 >= heightScreen) {
scale *= 2;
}
Bitmap bitmap = null;
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
scaleOptions = new BitmapFactory.Options();
scaleOptions.inSampleSize = scale;
bitmap = BitmapFactory.decodeStream(stream1, null, scaleOptions);
int width=widthScreen;
int height=heightScreen;
double y=height;
double x=width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int) x,
(int) y, true);
bitmap.recycle();
bitmap = scaledBitmap;
System.gc();
} else {
bitmap = BitmapFactory.decodeStream(stream1);
}
if((widthScreen>=450)&& (heightScreen>=750) ) {
sample=1;
}
else{
sample=2;
}
//decode with inSampleSize
BitmapFactory.Options scalOption = new BitmapFactory.Options();
scalOption.inSampleSize=sample;
FileInputStream stream2=new FileInputStream(f);
Bitmap bitMap=BitmapFactory.decodeStream(stream2, null, scalOption);
stream2.close();
return bitMap;
} catch (FileNotFoundException e) {
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
how to increase the image sizes according phone resolution. I have tired more days to overcome this problem. But it doesn't work. So give me right instruction.......
thanks............

You need to define your layout for the different screen sizes / resolutions.
See Supporting Multiple Screens.

try to load images with this image loader library

public 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) {
if (width > height) {
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
put this method in my code and call this method as following way ,
private Bitmap decodeFile(File f) {
try {
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1 = new FileInputStream(f);
BitmapFactory.decodeStream(stream1, null, o);
stream1.close();
Matrix matrix = new Matrix();
// matrix.postScale(scaleWidth, scaleHeight);
matrix.postRotate(45);
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
//calculateInSampleSize1(o, widthScreen,heightScreen);
o2.inSampleSize=calculateInSampleSize(o, widthScreen,heightScreen);;
FileInputStream stream2 = new FileInputStream(f);
o2.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

Related

outofmemory exception for Large Bitmap

I found a lot of documentation on how to load large Bitmaps and avoid outofmemory exception. but the problem is that I have to take the image from my MediaStore.Images.media so the classical
decodeFile(path,options) indicated in the google documentation does not work to me
As you can see below I decommented the line // Bitmap photo= Mediastore.Images, that is the one that triggers the out of memory. on the other side adding
the line Bitmap bm=BitmapFactory.decodeFile(selectedImageToUri,options) returns null, although the compiler can see both the path in selectedImageToUri (that indicates the content provider where the pics are) than the options value, that I set to 8, because I want to subscale all the images
My question is how can I insert in bm the bitmap that is referring to the image selected by the user in the gallery. in the line BitMap photo does not return null and work really well, but I decommented because after I change a couple of images gives me outofmemory exception.
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable final Bundle savedInstanceState) {
if (flagVariable) {
if (selectedImageToUri != null) {
// BitMap photo = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), Uri.parse(selectedImageToUri));
final BitmapFactory.Options options= new BitmapFactory.Options();
options.inSampleSize=8;
Bitmap bm = BitmapFactory.decodeFile(selectedImageToUri, options);
pic = new BitmapDrawable(bm);
getActivity().getWindow().setBackgroundDrawable(pic);
} else {
getDefaultImageBackground(inflater, container);
}
hiddenList = inflater.inflate(R.layout.fragment_as_list_layout_temp, container, false);
} else {
getDefaultImageBackground(inflater, container);
}
listView = (ListView) hiddenList.findViewById(R.id.list_hidden);
MediaStore.getBitmap is just a simple convienence method, it looks like this:
public static final Bitmap getBitmap(ContentResolver cr, Uri url)
throws FileNotFoundException, IOException {
InputStream input = cr.openInputStream(url);
Bitmap bitmap = BitmapFactory.decodeStream(input);
input.close();
return bitmap;
}
You can create your own method based on this that takes the options and calls a different overload on BitmapFactory:
public static final Bitmap getBitmap(ContentResolver cr,
Uri url,
BitmapFactory.Options options)
throws FileNotFoundException, IOException {
InputStream input = cr.openInputStream(url);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, options);
input.close();
return bitmap;
}
Usage:
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bm = getBitmap(getActivity().getContentResolver(),
Uri.parse(selectedImageToUri),
options);
I spent a lot of time on this problem, but no one will give me exact answer and finally i solved it. First create method and provide Image URI as argument, and this will return bitmap basically here i calculated image size on bases of, we can manage memory as well as image and get exact image in bitmap form.
you can even display 5000×8000 and 12MiB picture without any error code is tested just copy paste in your class and enjoy.
Use
Bitmap mBitmap = getPhoto(MYIMAGEURI);
Provide URI to method and get Bitmap
Bitmap getPhoto(Uri selectedImage) {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
Bitmap photoBitmap = null;
InputStream inputStream = null;
try {
inputStream = getContentResolver().openInputStream(selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, null, bitmapOptions);
int imageWidth = bitmapOptions.outWidth;
int imageHeight = bitmapOptions.outHeight;
#SuppressWarnings("unused")
InputStream is = null;
try {
is = getContentResolver().openInputStream(selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
float scale = 1.0f;
if (imageWidth < imageHeight) {
if (imageHeight > width * 1.0f) {
scale = width * 1.0f / (imageHeight * 1.0f);
}
} else {
if (imageWidth > width * 1.0f) {
scale = width * 1.0f / (imageWidth * 1.0f);
}
}
photoBitmap = decodeSampledBitmapFromResource(this,
selectedImage, (int) (imageWidth * scale),
(int) (imageHeight * scale));
return photoBitmap;
}
Decode Bitmap Sample using image size
public static Bitmap decodeSampledBitmapFromResource(Context context,
Uri uri, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream is = null;
try {
is = context.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
BitmapFactory.decodeStream(is, null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode editBitmap with inSampleSize set
options.inJustDecodeBounds = false;
InputStream inputs = null;
try {
inputs = context.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return BitmapFactory.decodeStream(inputs, null, options);
}
Calculate Sample Size
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) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = Math.min(heightRatio, widthRatio);
// inSampleSize = heightRatio < widthRatio ? heightRatio :
// widthRatio;
}
return inSampleSize;
}
Or may be possible to solved using one line of code in manifiest.xml
is in application tag use this
android:largeHeap="true"

Scaling and loading the image from res\drawable-hdpi folder

In my Android app, To avoid the OOM (bitmap Out of Memory error), I am scaling and loading the image from the assets folder. I have some of my images in res\drawable-hdpi folder. Is there is any I can scale and load it as I do for the images in assets folder ?
#SuppressLint("NewApi")
public Drawable getAssetImage(String filename) throws IOException {
int dWidth,dHeight;
Display display = getWindowManager().getDefaultDisplay();
if ( Integer.valueOf(android.os.Build.VERSION.SDK_INT) < 13 ) {
dWidth = display.getWidth();
dHeight = display.getHeight();
} else {
Point size = new Point();
display.getSize(size);
dWidth = size.x;
dHeight = size.y;
}
AssetManager assets = getApplicationContext().getResources().getAssets();
InputStream buffer = null;
try {
buffer = new BufferedInputStream((assets.open(filename + ".png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
if (tabletSize) {
} else {
int tempSampleSize = calculateInSampleSize(options, (int)dWidth, (int)dHeight);
Log.i("ClassicalMemoryGame", "dWidth " + dWidth );
Log.i("ClassicalMemoryGame", "dHeight " + dHeight );
Log.i("ClassicalMemoryGame", "sample size - " + tempSampleSize );
if (tempSampleSize > 1) {
options.inSampleSize = tempSampleSize;
}
}
options.inJustDecodeBounds = false;
Bitmap temp = BitmapFactory.decodeStream(buffer, null, options);
Bitmap finalImage = Bitmap.createScaledBitmap(temp, (int) dWidth, (int) dHeight, true);
Drawable d = new BitmapDrawable(getResources(),finalImage);
return d;
}
You can use following method to do so:
public static Bitmap decodeScaledSampleBitmap(Resources res,
int resourceId,int width, int height)
{
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resourceId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options,
width, height);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap b = Bitmap.createScaledBitmap(
BitmapFactory.decodeResource(res, resourceId, options),
width, height, true);
return b;
}

Sampling a bitmap from url

I am trying to reduce the size of bitmap from a url. I saw many posts, but all were about sampling a local file. I want to sample the image at url. Here is my code:
public Bitmap getScaledFromUrl(String url) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 1 / 10;
try {
return BitmapFactory.decodeStream((InputStream) new URL(url)
.getContent());
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
Is this approach correct? I am getting out of memory crashes in my app at this function. Any ideas?
This works. I found it at http://blog.vandzi.com/2013/01/get-scaled-image-from-url-in-android.html . Use the following snippet of code, pass params as you like.
private static Bitmap getScaledBitmapFromUrl(String imageUrl, int requiredWidth, int requiredHeight) throws IOException {
URL url = new URL(imageUrl);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(url.openConnection().getInputStream(), null, options);
options.inSampleSize = calculateInSampleSize(options, requiredWidth, requiredHeight);
options.inJustDecodeBounds = false;
//don't use same inputstream object as in decodestream above. It will not work because
//decode stream edit input stream. So if you create
//InputStream is =url.openConnection().getInputStream(); and you use this in decodeStream
//above and bellow it will not work!
Bitmap bm = BitmapFactory.decodeStream(url.openConnection().getInputStream(), null, options);
return bm;
}
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) {
if (width > height) {
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
It's really flexible.. I think you should try it out.
You are using it wrong. You are asking to make the picture 10 times bigger :) You should give the command in normal numbers, not fraction. For example:
final BitmapFactory.Options options2 = new BitmapFactory.Options();
options2.inSampleSize = 8;
b = BitmapFactory.decodeFile(image, options2);
with this configuration you obtain 8 times smaller picture than the original.
UPDATE: To load image from internet add this class to the project and do the following:
ImageLoader loader = new ImageLoader(context);
Bitmap image = loader.getBitmap(URL);

Image picked from gallery is wrongly oriented

After calling gallery intent and getting the image URI in onActivityResult()
Uri selectedImageUri = data.getData();
String filePath;
try {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImageUri,
projection, null, null, null);
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
filePath = cursor.getString(column_index);;
} catch (Exception e) {
}
File imageFile = new File(filePath);
Bitmap bitmap = decodeFile(imageFile.getAbsolutePath());
imageView.setImageBitmap(bitmap);
But the image in the imageView is rotated 90 degree. I even sent the image as a file to a web server and that's rotated too.
So, I tried checking for the Exif details,
//getOutputMediaFile() just returns a filepath to store image in my app folder
String newFilePath = getOutputMediaFile();
//800 is the desired width and height
Bitmap photo = decodeSampledBitmapFromFile(filePath, 800, 800);
//reduce the size of the image and store it in a new file ie.. newFilePath
FileOutputStream out = new FileOutputStream(newFilePath);
photo.compress(Bitmap.CompressFormat.JPEG, 100, out);
ExifInterface exif = new ExifInterface(newFilePath);
int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL);
int rotationInDegrees = exifToDegrees(rotation);
//If rotation is required
if (rotation != 0) {
Matrix matrix = new Matrix();
matrix.preRotate(rotationInDegrees);
File imageFile = new File(newFilePath);
//get the same image
Bitmap bitmap = decodeFile(imageFile.getAbsolutePath());
//rotate it
Bitmap adjustedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
//and save in the same file
FileOutputStream out2 = new FileOutputStream(newFilePath);
adjustedBitmap.compress(Bitmap.CompressFormat.JPEG, 100,out2);
}
decodeSampledBitmapFromFile()
public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth,
int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize, Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
int inSampleSize = 1;
if (height > reqHeight) {
inSampleSize = Math.round((float) height / (float) reqHeight);
}
int expectedWidth = width / inSampleSize;
if (expectedWidth > reqWidth) {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
options.inSampleSize = inSampleSize;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
decodeFile()
private Bitmap decodeFile(String path) {
IMAGE_MAX_SIZE = 800;
Bitmap b = null;
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
File f = new File(path);
FileInputStream fis = new FileInputStream(f);
BitmapFactory.decodeStream(fis, null, o);
fis.close();
int scale = 1;
if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
scale = (int) Math.pow(
2,
(int) Math.round(Math.log(IMAGE_MAX_SIZE
/ (double) Math.max(o.outHeight, o.outWidth))
/ Math.log(0.5)));
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = new FileInputStream(f);
b = BitmapFactory.decodeStream(fis, null, o2);
fis.close();
} catch (IOException e) {
return null;
}
return b;
}
The code never goes inside if(rotation != 0f){}. Which means the image Orientation is proper, then why the file I get or the Bitmap I get are rotated. What am I missing?

Outofmemory error in bitmap runtime exception

i am displaying my images from assests/image folder ,
but this code is not working . this code display images from assets folder in gallery . i am using gallery prefine library or jar file.
please expert check it . thank u
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("image");
} catch (IOException e) {
Log.e("tag", e.getMessage());
}
for(String filename : files) {
System.out.println("File name => "+filename);
InputStream in = null;
try {
ImageViewTouch imageView = new ImageViewTouch(Rahul.this);
imageView.setLayoutParams(new Gallery.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
final Options options = new Options();
options.outHeight = (int) scaleHeight;
options.outWidth = (int) scaleWidth;
options.inScaled = true;
options.inPurgeable = true;
options.inSampleSize = 2;
in = assetManager.open("image/"+filename);
Bitmap bit=BitmapFactory.decodeStream(in);
imageView.setImageBitmap(bit);
} catch(Exception e) {
Log.e("tag", e.getMessage());
}
}
gallery.setAdapter(arrayAdapter);
Hey please check my answer on the same issue: bitmap size exceeds Vm budget error android
And also always try to use maximum options while dealing with bitmaps like this:
final Options options = new Options();
options.outHeight = (int) scaleHeight; // new smaller height
options.outWidth = (int) scaleWidth; // new smaller width
options.inScaled = true;
options.inPurgeable = true;
// to scale the image to 1/8
options.inSampleSize = 8;
bitmap = BitmapFactory.decodeFile(imagePath, options);
This might solve your problem.
1) try to use bitmap.recycle(); to release memory before setting a new bitmap to your images
BitmapDrawable drawable = (BitmapDrawable) myImage.getDrawable();
Bitmap bitmap = drawable.getBitmap();
if (bitmap != null)
{
bitmap.recycle();
}
2) if your images are too large scale down them:
public static Bitmap decodeFile(File file, int requiredSize) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(file), null, o);
// The new size we want to scale to
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < requiredSize
|| height_tmp / 2 < requiredSize)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(file),
null, o2);
return bmp;
} catch (FileNotFoundException e) {
} finally {
}
return null;
}
Update
something like this:
for(int i=0; i<it.size();i++) {
ImageViewTouch imageView = new ImageViewTouch(GalleryTouchTestActivity.this);
imageView.setLayoutParams(new Gallery.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
Options options = new Options();
options.inSampleSize = 2;
String photoURL = it.get(i);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
if (bitmap != null)
{
bitmap.recycle();
}
bitmap = BitmapFactory.decodeFile(photoURL);
imageView.setImageBitmap(bitmap);
arrayAdapter.add(imageView);
}

Categories

Resources