12
votes

I have a large number of resources in my drawable folder.All are having big size more than 500KB. I have to load all these 25 images all at once in a srollView. As usual I ran out of memory. Is there any way to reduce the size of the image programmatically.

I got this function but it's parameter is a File and I don't know how to create a File from a drawable.


private Bitmap decodeFile(File f){
    Bitmap b = null;
    try {
        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;

        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 = 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 (FileNotFoundException e) {
    }
    return b;
}

I have to go thorugh this screen cyclically many times after a number of traversal the system is showing Low memory and it is removing the other views in the back from the stack , but I actually need it. Please help me.

4

4 Answers

34
votes

You can open an InputStream from your drawable resource using following code:

InputStream is = getResources().openRawResource(id);

here id is the identifier of your drawable resource. for eg: R.drawable.abc

Now using this input stream you can create a file. If you also need help on how create a file using this input stream then tell me.

Update: to write data in a file:

try
    {
    File f=new File("your file name");
    InputStream inputStream = getResources().openRawResource(id);
    OutputStream out=new FileOutputStream(f);
    byte buf[]=new byte[1024];
    int len;
    while((len=inputStream.read(buf))>0)
    out.write(buf,0,len);
    out.close();
    inputStream.close();
    }
    catch (IOException e){}
    }
0
votes

I like shortcuts so I prefer using this.

For creatting file from drawable see this.

Put this in your build.gradle

compile 'id.zelory:compressor:1.0.4'

And wherever you want to compress the image put

 Bitmap compressedImageFile = Compressor.getDefault(context).compressToBitmap(your_file);

README.md provides much more information. Sorry for bringing the answer after 6 years.

0
votes

bro there are two methods

  1. Easiest one Use some 3rd party library
  2. Or use Bitmap class to scale drawable down

just use Bitmap.createScaledBitmap method to compress drawables

steps :

// Step 1 Load drawable and convert it to bitmap

Bitmap b = BitmapFactory.decodeResource( context , resId )

// Step 2 reScale your Bitmap

Bitmap nBitmap = b.createScaledBitmap( getResources() , newHieght , newWidth , true );  

// Step 3 Create a drawable from bitmap

BitmapDrawable drawable = new BitmapDrawable(nBitmap);

I highly recommend you to use 3rd part library because this method is very expensive

like https://github.com/Tourenathan-G5organisation/SiliCompressor

-1
votes

I took cue from @mudit's answer and created the drawable from Input Stream. And later loaded the drawable to the ImageView in the Adapter.

InputStream inputStream = mContext.getResources().openRawResource(R.drawable.your_id);

Bitmap b = BitmapFactory.decodeStream(inputStream);
b.setDensity(Bitmap.DENSITY_NONE);
Drawable d = new BitmapDrawable(b);
mImageView.setImageDrawable(d);

Here is the detailed version of solution