【问题标题】:How to quickly estimate file sizes of resized images on iOS?如何在 iOS 上快速估计调整大小图像的文件大小?
【发布时间】:2012-09-16 18:56:15
【问题描述】:

在 Mail 中,当我添加图像并尝试发送它时,它会快速询问我要以哪种尺寸发送图像。见截图:

我想在要上传图片的应用中做类似的事情,并希望用户能够在上传之前调整图片大小。像Apple在这里所做的那样估计文件大小的最佳方法是什么?

实际上创建每个调整大小的图像只是为了检查它们的大小似乎需要很长时间。有没有更好的办法?

我确实找到了this Apple sample code,这有点帮助,但说实话有点不知所措。 :)

【问题讨论】:

  • 截图是全景图吗?那可能会抛出
  • 您确定这是估算而不是合同吗?所以这并不是说'媒介将是 X by Y;假设我们可以在 1.1 mb 中做到这一点,如果用户选择我们将在他们点击发送时试验压缩质量,直到我们得到 1.1 mb'?
  • 我不确定,不是 - 但实际文件大小稍后非常接近,但不等于我在该对话框中看到的估计值(?)。

标签: objective-c ios image cocoa-touch image-processing


【解决方案1】:

如果您将其存储到NSData,您可以调用[NSData length] 以获取包含的字节数,然后将其除以得到适当的大小(以 kB 或 MB 为单位)

【讨论】:

  • 这不考虑使用 JPG 进行压缩。
【解决方案2】:

我已经构建了一个可以调整图像大小的方法,如下所示:

-(UIImage *)resizeImage:(UIImage *)image width:(CGFloat)resizedWidth height:(CGFloat)resizedHeight
{
CGImageRef imageRef = [image CGImage];

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmap = CGBitmapContextCreate(NULL, resizedWidth, resizedHeight, 8, 4 * resizedWidth, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(bitmap, CGRectMake(0, 0, resizedWidth, resizedHeight), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage *result = [UIImage imageWithCGImage:ref];

CGContextRelease(bitmap);
CGImageRelease(ref);

return result;
}

要获得图片的大小,你必须将其转换为NSData,并询问长度:

 UIImage* actualImage = [UIImage imageNamed:@"image"];

NSData* actualImageData = UIImagePNGRepresentation(actualImage);

NSLog(@"Actual %f KB", (CGFloat)actualImageData.length / (CGFloat)1024);


UIImage* largeImage = [self resizeImage:actualImage width:actualImage.size.width * 0.8 height:actualImage.size.height * 0.8];

NSData* largeImageData = UIImagePNGRepresentation(largeImage);

NSLog(@"Large %f KB", (CGFloat)largeImageData.length / (CGFloat)1024);


UIImage* mediumImage = [self resizeImage:actualImage width:actualImage.size.width * 0.5 height:actualImage.size.height * 0.5];

NSData* mediumImageData = UIImagePNGRepresentation(mediumImage);

NSLog(@"Medium %f KB", (CGFloat)mediumImageData.length / (CGFloat)1024);


UIImage* smallImage = [self resizeImage:actualImage width:actualImage.size.width * 0.3 height:actualImage.size.height * 0.3];

NSData* smallImageData = UIImagePNGRepresentation(smallImage);

NSLog(@"Small %f KB", (CGFloat)smallImageData.length / (CGFloat)1024);

【讨论】:

    【解决方案3】:

    决定最终压缩图像大小的最大因素不是图像大小或 JPEG 压缩质量,而是图像复杂度(点燃熵)。如果您知道您总是要处理高度详细的照片(而不是纯色场或渐变),这会在一定程度上减少沿该维度的差异,但是...

    我花了相当多的时间对这个问题进行数值分析。我以 9 个不同的 JPEG 质量级别对一张详细的高分辨率图像的压缩图像大小进行了采样,该图像以 10 个百分点的增量缩小。这产生了一个描述隐式函数 z = (x, y) 的 3 维数据集,其中 x 是以像素为单位的缩放图像大小 (w*h),y 是 JPEG 压缩质量,z 是结果图像的大小以字节为单位。

    生成的表面很难估计。与直觉相反,它具有振荡和多个拐点,这意味着 x 和 y 中的 2 次函数不足以拟合它,并且增加多项式次数和创建自定义拟合函数并没有产生明显更好的结果。它不仅不是线性关系,甚至不是单调关系。这很复杂。

    让我们开始实践吧。请注意 Apple 何时提示您输入图像大小:当您点击“发送”时,而不是图像首次出现在邮件撰写视图中时。这可以让他们在必须准备好估计的图像尺寸之前撰写您的消息。所以我的怀疑是:他们做得很艰难。将图像缩放到不同大小可以在后台并行执行,即使在 iPhone 4 calibur 硬件上需要几秒钟,所有这些工作都可以对用户隐藏。如果您担心内存使用情况,您可以将图像写入临时文件并按顺序而不是并行渲染它们,这将使用不超过内存中未压缩文件的 2 倍的内存。

    总而言之:除非您对正在压缩的图像的预期熵有很多了解,否则对于某些类别的图像,任何估计函数都会非常不准确。如果你能处理好,那么对一些样本数据进行线性或二次拟合并产生一个用于估计目的的函数是相当容易的。但是,如果您想像 Apple 一样接近,您可能需要在后台进行实际的调整大小工作,因为构建一个始终正确的启发式方法的因素太多了。

    【讨论】:

    • 这也是我们所怀疑的,但您肯定不仅仅是“直觉”来支持它,谢谢。除非其他人提出解决方案,否则我将接受此答案并奖励您。
    【解决方案4】:

    邮件应用程序中提供的图像大小仅为估计值 - 发送图像的实际文件大小不同。将全尺寸图像(iPhone 4S 中为 3264 x 2448)转换为各种尺寸,只是为了获取文件大小也太慢了。

    [编辑]

    压缩文件大小不是线性的,因此您不能只获取 numPixels/filesize 来准确估计较小图像的文件大小。

    所以这个答案并非完全没用,这里是 Mail.app 导出的图像大小:

    小:320x240 中:640x480 大:1224x1632

    【讨论】:

    • 似乎不正确,因为正如您在屏幕截图中看到的那样,“大”超过 1MB,而“中”为 46KB - 尽管它只是图像大小的四分之一。似乎正在考虑压缩。
    【解决方案5】:

    您始终可以使用UIImageJPEGRepresentation 来压缩图像。四个选项可以是0.25、0.5、0.75和1.0范围内的值,其大小可以很容易地通过应用相同方法后的图像计算找到。

    【讨论】:

      猜你喜欢
      • 2016-08-18
      • 2011-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-29
      • 1970-01-01
      • 2020-06-14
      • 1970-01-01
      相关资源
      最近更新 更多