I'm trying to calculate the remaining number of photos that can be taken using my custom camera and show that count to the user. I tried with the following code:
private void numberOfPhotosAvailable() {
long photosAvailable = 0;
StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
resolution=getResolution();
long bytesPerPhoto=resolution/1048576;
long bytesAvailable = (long) stat.getAvailableBlocksLong() * (long) stat.getBlockSizeLong();
long megAvailable = bytesAvailable / 1048576;
System.out.println("Megs :" + megAvailable);
photosAvailable = megAvailable / bytesPerPhoto;
tvAvailablePhotos.setText("" + photosAvailable);
}
Method for getting resolution.
public long getResolution(){
long resolution=0;
Camera.Parameters params=mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPictureSizes();
Camera.Size size = sizes.get(0);
int width=size.width;
int height=size.height;
resolution=width*height;
return resolution;
}
PROBLEM: There is a lot of difference in the count shown in the phone's camera and count that is shown in my app.
So what is the proper way of doing this ?
NOTE: I will only be capturing image in the highest quality available. Therefore I am only calculating count according to one resolution only.
It is impossible to find the exact size of the output image for JPEG/PNG compression. The compression algorithms are optimized in such a way that they use as less size as possible but preserve the image pixels (although JPEG is slightly lossy).
However, you can estimate the no of images by taking multiple sample photos and calculating the average compression ratio.
From Wikipedia:
JPEG typically achieves 10:1 compression with little perceptible loss in image quality.
So estimated storage size can be calculated as:
int bytes = width * height * 2 / compressionRatio;
Here it is multiplied by 2 because in RGB_565 config, it requires 2 bytes to store 1 pixel.
I think that there is no ultimate solution for images left because there are too much different devices and cameras and also it depends heavily on image content.
One good explanation for that I have found here
As suggested before you can predict image size and calculate images count left based on a device free space. To get that prediction best solution is to try it on your device first. After user starts using the app, you can include his last 10 photo sizes in calculation. If it is not a key feature you can just present it as prediction based on usage, not as a binding fact.
P.S I am using Samsung Galaxy S7 edge and there is no images left count in camera at all. (Or I am just unable to find it)
Well after lot of researching and googling, I came to this site.
According to this site, following are the steps to get the file size.
So when I followed the above steps, i.e. my detectors resolution is 5376X3024. Proceeding with the above steps I finally got 39 MB as answer for image size.
But the image taken by camera was around 8-10 MB in size which was still not close to what I got in result above.
My phone (HTC Desire 10 pro) has a pro mode settings available. In this mode photos are captured as raw images. So when I checked for the size of the captured raw image, I was amused as the size of the raw file was indeed around 39 MB, which states that above steps are correct for calculating image's original size.
CONCLUSION
With the above steps I came to the conclusion that phone's softwares indeed use some compression algorithms to make image size less. So what I was comparing to was actually compressed images hence the count of images was different.
PROBABLE SOLUTION
The approach that I am now aiming is to get the last clicked image from my camera, get its file size and show count according to that file size. This will also be a approximate result but I don't think there can be any solution for getting exact count.
This is the code I am using to implement the above solution
private void numberOfPhotosAvailable() {
long photosAvailable = 0;
StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
File lastFile=null;
lastFile=utils.getLatestFilefromDir(prefManager.getString(PrefrenceConstants.STORAGE_PATH));
if (lastFile!=null){
double fileSize=(lastFile.length())/(1024*1024);
long bytesAvailable = (long) stat.getAvailableBlocksLong() * (long) stat.getBlockSizeLong();
long megAvailable = bytesAvailable / 1048576;
System.out.println("Megs :" + megAvailable);
photosAvailable = (long) (megAvailable / fileSize);
tvAvailablePhotos.setText("" + photosAvailable);
}else{
tvAvailablePhotos.setVisibility(View.INVISIBLE);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With