pogong
pogong

Reputation: 31

Converting a UIImage to the WebP format is extremely slow

Converting a UIImage to the WebP format is extremely slow. For a 2.5M HEIF photo with a compression ratio of 0.85, SDImageWebPCoder and libwebp take about 13.5 seconds.

SDImageWebPCoder

let webpCoder = SDImageWebPCoder.shared
var options: [SDImageCoderOption: Any] = [:]
options[SDImageCoderOption.encodeCompressionQuality] = 0.85
        
if let webpData = webpCoder.encodedData(with: image, format: .webP, options: options) 
{
       compressionImageData = webpData
}

libwebp

func convertToWebP(quality: CGFloat = 0.8) -> Data? {
    // 先检查 UIImage 是否能获取到 CGImage
    guard let cgImage = self.cgImage else { return nil }
    let width = Int32(cgImage.width)
    let height = Int32(cgImage.height)
    
    // 创建一个 ARGB 格式的位图上下文
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bytesPerPixel = 4
    let bytesPerRow = bytesPerPixel * Int(width)
    let bitmapInfo = CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
    guard let context = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else { return nil }
    
    // 将 CGImage 绘制到上下文中
    context.draw(cgImage, in: CGRect(x: 0, y: 0, width: Int(width), height: Int(height)))
    guard let pixelData = context.data else { return nil }
    
    // 转换为 WebP 数据
    var webpData: UnsafeMutablePointer<UInt8>?
    let qualityFactor = Float(quality * 100)
    let result = WebPEncodeRGBA(pixelData.assumingMemoryBound(to: UInt8.self), width, height, Int32(bytesPerRow), qualityFactor, &webpData)
    
    if result > 0 {
        let data = Data(bytes: webpData!, count: result)
        WebPFree(UnsafeMutableRawPointer(webpData))
        return data
    }
    return nil
}

Upvotes: 0

Views: 30

Answers (0)

Related Questions