我在我的iOS应用程序中遇到了一个与图像大小调整和上传相关的特殊问题.在上传到服务器之前,我实现了一种调整图像大小以适应特定大小范围(最小大小:320px,最大大小:1536px)的方法.调整大小似乎工作得很好,通过在调整大小后直接判断UIImage来验证这一点.然而,当我将调整大小的图像转换为数据(JPEG格式)以准备上传时,它似乎恢复到了原始大小或不保持调整后的尺寸.

下面是我正在使用的调整大小的方法:

func resizedImage(minimumSize: CGFloat, maximumSize: CGFloat) -> UIImage? {
    let originalWidth = size.width
    let originalHeight = size.height

    var scaleFactor: CGFloat
    var newWidth: CGFloat
    var newHeight: CGFloat

    if originalWidth < minimumSize || originalHeight < minimumSize {
        scaleFactor = max(minimumSize / originalWidth, minimumSize / originalHeight)
    } else if originalWidth > maximumSize || originalHeight > maximumSize {
        scaleFactor = min(maximumSize / originalWidth, maximumSize / originalHeight)
    } else {
        scaleFactor = 1.0
    }

    newWidth = originalWidth * scaleFactor
    newHeight = originalHeight * scaleFactor

    UIGraphicsBeginImageContextWithOptions(CGSize(width: newWidth, height: newHeight), false, 0)
    draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
    let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return resizedImage
}

在重新加载之后,当我试图将调整大小的UI Image转换为如下数据时:

if let resizedImage = resizedImage(minimumSize: 320, maximumSize: 1536) {
    let imageData = resizedImage.jpegData(compressionQuality: 1.0)
    // Proceed to upload imageData
}

尽管有了默认值,imageData似乎反映了原始图像的大小,而不是调整大小的一个.此问题发生在上传之前,在为请求主体准备图像数据期间.目标是确保上传到服务器的映像遵守指定的大小限制.在数据转换过程中,是否有什么我忽略了可能导致图像恢复到原始尺寸的东西?

任何关于如何确保调整大小的图像在转换为上传数据时保持其尺寸的建议或见解都将不胜感激.谢谢!

推荐答案

使用UIGraphicsBeginImageContextWithOptions和最后一个参数使用0的刻度,意味着它将使用设备的刻度.例如,如果在Retina 3 ×屏幕的设备上将一张图像渲染成UIGraphicsBeginImageContextWithOptions × UIGraphicsBeginImageContextWithOptions的大小,比例为0,则结果的UIImage将具有size的"逻辑维度",但它的scale将是3:这意味着结果的JPEG将是300 × 300px.

因此,不仅要判断结果图像的size,还要判断它的scale.简而言之,如果希望生成的图像与函数参数中指定的以像素为单位的预期最小/最大尺寸匹配,请考虑使用1而不是0的比例.


FWIW,UIGraphicsBeginImageContextWithOptions现在被弃用,并被替换为UIGraphicsImageRenderer.所以,如果你想用1的比例,也许:

extension UIImage {
    func resizedImage(minimumSize: CGFloat, maximumSize: CGFloat) -> UIImage {
        let originalWidth = size.width
        let originalHeight = size.height
        
        let resizeFactor: CGFloat = if originalWidth < minimumSize || originalHeight < minimumSize {
            max(minimumSize / originalWidth, minimumSize / originalHeight)
        } else if originalWidth > maximumSize || originalHeight > maximumSize {
            min(maximumSize / originalWidth, maximumSize / originalHeight)
        } else {
            1
        }
        
        let width = originalWidth * resizeFactor
        let height = originalHeight * resizeFactor
        
        let bounds = CGRect(x: 0, y: 0, width: width, height: height)

        let format = UIGraphicsImageRendererFormat()
        format.scale = 1
        
        return UIGraphicsImageRenderer(bounds: bounds, format: format).image { _ in
            draw(in: bounds)
        }
    }
}

Ios相关问答推荐

使用CGAffineTransform旋转视图只起作用一次吗?

当重新呈现UI时,嵌套的 struct 值如何与@Observable一起工作?

IFrame内容拒绝仅在iOS浏览器上加载-即使发布了内容-安全-策略(CSP)框架-祖先指令

快速相机放大手势不能正常工作

NSHashTable要求任何MyCustomProtocolAnyObject都是类类型

如何制作支持不同语言的iOS应用

在 Swift 中,对象如何被准确地从内存中移除?

使用按位|带有布尔操作数

使用 AVCaptureDeviceTypeBuiltInTripleCamera 时 Select 合适的相机进行条码扫描

使用 SceneKit 从 CapturedRoom.walls 重新创建 RoomPlan

UIViewRepresentable - MKMapView 没有得到更新

SwiftUI - 使用切换switch 切换键盘类型(默认/数字)?

SwiftUI:如何用拇指移动滑块值

Swift如何表示单位转换的标准大气压

如何在保持纵横比的同时zoom UIView 的内容以适应目标矩形?

Xcode 4.1 致命错误:自构建预编译头文件后修改了 stdlib

无法验证客户端 3000

Swift枚举继承

如何将 iPhone OSStatus 代码转换为有用的东西?

如果已安装,则重定向到应用程序,否则重定向到 App Store