Question

I want to save bitmap image in sd card, i am able to save it but some time my activity is killed because of low ram.

So can i save image in chunks rather to save in form of byte array.

My code is like below:

    try {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();

        b.compress(Bitmap.CompressFormat.JPEG, 40, bytes);

        File f = new File(Environment.getExternalStorageDirectory() + File.separator + "temp.jpg");
        if (f.exists()) {
            f.delete();
        }
        f.createNewFile();

        FileOutputStream fo = new FileOutputStream(f);
        fo.write(bytes.toByteArray());
        fo.flush();
        fo.close();

    } catch (Exception e) {

        e.printStackTrace();
    }
Was it helpful?

Solution

To reduce this issue one thing you can do is to resize of rescale the image and then after save it into the memory.

Below is the code which will help . You can try out below method.

  // decodes image and scales it to reduce memory consumption
public static Bitmap decodeFile(File p_f)
{
    try
    {
        // decode image size
        BitmapFactory.Options m_opt = new BitmapFactory.Options();
        m_opt.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(p_f), null, m_opt);
        // Find the correct scale value. It should be the power of 2.
        final int REQUIRED_SIZE = 70;
        int m_widthTmp = m_opt.outWidth, m_heightTmp = m_opt.outHeight;
        int m_scale = 1;
        while (true)
        {
            if (m_widthTmp / 2 < REQUIRED_SIZE || m_heightTmp / 2 < REQUIRED_SIZE) break;
            m_widthTmp /= 2;
            m_heightTmp /= 2;
            m_scale *= 2;
        }
        // decode with inSampleSize
        BitmapFactory.Options m_o2 = new BitmapFactory.Options();
        m_o2.inSampleSize = m_scale;
        return BitmapFactory.decodeStream(new FileInputStream(p_f), null, m_o2);
    }
    catch (FileNotFoundException p_e)
    {
    }
    return null;
}

EDITED:

You can also check for whether a space is available in sdcard or not and based on available space you can save the image into sdcard. I have used below method to get the free space available or not.

 /**
 * This function find outs the free space for the given path.
 * 
 * @return Bytes. Number of free space in bytes.
 */
public static long getFreeSpace()
{
    try
    {
        if (Environment.getExternalStorageDirectory() != null
                && Environment.getExternalStorageDirectory().getPath() != null)
        {
            StatFs m_stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
            long m_blockSize = m_stat.getBlockSize();
            long m_availableBlocks = m_stat.getAvailableBlocks();
            return (m_availableBlocks * m_blockSize);
        }
        else
        {
            return 0;
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
        return 0;
    }
}

Use the above as below:

     if (fileSize <= getFreeSpace())
   {
        //write your code to save the image into the sdcard.
       } 
       else
       {
         //provide message that there is no more space available.
         }  

OTHER TIPS

The Best way to solve this problem is to scale down the size of image to the required view size, and do all your heavy work on a background thread(Async Task), while your background thread is working, you can show any dummy image form resource, and once the image is properly properly processed replace your bitmap with the previous one.

Once read this, before you proceed

Displaying Bitmaps Efficiently

Processing Bitmaps Off the UI Thread

Load a Scaled Down Version into Memory

Managing Bitmap Memory

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top