【问题标题】:Resize and compress images before uploading to Google Cloud storage在上传到 Google Cloud 存储之前调整图像大小和压缩图像
【发布时间】:2018-01-16 19:23:43
【问题描述】:

我制作了一个函数,可以在保持纵横比的同时将图像的大小调整为最大宽度和高度。此外,我正在根据 compressionQuality 压缩图像 - 我已经使用 3024x4032 jpeg 图像 @ 11.7 mb 对此进行了测试。

maxWidth = 800px
maxHeight = 1200px
compressionQuality = 0.5

该功能确实将图像大小从 11.7mb 减小到 0.51mb,但是宽度和高度没有正确减小。上传到 Firebase 后,图像的大小是 1600 x 2134 像素的两倍……但应该是 800x1066 像素(一半)

你能看出哪里不对吗?

import UIKit
import Foundation

class ImageEdit {
        static let instance = ImageEdit()

    func resizeAndCompressImageWith(image: UIImage, maxWidth: CGFloat, maxHeight: CGFloat, compressionQuality: CGFloat) -> Data? {

    let horizontalRatio = maxWidth / image.size.width
    let verticalRatio = maxHeight / image.size.height


    let ratio = min(horizontalRatio, verticalRatio)

    let newSize = CGSize(width: image.size.width * ratio, height: image.size.height * ratio)
    var newImage: UIImage

    if #available(iOS 10.0, *) {
        let renderFormat = UIGraphicsImageRendererFormat.default()
        renderFormat.opaque = false
        let renderer = UIGraphicsImageRenderer(size: CGSize(width: newSize.width, height: newSize.height), format: renderFormat)
        newImage = renderer.image {
            (context) in
            image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
        }
    } else {
        UIGraphicsBeginImageContextWithOptions(CGSize(width: newSize.width, height: newSize.height), true, 0)
        image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
        newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
    }

            let data = UIImageJPEGRepresentation(newImage, compressionQuality)



    return data

}

}

这是将图像上传到 firebase 的代码。

func uploadImageToFirebaseAndReturnImageURL(directory: String, image: UIImage!, maxWidth: CGFloat, maxHeight: CGFloat, compressionQuality: CGFloat, handler: @escaping(_ imageURL: String)  -> ()) {
        let imageName = NSUUID().uuidString // create unique image name

        if let uploadData = ImageEdit.instance.resizeAndCompressImageWith(image: image, maxWidth: maxWidth, maxHeight: maxHeight, compressionQuality: compressionQuality) {

            DB_STORE.child(directory).child(imageName).putData(uploadData, metadata: nil, completion: { (metadata, error) in

                if error != nil {
                    print(error ?? "Image upload failed for unknown reason")
                    return
                }

                // if URL exist, then return imageURL
                if let imageURL = metadata?.downloadURL()?.absoluteString {
                  handler (imageURL)


                }
                return

            })
        }



    }

【问题讨论】:

    标签: swift firebase uiimage resize compression


    【解决方案1】:

    我将您的代码复制到一个测试项目中,并添加了一些打印语句,并尝试使用 3360x2108 的原始尺寸调整图像的大小。 (注意:我在此测试代码中使用强制解包,但不建议将其用于任何生产代码)。

    这是我调用调整大小代码的函数:

    func resizeImage() {
        guard let image = UIImage.init(named: "landscape") else {
            return
        }
        print("Original Image Size: width: \(image.size.width) height: \(image.size.height)")
    
        let _ = ImageEdit.instance.resizeAndCompressImageWith(image: image, maxWidth: 800.0, maxHeight: 1200.0, compressionQuality: 0.5)
    }
    

    这是我的调整大小代码的更新版本。我只是在最后添加了一些代码来实例化一些图像实例,以便在转换后注销它们的实际大小:

    import UIKit
    
    class ImageEdit {
        static let instance = ImageEdit()
    
        func resizeAndCompressImageWith(image: UIImage, maxWidth: CGFloat, maxHeight: CGFloat, compressionQuality: CGFloat) -> Data? {
    
            let horizontalRatio = maxWidth / image.size.width
            let verticalRatio = maxHeight / image.size.height
    
    
            let ratio = min(horizontalRatio, verticalRatio)
            print("Image Ratio: \(ratio)")
    
            let newSize = CGSize(width: image.size.width * ratio, height: image.size.height * ratio)
            print("NewSize: \(String(describing: newSize))")
            var newImage: UIImage
    
            if #available(iOS 10.0, *) {
                print("UIGraphicsImageRendererFormat")
                let renderFormat = UIGraphicsImageRendererFormat.default()
                renderFormat.opaque = false
                let renderer = UIGraphicsImageRenderer(size: CGSize(width: newSize.width, height: newSize.height), format: renderFormat)
                newImage = renderer.image {
                    (context) in
                    image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
                }
            } else {
                print("UIGraphicsBeginImageContextWithOptions")
                UIGraphicsBeginImageContextWithOptions(CGSize(width: newSize.width, height: newSize.height), true, 0)
                image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
                newImage = UIGraphicsGetImageFromCurrentImageContext()!
                UIGraphicsEndImageContext()
            }
            print("NewImageSize: width: \(newImage.size.width) height: \(newImage.size.height)")
    
            let png = UIImagePNGRepresentation(newImage)
            let pngImg = UIImage.init(data: png!)!
            print("PNG - width: \(pngImg.size.width) - height: \(pngImg.size.height)")
    
            let data = UIImageJPEGRepresentation(newImage, compressionQuality)
            let jpgImg = UIImage.init(data: data!)!
            print("JPG - width: \(jpgImg.size.width) - height: \(jpgImg.size.height)")
    
            let fullData = UIImageJPEGRepresentation(newImage, 1.0)
            let jpgFull = UIImage.init(data: fullData!)!
            print("JPG FULL - width: \(jpgFull.size.width) - height: \(jpgFull.size.height)")
    
            return data
    
        }
    }
    

    在带有 iOS 11 的模拟器上运行它时,我会将它记录到调试器中:

    Original Image Size: width: 3360.0 height: 2108.0
    Image Ratio: 0.238095238095238
    NewSize: (800.0, 501.904761904762)
    UIGraphicsImageRendererFormat
    NewImageSize: width: 800.0 height: 502.0
    PNG - width: 2400.0 - height: 1506.0
    JPG - width: 2400.0 - height: 1506.0
    JPG FULL - width: 2400.0 - height: 1506.0
    

    如果我注释掉你的

    if #available(iOS 10.0, *) {
    

    block 我仍然看到相同的测量结果。

    所以看来newImage是直接从

    生成的
    UIGraphicsImageRendererFormat 
    or 
    UIGraphicsBeginImageContextWithOptions 
    

    生成您指定大小的图像。但是,由于某种原因,通过

    运行该图像
    UIImagePNGRepresentation(newImage)
    or
    UIImageJPEGRepresentation(newImage, compressionQuality)
    

    生成尺寸比原始图像大 3 倍的图像。即使我更新了

    UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
    to
    UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
    

    这似乎无关紧要。

    在我的测试用例中 UIScreen.main.scale = 3.0。

    因此,通过 PNG 或 JPEG 表示方法转换图像似乎将其乘以 UIScreen.main.scale 是由这些函数生成的最终图像大小。

    【讨论】:

    • 感谢您的努力。奇怪的是 UIScreen.main.scale 应该对缩放有影响......这是 Xcode 中的错误吗?
    • 我不确定,这对我来说没有意义,我今天会尝试更多。我注意到一件事,如果您在原始图像上运行 UIImagePNGRepresentation 或 UIImageJPEGRepresentation 而不首先通过调整大小操作运行它,则生成的图像大小与原始大小相同,而不是 3 倍大,这对我来说真的很奇怪。
    • 这里也一样,仍在尝试解决这个问题。
    【解决方案2】:

    我正在为我的项目做完全相同的功能。但是,我相信您当前的结果是预期的结果。由于您没有在 UIGraphicsBeginImageContextWithOptions 中设置 UIGraphicsImageRendererFormat.scale 或 scale 参数,因此它使用设备的主屏幕比例。通过将比例设置为 1.0,您可以使用所需的 CGSize 作为这些方法的输入,并获得所需的 UIImage 和 UIImagePNG/JPEGRepresentation 大小。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-25
      • 2017-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      • 2011-05-22
      • 1970-01-01
      相关资源
      最近更新 更多