如何在Android的自定义相机中计算剩余照片数量

7
我正在尝试计算使用我的自定义相机可以拍摄的剩余照片数量,并向用户显示该计数。我尝试使用以下代码:
```python ```
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);
    }

获取分辨率的方法。
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;
    }

问题: 手机相机显示的数值和我的应用程序中显示的数值有很大的差异。

那么正确的处理方式是什么呢?

注意:我只会以可用最高质量来捕获图像,因此我只会按照一个分辨率计算数量。


你为什么会认为一张照片的大小是7MB呢?那些都是压缩文件。实际捕捉到的数据取决于拍摄内容,可能会更少或更多。而且这还假设你没有达到特定供应商每个应用程序的最大存储限制。你还假设所有相机拍摄的分辨率都相同,但事实并非如此。 - Gabe Sechan
这就是为什么我在问什么是正确的计算方法。我知道上面的代码对其他设备不起作用。 - Vivek Mishra
@GabeSechan 现在检查一下。我现在正在使用动态方法进行计算。 - Vivek Mishra
我还开发了一个自定义相机,会采用这种方式:当应用程序启动时,我会假设照片文件大约需要4(5?6?)MB - 然后让用户知道还剩下多少张图片。同时,我会启动一个低优先级线程,创建一个具有随机颜色像素的位图,分辨率与您的图像相同,将其写入文件系统并读取其实际大小。之后,我会更新用户剩余图像的数量。如果您想更精确地操作,在应用程序运行过程中考虑新文件。 - rommex
4个回答

4

对于JPEG/PNG压缩,无法找到确切的输出图像大小。压缩算法被优化为尽可能使用较少的空间,同时保留图像像素(虽然JPEG略有损失)。

但是,您可以通过拍摄多个样本照片并计算平均压缩比来估计图像数量。

来自维基百科:

JPEG通常在几乎不会损失图像质量的情况下实现10:1的压缩。

因此,可以计算出估计的存储大小:

int bytes = width * height * 2 / compressionRatio;

这里乘以2是因为在RGB_565配置中,需要2个字节来存储1个像素。


我该如何获得压缩比。我认为它会因手机而异。 - Vivek Mishra
是的,它会因手机而异,这就是为什么你应该考虑一个平均值。不仅因手机而异,即使在单个手机中,它也会因照片而异。您可以计算多个样本的压缩比并对其进行平均,或在谷歌上搜索其他人的结果。 - Nabin Bhandari
我如何通过编程方式获取照片的压缩比率? - Vivek Mishra
你计算压缩比和字节数的公式得出的结果非常大。我的图片分辨率为3744X5376。 - Vivek Mishra
针对我的情况,我有一张尺寸为2560 x 1920的照片,保存在一个1.11MB的文件中。因此,压缩比将是 (256019202)/(1.1110241024) = 8.44。 - Nabin Bhandari
显示剩余2条评论

2
经过大量的调查和搜索,我找到了这个网站。
根据这个网站,以下是获取文件大小的步骤:
  1. 将水平像素数乘以垂直像素数,以获得探测器的总像素数。
  2. 将总像素数乘以探测器的位深度(16位、14位等),以获得数据的总位数。
  3. 将总位数除以8,即可得到以字节为单位的文件大小。
  4. 将字节数除以1024,即可得到以千字节为单位的文件大小。再除以1024,即可得到以兆字节为单位的文件大小。
所以当我按照上述步骤进行操作时,即我的探测器分辨率为5376X3024。最终我得到的图像大小答案是39 MB。
但是相机拍摄的图像大小约为8-10 MB,与上述结果仍有差距。
我的手机(HTC Desire 10 pro)有一个专业模式设置。在此模式下,照片以原始图像的形式捕获。因此,当我检查捕获的原始图像的大小时,我感到惊讶,因为原始文件的大小确实约为39 MB,这表明上述步骤是正确计算图像原始大小的方法。 结论 通过上述步骤,我得出结论,手机软件确实使用一些压缩算法来减小图像大小。因此,我比较的实际上是经过压缩的图像,因此图像数量不同。 可能的解决方案 我现在正在采取的方法是从我的相机中获取最后拍摄的图像,获取其文件大小,并根据该文件大小显示计数。这也将是一个近似结果,但我认为没有任何解决方案可以获得精确计数。
这是我用来实现上述解决方案的代码。
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);
    }

}

当然JPEG文件是经过压缩的。您可以使用setJpegQuality(int)方法来指定压缩级别。我通常使用70-90的范围,以保持图像的高质量并大幅减小它们的大小。 - rommex
@rommex 不明白你在评论中的意思? - Vivek Mishra
基本上,我是在说如果你使用非原始格式,你是无法预测图像文件的大小的。这些格式使用压缩。 - rommex

2

我认为关于图像剩余问题,没有一种终极解决方案,因为设备和相机太多,而且它也严重依赖于图像内容。

我在这里找到了一个很好的解释(链接)

如之前所建议的,您可以预测图像大小,并基于设备可用空间计算剩余图像数量。要获得最佳预测结果,请先在您的设备上尝试。 用户开始使用应用程序后,您可以将其最后10张照片的大小包含在计算中。 如果这不是关键特性,您只需将其呈现为基于使用情况的预测,而不是作为约束性事实。

P.S 我正在使用三星Galaxy S7 Edge,相机中根本没有剩余图像计数。(或者我只是找不到)


2
我认为您可以检查DCIM目录(默认相机目录)中的文件数量,并计算所有文件的大小,然后通过将文件数量除以总大小来得出平均大小。
在Asynctask中执行以上步骤,您将获得相机捕捉图像的平均大小。
您已经计算了剩余大小(以字节为单位),现在再次将剩余大小除以平均大小,您将得到可以拍摄的大约图像数量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接