jsdw_ios/QuickLocation/Core/Extension/UIImage+Extension.swift

463 lines
17 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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..<count {
// 获取单帧图片
guard let cgImage = CGImageSourceCreateImageAtIndex(source, i, nil) else {
continue
}
let image = UIImage(cgImage: cgImage)
images.append(image)
// 累加每帧的持续时间
duration += UIImage.gifFrameDuration(source: source, index: i)
}
// 创建动画图片
return UIImage.animatedImage(with: images, duration: duration)
}
// 获取单帧的持续时间
private class func gifFrameDuration(source: CGImageSource, index: Int) -> 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
}
}