swift 图片进行不失真压缩

2020-09-23  本文已影响0人  wsj_2012

// 图片压缩
func resetSizeOfImageData(_ sourceImage: UIImage, maxSize: NSInteger) -> Data? {
    //先判断当前质量是否满足要求,不满足再进行压缩
    var finalImageData = sourceImage.jpegData(compressionQuality: 1.0)
    guard let sizeOrigin = finalImageData?.count else {
        return nil
    }
    let sizeOriginKB = sizeOrigin  / 1000
    if sizeOriginKB <= maxSize {
        return finalImageData
    }
    // 获取原图片宽高比
    let sourceImageAepectRatio = sourceImage.size.width / sourceImage.size.height
    // 先调整分辨率
    var defaultSize = CGSize(width: 1024, height: 1024 / sourceImageAepectRatio)
    guard let newImage = newSizeImage(defaultSize, sourceImage: sourceImage) else { return nil }
    finalImageData = newImage.jpegData(compressionQuality: 1.0)
    
    // 保存压缩系数
    var compressionQualityArr: [CGFloat] = []
    let avg: CGFloat = 1.0 / 250
    var value = avg
    for i in (1...250).reversed() {
        value = CGFloat(i) * avg
        compressionQualityArr.append(value)
    }
    /*
     调整大小
     说明:压缩系数数组compressionQualityArr是从大到小存储。
     */
    //思路:使用二分法搜索
    guard let imageData = halfFunction(compressionQualityArr, image: newImage, finalImageData: finalImageData, maxSize: maxSize) else {
        return nil
    }
    //如果还是未能压缩到指定大小,则进行降分辨率
    while imageData.count == 0 {
        // 每次降100分辨率
        let reduceW: CGFloat = 100.0
        let reduceH = 100.0 / sourceImageAepectRatio
        if defaultSize.width - reduceW <= 0 || defaultSize.height - reduceH <= 0 {
            break
        }
        defaultSize = CGSize(width: defaultSize.width - reduceW, height: defaultSize.height - reduceH)
        guard let last = compressionQualityArr.last,
            let imgData = newImage.jpegData(compressionQuality: last),
            let img = UIImage(data: imgData) else {
            break
        }
        
        let image = newSizeImage(defaultSize, sourceImage: img)
        finalImageData = halfFunction(compressionQualityArr, image: image, finalImageData: image?.jpegData(compressionQuality: 1.0), maxSize: maxSize)
    }
    return finalImageData
}

// 调整图片分辨率/尺寸(等比例缩放)
func newSizeImage(_ size: CGSize, sourceImage: UIImage) -> UIImage? {
    var newSize = CGSize(width: sourceImage.size.width, height: sourceImage.size.height)
    let tempH = newSize.height / size.height
    let tempW = newSize.width / size.width
    if tempW > 1.0, tempW > tempH {
        newSize = CGSize(width: sourceImage.size.width / tempW, height: sourceImage.size.height / tempW)
    } else if tempH > 1.0, tempW < tempH {
        newSize = CGSize(width: sourceImage.size.width / tempH, height: sourceImage.size.height / tempH)
    }
    UIGraphicsBeginImageContext(newSize)
    sourceImage.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

func halfFunction(_ arr: [CGFloat], image: UIImage?, finalImageData: Data?, maxSize: NSInteger) -> Data? {
    var tempData = Data.init()
    var start = 0
    var end = arr.count - 1
    var index = 0
    var difference = NSInteger.max
    while start <= end {
        index = start + (end - start) / 2
        if let img = image, let finalImageData = img.jpegData(compressionQuality: arr[index]) {
            let sizeOrigin = finalImageData.count
            let sizeOriginKB = sizeOrigin / 1024
            print("当前降到质量\(sizeOriginKB)")
            print("\nstart:\(start)\nend:\(end)\nindex:\(index)\n压缩系数:\(String(format: "%.1f", arr[index]))")
            if sizeOriginKB > maxSize {
                start = index + 1
            } else if sizeOriginKB < maxSize {
                if maxSize - sizeOriginKB < difference {
                    difference = maxSize - sizeOriginKB
                    tempData = finalImageData
                }
                if index <= 0 {
                    break
                }
                end = index - 1
            }
        } else {
            break
        }
    }
    return tempData
}
上一篇下一篇

猜你喜欢

热点阅读