在不重新采样的情况下裁剪 JPEG 图像

Cropping a JPEG image without resampling it

我的应用程序需要从磁盘读取 JPEG 文件,将其裁剪到已知区域,然后用不同的文件名保存。我当前的实现看起来像这样:

// open and crop the image
let image = CIImage(contentsOf: imagePath)
let cropRect = CGRect(x: 100, y: 100, width: 100, height: 100)
let croppedImage = image.cropped(to: cropRect)

// write to disk
let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)
let context = CIContext()
context.writeJPEGRepresentation(of: croppedImage, to: destination, colorSpace: colorSpace, options: [kCGImageDestinationLossyCompressionQuality as CIImageRepresentationOption: 1])

我发现即使我通过裁剪边缘来减小图像的尺寸,保存的文件也是原始文件的两倍大。我认为这是因为我正在对其重新采样以另存为新的 JPEG。我还注意到图像略有不同 - 可能不那么清晰。我当然可以调整压缩质量以减小文件大小,但这同样会影响图像质量。

有没有办法只裁剪已经压缩的 jpeg 文件而不增加文件大小或改变其任何其他特征?

您的方法看起来是正确的。由于 JPEG 压缩的性质,您不能 "just crop" 不解码的图像和 re-encoding 在处理过程中的图像。

较大的文件大小应该是由您选择的压缩质量造成的。引用文档:

A value of 1.0 specifies to use lossless compression if destination format supports it […]

1.0 质量的 JPEG 图像通常比 PNG 图像大。根据我的经验,介于 0.7 和 0.85 之间的值会产生良好的 quality-to-size 平衡。