12

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.

James
  • 13,891
  • 26
  • 68
  • 93

4 Answers4

35

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){}
    }
mudit
  • 25,306
  • 32
  • 90
  • 132
  • 1
    Thanks for the help. I am getting an error on this... InputStream is = (InputStream) getResources().openRawResource(R.drawable.image); .Please tell me how to create the file also – James May 05 '11 at 10:13
  • 1
    I had to cast it like this. InputStream is = (InputStream) getResources().openRawResource(R.drawable.simplelist); – James May 05 '11 at 10:13
  • 1
    "getResources" is a function defined under Activity class, so are you sure that you have the context of the activity where ever you are writing the code for getting the input stream. – mudit May 05 '11 at 10:14
  • 1
    Okk. Are you getting an error in your IDE or you are getting this error when you are running the project? – mudit May 05 '11 at 10:19
  • But what should be the filename, the image may be of type png or jpg – James May 05 '11 at 10:34
  • For filename: "\sdcard\\image.png". For file type: it depends on what is the file type of your drawable, and if you dont know the filetype, you can simply use png for all of them. – mudit May 05 '11 at 10:40
  • If you think that answer posted by me is helpful than consider up voting the answer and if you think it is a correct answer than also accept the answer by clicking on the tick icon along with the answer. – mudit May 05 '11 at 10:41
  • No error, I think the image size is not reduced. Still jerking in the image flow. I am using a Gallery widget which has about 20 images. Can you advice me some technique to reduce this jerkness. – James May 05 '11 at 10:49
  • One way is to showing a progress dialog till you load the images and then allow the user to interact with the screen OR use images of smaller size. There are enough tools on internet who will provide you compression with a very minimal degradation in image quality. – mudit May 05 '11 at 10:52
  • @mudit:- thanks for your answer but to set the File f=new File("your file name");, i have set the File f=new File(R.drawable.ic_launcher+".png"); but get exception file not found – V.P. Apr 12 '13 at 07:44
  • @V.P.: before doing any file operation, you need to check if f.exist() and if it returns false then you need to create a file via f.createNewFile(); – mudit Apr 15 '13 at 06:17
0

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.

Community
  • 1
  • 1
Daksh Agrawal
  • 855
  • 1
  • 11
  • 22
0

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

Anas Aijaz
  • 352
  • 2
  • 9
-1

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

Community
  • 1
  • 1
sud007
  • 5,824
  • 4
  • 56
  • 63