2

Days, I've spent working on this. Weeks, perhaps. Literally. :(

So I've got an image on an SD card that more than likely came out of the built-in camera. I want to take that image and downsample it to an arbitrary size (but always smaller and never larger). My code uses standard Android Bitmap methods to decode, resize, recompress, and save the image. Everything works fine as long as the final image is smaller than 3MP or so. If the image is larger, or if I try to do several of these at once, the application crashes with an OutOfMemoryError. I know why that's happening, and I know it's happening for a perfectly legitimate reason, I just want it to not happen anymore.

Look, I'm not trying to launch a rocket here. All I want to do is resize a camera image and dump it to an OutputStream or even a temporary file. Surely someone out there must have done such a thing. I don't need you to write my code for me, and I don't need my hand held. But between my various programming abortions and days of obsessed Googling, I don't even know which direction to head in. Roughly speaking, does anyone know how to decode a JPEG, downsample it, re-compress it in JPEG, and send it out on an OutputStream without allocating a massive amount of memory?

4
  • please post your logcat, will help you Commented Apr 24, 2013 at 5:24
  • Can you please tell what you want to do with this image finally,I mean to upload or display in an imageview etc.. Commented Apr 24, 2013 at 5:29
  • hey adi, why you don't try @Evan Lis solution, that is best, to resize and show image in view. Commented Apr 24, 2013 at 5:34
  • @Umesh... Can you please provide the link for the same? Thanks. Commented Apr 24, 2013 at 6:46

2 Answers 2

3

Ok I know it's a little bit late but, I had this problem and I found solution. It is actually easy and I am sure it supports back to api 10(I have no idea about before 10). I tried this with my phone. It is a samsung galaxy s2 with an 8mp camera and the code perfectly resized camera images to the 168x168 as well as images i found on web. I checked the images by using file manager too. I never tried resizing images to bigger resoulation.

private Bitmap resize(Bitmap bp, int witdh, int height){
    return Bitmap.createScaledBitmap(bp, width, height, false);
}

you can save it like this

private void saveBitmap(Bitmap bp) throws FileNotFoundException{
    String state = Environment.getExternalStorageState();
    File folder;
    //if there is memory card available code choose that
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        folder=Environment.getExternalStorageDirectory();
    }else{
        folder=Environment.getDataDirectory();
    }
    folder=new File(folder, "/aaaa");
    if(!folder.exists()){
        folder.mkdir();
    }

    File file=new File(folder, (int)(Math.random()*10000)+".jpg");
    FileOutputStream os=new FileOutputStream(file);
    bp.compress(Bitmap.CompressFormat.JPEG, 90, os);
}

thanks to this link

Sign up to request clarification or add additional context in comments.

Comments

0

The following code is from my previous project. Key point is "options.inSampleSize".

public static Bitmap makeBitmap(String fn, int minSideLength, int maxNumOfPixels) {
    BitmapFactory.Options options;
    try {
        options = new BitmapFactory.Options();

        options.inPurgeable = true;
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(fn, options);
        if (options.mCancel || options.outWidth == -1
                || options.outHeight == -1) {
            return null;
        }
        options.inSampleSize = computeSampleSize(
                options, minSideLength, maxNumOfPixels);
        options.inJustDecodeBounds = false;
        //Log.e(LOG_TAG, "sample size=" + options.inSampleSize);

        options.inDither = false;
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        return BitmapFactory.decodeFile(fn, options);
    } catch (OutOfMemoryError ex) {
        Log.e(LOG_TAG, "Got oom exception ", ex);
        return null;
    }
}

private static int computeInitialSampleSize(BitmapFactory.Options options,
        int minSideLength, int maxNumOfPixels) {
    double w = options.outWidth;
    double h = options.outHeight;

    int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 :
            (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
    int upperBound = (minSideLength == UNCONSTRAINED) ? 128 :
            (int) Math.min(Math.floor(w / minSideLength),
            Math.floor(h / minSideLength));

    if (upperBound < lowerBound) {
        // return the larger one when there is no overlapping zone.
        return lowerBound;
    }

    if ((maxNumOfPixels == UNCONSTRAINED) &&
            (minSideLength == UNCONSTRAINED)) {
        return 1;
    } else if (minSideLength == UNCONSTRAINED) {
        return lowerBound;
    } else {
        return upperBound;
    }
}

1 Comment

best answer, its the only way

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.