如何使用 af_imageAspectScaled 缩放到所需的像素大小

How to scale to desired size in pixels using af_imageAspectScaled

我正在使用 AlamoFireImage 在将用户个人资料图片发送到服务器之前裁剪它。我们的服务器有一些限制,我们不能发送大于 640x640 的图片。

我正在使用 af_imageAspectScaled UIImage 扩展函数,如下所示:

let croppedImage = image.af_imageAspectScaled(
  toFill: CGSize(
    width: 320,
    height: 320
  )
)

我原以为这会将 image 裁剪为 320 像素 x 320 像素的图像。但是我发现输出图像被保存为比例为 2.0 的 640x640px 图像。以下 XCTest 显示了这一点:

class UIImageTests: XCTestCase {
  func testAfImageAspectScaled() {
    if let image = UIImage(
      named: "ipad_mini2_photo_1.JPG",
      in: Bundle(for: type(of: self)),
      compatibleWith: nil
    ) {
      print (image.scale) // prints 1.0
      print (image.size)  // prints (1280.0, 960.0)

      let croppedImage = image.af_imageAspectScaled(
        toFill: CGSize(
          width: 320,
          height: 320
        )
      )

      print (croppedImage.scale) // prints 2.0
      print (croppedImage.size)  // prints (320.0, 320.0)
    }  
  }
}

我 运行 在 iPhone Xr 模拟器上 Xcode 10.2.

原始图像为 1280 x 960 点,比例为 1,相当于 1280 x 960 像素。裁剪后的图像为 320 x 320 点,比例为 2,相当于 640 x 640 像素。

为什么比例设置为2?我可以改变吗?如何生成独立于比例和设备的 320 x 320 像素图像?

好吧,检查 source code for the af_imageAspectScaled method 我发现了以下用于生成实际缩放图像的代码:

UIGraphicsBeginImageContextWithOptions(size, af_isOpaque, 0.0)
draw(in: CGRect(origin: origin, size: scaledSize))
let scaledImage = UIGraphicsGetImageFromCurrentImageContext() ?? self
UIGraphicsEndImageContext()

UIGraphicsBeginImageContextWithOptions 上参数值为 0.0 告诉该方法使用主屏幕比例因子来定义图像大小。

我尝试将其设置为 1.0,当 运行 我的测试用例时,af_imageAspectScaled 生成了一张具有我想要的正确尺寸的图像。

Here 有一个 table 显示所有 iOS 设备分辨率。我的应用程序正在为比例因子为 2.0 的所有设备发送适当大小的图像,但是有几个设备的比例因子为 3.0。对于那些应用程序无法运行的人。

嗯,不幸的是,如果我想使用 af_imageAspectScaled,我必须在像这样设置缩放尺寸时将我想要的最终尺寸除以设备的比例:

let scale = UIScreen.main.scale

let croppedImage = image.af_imageAspectScaled(
  toFill: CGSize(
    width: 320/scale,
    height: 320/scale
  )
)

I've sent a pull request to AlamofireImage提议在函数af_imageAspectScaled(toFill:)af_imageAspectScaled(toFit:)af_imageScaled(to:)中增加一个参数scale。如果他们接受了,上面的代码应该变成:

// this is not valid with Alamofire 4.0.0 yet! waiting for my pull request to
// be accepted
let croppedImage = image.af_imageAspectScaled(
  toFill: CGSize(
    width: 320,
    height: 320
  ),
  scale: 1.0
)
// croppedImage would be a 320px by 320px image, regardless of the device type.