Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload a picture taken by the camera to a server with limited size

the title sounds maybe a bit like a "noob question" but I know quite well how to program for Android, I just to figure out what it is the best way to achieve what I want.

My use case is: the user takes a photo and sends it to our server which have a file-size limit (which could mean that we have to resize the photo directly on the device).

Seems easy, right? My problem are the following:

1) Better use intents which could crash because some camera apps are coded with the ass or build a basic view "take photo and confirm" with cawc camera libs ? (I did the two, I prefer intents but I'd like to have an opinion on that).

2) How do you handle the file size limit? I mean getting the size of the photo is quite easy with the File.length() (even if the returned value is not perfectly right) but if you goes over the limit, how can you say how big will be the resized picture? (you need to convert in bitmap to resize it and it's then a lot of problems with OOMException and you cannot calculate final size of a bitmap on the disk, you need to compress and write it to the disk and analyse the newly created file after).

Thanks for help :D

like image 686
Laurent Meyer Avatar asked May 20 '15 16:05

Laurent Meyer


People also ask

What to do if a photo is too big to upload?

Scan your document at a lower resolution (96 DPI). Crop the image to remove any empty space around it. Shrink the image. Save the file in JPG format instead.

How do I reduce the size of a picture on my Android?

Compress Image Size Step 1: Download and install 'Compress image size' from the Play Store. Step 2: Open the app and choose a photo. Step 3: You can check the original image size. Enable Quality toggle and use the slider to reduce image size.


2 Answers

I did the same thing before.

1.I use intent to call the other camera app, and inside onActivityResult, I get back the URI and process it as I need.

  1. We do resize the pic, but I also keep the original ratio, and rotate it based on exif data. Hopefully this resizing code block can give you some hints.

    public static Bitmap DecodeImage(String path, int resolution) {
    BitmapFactory.Options opts = new BitmapFactory.Options();
    
    opts.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path, opts);
    opts.inSampleSize = computeSampleSize(opts, -1, resolution);
    opts.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(path, opts);
        }
    
    public static int computeSampleSize(BitmapFactory.Options options,
                                    int minSideLength, int maxNumOfPixels) {
    int initialSize = computeInitialSampleSize(options, minSideLength,
            maxNumOfPixels);
    
    int roundedSize;
    
    if (initialSize <= 8) {
        roundedSize = 1;
        while (roundedSize < initialSize) {
            roundedSize <<= 1;
        }
    } else {
        roundedSize = (initialSize + 7) / 8 * 8;
    }
    
    return roundedSize;
        }
    
    private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
    double w = options.outWidth;
    double h = options.outHeight;
    
    int lowerBound = (maxNumOfPixels == -1) ? 1 :
            (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
    
    int upperBound = (minSideLength == -1) ? 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 == -1) &&
    
            (minSideLength == -1)) {
        return 1;
    } else if (minSideLength == -1) {
        return lowerBound;
    } else {
        return upperBound;
    }
    
        }
    

    The solution is not fancy but it is what I did it in the project, and we so far have no problems with it after release.

like image 61
Jacky Lian Avatar answered Oct 11 '22 19:10

Jacky Lian


There are lots of question over this topic and hope you searched for it.

Q) Better use intents which could crash because some camera apps are coded with the ass or build a basic view "take photo and confirm" with cawc camera libs ? (I did the two, I prefer intents but I'd like to have an opinion on that).

A) Intents are best because they are build in, some device manufacturers intents for cropping and re-sizing images and I face similar problem of not having that on same manufacturer but on Older device. A stable/relible third party app would suffice for basic operations.

Q) How do you handle the file size limit? I mean getting the size of the photo is quite easy with the File.length() (even if the returned value is not perfectly right) but if you goes over the limit, how can you say how big will be the resized picture? (you need to convert in bitmap to resize it and it's then a lot of problems with OOMException and you cannot calculate final size of a bitmap on the disk, you need to compress and write it to the disk and analyse the newly created file after).

A)

  1. How do you handle the file size limit? Size limit depends on Camera, if you have 10MP camera then the resultant size would be greater than 5MP (hope you get the part).
  2. You need to convert in bitmap to resize it and it's then a lot of problems with OOMException and you cannot calculate final size of a bitmap on the disk You can calculate the image size or sample it or crop it or resize it as far as you keep best practices of Android intact, recycle the bitmap as soon as you done with the bitmap operations. I have a app which has 100s of Images and most of them being send to server and some times it throws OOM, then I handle it accordingly.
like image 26
Murtaza Khursheed Hussain Avatar answered Oct 11 '22 19:10

Murtaza Khursheed Hussain