// // UIImage+Extension.swift // GXM-CRM // // Created by XUXIAOTENG on 06/02/2018. // Copyright © 2018 GuoXiaoMei. All rights reserved. // import Foundation import UIKit public extension UIImage { func blend(with color: UIColor) -> UIImage? { UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale) let context = UIGraphicsGetCurrentContext()! let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height) // Unflip the image context.translateBy(x: 0, y: size.height) context.scaleBy(x: 1.0, y: -1.0) context.setBlendMode(.overlay) context.draw(cgImage!, in: rect) context.setFillColor(color.cgColor) context.fill(rect) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage } func blurImage(radius: CGFloat) -> UIImage { let inputImage = CIImage(image: self)! let parameters: [String: Any] = [ kCIInputRadiusKey: radius, kCIInputImageKey: inputImage ] let filter = CIFilter(name: "CIGaussianBlur", parameters: parameters)! let cgimg = CIContext().createCGImage(filter.outputImage!, from: inputImage.extent) return UIImage(cgImage: cgimg!) } func saveToTemp(fileName: String) -> String? { let dirURL = URL(fileURLWithPath: NSTemporaryDirectory()) let tempURL = dirURL.appendingPathComponent("GXM") let fileURL = tempURL.appendingPathComponent(fileName).appendingPathExtension("jpg") // 创建CRM目录 if !FileManager.default.fileExists(atPath: tempURL.path) { do { try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: false, attributes: nil) } catch { print("目录创建失败: \(error)") ProgressHUD.showError(withStatus: error.localizedDescription) } } if FileManager.default.fileExists(atPath: fileURL.path) { do { try FileManager.default.removeItem(at: fileURL) } catch { print("文件删除失败:\(error)") ProgressHUD.showError(withStatus: error.localizedDescription) } } if let data = self.jpegData(compressionQuality: 1.0) { do { try data.write(to: fileURL) return fileURL.path } catch { print("文件保存失败:\(error)") ProgressHUD.showError(withStatus: error.localizedDescription) } } return nil } // Thumbnail image func thumbnail(size: CGFloat) -> UIImage { let scale = UIScreen.main.scale let length = size * scale let thumbnail = resizeTo(CGSize(width: length, height: length), scale: false) ?? self return thumbnail } func resizeTo(_ size: CGSize) -> UIImage? { guard let imgRef = cgImage else { return self } let srcSize = CGSize(width: imgRef.width, height: imgRef.height) var dstSize = size // Don't resize guard !(srcSize.equalTo(dstSize)) else { return self } let scaleRatio: CGFloat = dstSize.width / srcSize.width let orient = imageOrientation var transform = CGAffineTransform.identity switch orient { case .up: //EXIF = 1 transform = CGAffineTransform.identity case .upMirrored: //EXIF = 2 transform = CGAffineTransform(translationX: srcSize.width, y: 0) transform = transform.scaledBy(x: -1.0, y: 1.0) case .down: //EXIF = 3 transform = CGAffineTransform(translationX: srcSize.width, y: srcSize.height) transform = transform.rotated(by: CGFloat.pi) case .downMirrored: //EXIF = 4 transform = CGAffineTransform(translationX: 0, y: srcSize.height) transform = transform.scaledBy(x: 1.0, y: -1.0) case .leftMirrored: //EXIF = 5 dstSize = CGSize(width: dstSize.height, height: dstSize.width) transform = CGAffineTransform(translationX: srcSize.height, y: srcSize.width) transform = transform.scaledBy(x: -1.0, y: 1.0) transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0) case .left: //EXIF = 6 dstSize = CGSize(width: dstSize.height, height: dstSize.width) transform = CGAffineTransform(translationX: 0.0, y: srcSize.width) transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0) case .rightMirrored: //EXIF = 7 dstSize = CGSize(width: dstSize.height, height: dstSize.width) transform = CGAffineTransform(scaleX: -1.0, y: 1.0) transform = transform.rotated(by: CGFloat.pi / 2.0) case .right: //EXIF = 8 dstSize = CGSize(width: dstSize.height, height: dstSize.width) transform = CGAffineTransform(translationX: srcSize.height, y: 0) transform = transform.rotated(by: CGFloat.pi / 2.0) @unknown default: break } // Draw the image on a new context, applying a transform matrix UIGraphicsBeginImageContextWithOptions(dstSize, false, scale) guard let context = UIGraphicsGetCurrentContext() else { return nil } if orient == .right || orient == .left { context.scaleBy(x: -scaleRatio, y: scaleRatio) context.translateBy(x: -srcSize.height, y: 0) } else { context.scaleBy(x: scaleRatio, y: -scaleRatio) context.translateBy(x: 0, y: -srcSize.height) } context.concatenate(transform) let rect = CGRect(x: 0, y: 0, width: srcSize.width, height: srcSize.height) context.draw(imgRef, in: rect) let resizedImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return resizedImage } func resizeTo(_ size: CGSize, scale: Bool) -> UIImage? { guard let imgRef = cgImage else { return self } let srcSize = CGSize(width: imgRef.width, height: imgRef.height) var boundingSize = size let orient = self.imageOrientation switch orient { case .left, .right, .leftMirrored, .rightMirrored: boundingSize = CGSize(width: boundingSize.height, height: boundingSize.width) default: // NOP break } // Compute the target CGRect var dstSize: CGSize if !scale && srcSize.width < boundingSize.width && srcSize.height < boundingSize.height { // no resize (draw the image anyway to take image orientation into account) dstSize = srcSize } else { let wRatio = boundingSize.width / srcSize.width let hRatio = boundingSize.height / srcSize.height if wRatio < hRatio { dstSize = CGSize(width: boundingSize.width, height: CGFloat(floorf(Float(srcSize.height * wRatio)))) } else { dstSize = CGSize(width: CGFloat(floorf(Float(srcSize.width * hRatio))), height: boundingSize.height) } } return resizeTo(dstSize) } } public extension UIImage { func scaledWidth(for height: CGFloat) -> CGFloat { return height * size.width / size.height } func scaledHeight(for width: CGFloat) -> CGFloat { return width * size.height / size.width } } public extension UIImage { /// 更改图片颜色/大小 /// - Parameters: /// - tintColor: 颜色 /// - scaleSize: 缩放size /// - blendMode: 默认destinationIn /// - Returns: 图片 func image(tintColor: UIColor, scaleSize : CGSize, blendMode: CGBlendMode = .destinationIn) -> UIImage? { let tempSize = scaleSize == .zero ? size : scaleSize UIGraphicsBeginImageContextWithOptions(tempSize, false, 0.0) // 更改图片大小 let bounds = CGRect(x: 0, y: 0, width: tempSize.width, height: tempSize.height) // 更改图片颜色 tintColor.setFill() UIRectFill(bounds) draw(in: bounds, blendMode: blendMode, alpha: 1.0) guard let tintImage = UIGraphicsGetImageFromCurrentImageContext() else { return self } UIGraphicsEndImageContext() return tintImage } /// 更改图片颜色 /// - Parameters: /// - tintColor: 颜色 /// - blendMode: 默认destinationIn /// - Returns: 图片 func image(tintColor: UIColor, blendMode: CGBlendMode = .destinationIn) -> UIImage? { UIGraphicsBeginImageContextWithOptions(size, false, 0.0) let bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height) // 更改图片颜色 tintColor.setFill() UIRectFill(bounds) draw(in: bounds, blendMode: blendMode, alpha: 1.0) guard let tintImage = UIGraphicsGetImageFromCurrentImageContext() else { return self } UIGraphicsEndImageContext() return tintImage } /// 更改图片大小 /// - Parameters: /// - scaleSize: 缩放size /// - blendMode: 默认destinationIn /// - Returns: 图片 func image(scaleSize : CGSize, blendMode: CGBlendMode = .destinationIn) -> UIImage? { let tempSize = scaleSize == .zero ? size : scaleSize UIGraphicsBeginImageContextWithOptions(tempSize, false, 0.0) // 更改图片大小 let bounds = CGRect(x: 0, y: 0, width: tempSize.width, height: tempSize.height) UIRectFill(bounds) draw(in: bounds, blendMode: blendMode, alpha: 1.0) guard let tintImage = UIGraphicsGetImageFromCurrentImageContext() else { return self } UIGraphicsEndImageContext() return tintImage } /// 生成颜色图片 /// - Parameter color: 颜色 /// - Returns: UIImage static func colorImage(with color: UIColor) -> UIImage? { var image: UIImage? let rect = CGRect(origin: .zero, size: CGSize(width: 1, height: 1)) UIGraphicsBeginImageContextWithOptions(rect.size, false, 0) if let context = UIGraphicsGetCurrentContext() { context.setFillColor(color.cgColor) context.fill(rect) image = UIGraphicsGetImageFromCurrentImageContext() } UIGraphicsEndImageContext() return image } } // MARK: - 旋转图片 extension UIImage { /// 图片镜像处理 public var adaptiveImage: UIImage? { guard let cgImage = cgImage else { return nil } let flippedImage = UIImage(cgImage: cgImage, scale: scale, orientation: UIView.appearance().semanticContentAttribute == .forceRightToLeft ? .upMirrored : .up) return flippedImage } } // MARK: - 压缩图片 extension UIImage { public func compressImage(maxSize: CGFloat) -> Data? { var imageData = self.jpegData(compressionQuality: 1.0) if imageData?.count ?? 0 > Int(maxSize) { var compressionQuality = 1.0 let sizeRatio = self.size.width / self.size.height var resizedImage = resizeImage(image: self, targetSize: CGSize(width: 360, height: 360 / sizeRatio)) imageData = resizedImage?.jpegData(compressionQuality: compressionQuality) while imageData?.count ?? 0 > Int(maxSize) { compressionQuality -= 0.1 // resizedImage = resizeImage(image: resizedImage!, targetSize: CGSize(width: resizedImage!.size.width, // height: resizedImage!.size.height)) imageData = resizedImage?.jpegData(compressionQuality: compressionQuality) } } return imageData } private func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? { let size = image.size // let widthRatio = targetSize.width / size.width // let heightRatio = targetSize.height / size.height // // let newSize: CGSize // if widthRatio > heightRatio { // newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio) // } else { // newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio) // } UIGraphicsBeginImageContextWithOptions(targetSize, false, 0.0) image.draw(in: CGRect(origin: CGPoint.zero, size: targetSize)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage } } // 修复图片旋转 extension UIImage { public func fixOrientation() -> UIImage { if self.imageOrientation == .up { return self } var transform = CGAffineTransform.identity switch self.imageOrientation { case .down, .downMirrored: transform = transform.translatedBy(x: self.size.width, y: self.size.height) transform = transform.rotated(by: .pi) break case .left, .leftMirrored: transform = transform.translatedBy(x: self.size.width, y: 0) transform = transform.rotated(by: .pi / 2) break case .right, .rightMirrored: transform = transform.translatedBy(x: 0, y: self.size.height) transform = transform.rotated(by: -.pi / 2) break default: break } switch self.imageOrientation { case .upMirrored, .downMirrored: transform = transform.translatedBy(x: self.size.width, y: 0) transform = transform.scaledBy(x: -1, y: 1) break case .leftMirrored, .rightMirrored: transform = transform.translatedBy(x: self.size.height, y: 0); transform = transform.scaledBy(x: -1, y: 1) break default: break } let ctx = CGContext(data: nil, width: Int(self.size.width), height: Int(self.size.height), bitsPerComponent: self.cgImage!.bitsPerComponent, bytesPerRow: 0, space: self.cgImage!.colorSpace!, bitmapInfo: self.cgImage!.bitmapInfo.rawValue) ctx?.concatenate(transform) switch self.imageOrientation { case .left, .leftMirrored, .right, .rightMirrored: ctx?.draw(self.cgImage!, in: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(size.height), height: CGFloat(size.width))) break default: ctx?.draw(self.cgImage!, in: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(size.width), height: CGFloat(size.height))) break } let cgimg: CGImage = (ctx?.makeImage())! let img = UIImage(cgImage: cgimg) return img } } // UIImage扩展:支持从Data创建GIF动画 extension UIImage { class func gifImageWithData(_ data: Data) -> UIImage? { // 创建图片源 guard let source = CGImageSourceCreateWithData(data as CFData, nil) else { return nil } let count = CGImageSourceGetCount(source) var images = [UIImage]() var duration: TimeInterval = 0 // 遍历所有帧 for i in 0.. TimeInterval { let defaultDuration = 0.1 guard let properties = CGImageSourceCopyPropertiesAtIndex(source, index, nil) as? [AnyHashable: Any] else { return defaultDuration } guard let gifProperties = properties[kCGImagePropertyGIFDictionary as String] as? [AnyHashable: Any] else { return defaultDuration } // 处理GIF的延迟时间 if let delayTime = gifProperties[kCGImagePropertyGIFDelayTime as String] as? TimeInterval { return delayTime > 0 ? delayTime : defaultDuration } return defaultDuration } }