import Foundation import AVFoundation import UIKit import MozjpegBinding public func scaleImageToPixelSize(image: UIImage, size: CGSize) -> UIImage? { UIGraphicsBeginImageContextWithOptions(size, true, 1.0) image.draw(in: CGRect(origin: CGPoint(), size: size), blendMode: .copy, alpha: 1.0) let result = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return result } public func extractImageExtraScans(_ data: Data) -> [Int] { return extractJPEGDataScans(data).map { item in return item.intValue } } public func compressImageToJPEG(_ image: UIImage, quality: Float, tempFilePath: String) -> Data? { if let result = compressJPEGData(image, tempFilePath) { return result } let data = NSMutableData() guard let destination = CGImageDestinationCreateWithData(data as CFMutableData, "public.jpeg" as CFString, 1, nil) else { return nil } let options = NSMutableDictionary() options.setObject(quality as NSNumber, forKey: kCGImageDestinationLossyCompressionQuality as NSString) guard let cgImage = image.cgImage else { return nil } CGImageDestinationAddImage(destination, cgImage, options as CFDictionary) CGImageDestinationFinalize(destination) if data.length == 0 { return nil } return data as Data } public func compressImageToJPEGXL(_ image: UIImage, quality: Int) -> Data? { return compressJPEGXLData(image, Int32(quality)) } public func decompressImageFromJPEGXL(data: Data) -> UIImage? { return decompressJPEGXLData(data) } @available(iOSApplicationExtension 11.0, iOS 11.0, *) public func compressImage(_ image: UIImage, quality: Float) -> Data? { let data = NSMutableData() guard let destination = CGImageDestinationCreateWithData(data as CFMutableData, AVFileType.heic as CFString, 1, nil) else { return nil } let options = NSMutableDictionary() options.setObject(quality as NSNumber, forKey: kCGImageDestinationLossyCompressionQuality as NSString) guard let cgImage = image.cgImage else { return nil } CGImageDestinationAddImage(destination, cgImage, options as CFDictionary) CGImageDestinationFinalize(destination) if data.length == 0 { return nil } return data as Data } public enum MiniThumbnailType { case image case avatar } public func compressImageMiniThumbnail(_ image: UIImage, type: MiniThumbnailType = .image) -> Data? { switch type { case .image: return compressMiniThumbnail(image, CGSize(width: 40.0, height: 40.0)) case .avatar: var size: CGFloat = 8.0 var data = compressMiniThumbnail(image, CGSize(width: size, height: size)) while true { size += 1.0 if let candidateData = compressMiniThumbnail(image, CGSize(width: size, height: size)) { if candidateData.count >= 32 { break } else { data = candidateData } } else { break } } return data } }