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

463 lines
17 KiB
Swift
Raw Permalink 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
}
}
// UIImageDataGIF
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
}
}