123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- //
- // UIImage+Ex.swift
- // TSLiveWallpaper
- //
- // Created by 100Years on 2024/12/23.
- //
- public extension UIImage {
-
- var width: CGFloat { size.width }
- var height: CGFloat { size.height }
-
- public func normalizedImage() -> UIImage? {
- if imageOrientation == .up {
- return self
- }
- return repaintImage()
- }
- public func repaintImage() -> UIImage? {
- let format = UIGraphicsImageRendererFormat()
- format.opaque = false
- format.scale = scale
- let renderer = UIGraphicsImageRenderer(size: size, format: format)
- let image = renderer.image { context in
- draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
- }
- return image
- }
- public func scaleToFillSize(size: CGSize, mode: UIView.ContentMode = .scaleToFill, scale: CGFloat = 0) -> UIImage? {
- if __CGSizeEqualToSize(self.size, size) {
- return self
- }
- let rect: CGRect
- let rendererSize: CGSize
- if mode == .scaleToFill {
- let isEqualRatio = size.width / size.height == width / height
- if isEqualRatio {
- rendererSize = size
- rect = CGRect(origin: .zero, size: size)
- }else {
- let scale = size.width / width
- var scaleHeight = scale * height
- var scaleWidth = size.width
- if scaleHeight < size.height {
- scaleWidth = size.height / scaleHeight * size.width
- scaleHeight = size.height
- }
- rendererSize = .init(width: scaleWidth, height: scaleHeight)
- rect = .init(origin: .zero, size: rendererSize)
- }
- }else {
- rendererSize = size
- if mode == .scaleAspectFit {
- rect = CGRect(origin: .zero, size: size)
- }else {
- var x: CGFloat = 0
- var y: CGFloat = 0
- let scale = size.width / width
- var scaleWidth = size.width
- var scaleHeight = scale * height
- if scaleHeight < size.height {
- scaleWidth = size.height / scaleHeight * scaleWidth
- scaleHeight = size.height
- }
- if scaleWidth < size.width {
- scaleHeight = size.width / scaleWidth * scaleHeight
- scaleWidth = size.width
- }
- x = -(scaleWidth - size.width) / 2
- y = -(scaleHeight - size.height) / 2
- rect = CGRect(
- x: x,
- y: y,
- width: scaleWidth,
- height: scaleHeight
- )
- }
- }
- let format = UIGraphicsImageRendererFormat()
- format.opaque = false
- format.scale = scale == 0 ? self.scale : scale
- let renderer = UIGraphicsImageRenderer(size: rendererSize, format: format)
- let image = renderer.image { context in
- draw(in: rect)
- }
- return image
- }
-
-
- public var pngImage:UIImage?{
- // 将 UIImage 转为 PNG Data
- guard let pngData = self.pngData() else {
- print("Failed to convert WebP image to PNG data.")
- return nil
- }
-
- // 使用 PNG Data 创建新的 UIImage
- return UIImage(data: pngData)
- }
- }
- public extension UIImage {
- /// 将颜色转换为 UIImage
- /// - Parameters:
- /// - color: 目标颜色
- /// - size: 图片尺寸(默认 1x1)
- /// - Returns: 转换后的 UIImage
- public static func colorFrom(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage? {
- // 创建一个矩形
- let rect = CGRect(origin: .zero, size: size)
-
- // 开始图形上下文
- UIGraphicsBeginImageContextWithOptions(size, false, 0)
-
- // 设置颜色填充
- color.setFill()
- UIRectFill(rect)
-
- // 获取生成的图片
- let image = UIGraphicsGetImageFromCurrentImageContext()
-
- // 结束图形上下文
- UIGraphicsEndImageContext()
-
- return image
- }
-
- public func resizableImage(capInsets:UIEdgeInsets) -> UIImage{
- return resizableImage(withCapInsets: capInsets, resizingMode: .stretch)
- }
-
-
-
- // 创建纯色图片
- convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
- let rect = CGRect(origin: .zero, size: size)
- UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
- color.setFill()
- UIRectFill(rect)
- let image = UIGraphicsGetImageFromCurrentImageContext()
- UIGraphicsEndImageContext()
-
- guard let cgImage = image?.cgImage else { return nil }
- self.init(cgImage: cgImage)
- }
-
- // 创建圆形图片
- static func circle(diameter: CGFloat, color: UIColor) -> UIImage {
- let size = CGSize(width: diameter, height: diameter)
- let renderer = UIGraphicsImageRenderer(size: size)
- return renderer.image { context in
- let rect = CGRect(origin: .zero, size: size)
- color.setFill()
- UIBezierPath(ovalIn: rect).fill()
- }
- }
- }
- public extension UIImage {
- var mirror: UIImage {
- // guard TSConfig.appLanguage.hasPrefix("ar"), let cgImage = self.cgImage else {
- guard let cgImage = self.cgImage else {
- return self
- }
- let image = UIImage(cgImage: cgImage, scale: self.scale, orientation: Orientation.upMirrored)
- return image.withRenderingMode(self.renderingMode)
- }
-
- func resize(to size: CGSize) -> UIImage? {
- UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
- self.draw(in: CGRect(origin: .zero, size: size))
- let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
- UIGraphicsEndImageContext()
- return resizedImage
- }
-
- func cropped(to aspectRatio: CGFloat) -> UIImage? {
- let originalSize = self.size
- let targetSize: CGSize
- if originalSize.width > originalSize.height {
- // 宽度大于高度,裁剪宽度
- targetSize = CGSize(width: originalSize.height, height: originalSize.height)
- } else {
- // 高度大于宽度,裁剪高度
- targetSize = CGSize(width: originalSize.width, height: originalSize.width)
- }
- let cropRect = CGRect(
- x: (originalSize.width - targetSize.width) / 2,
- y: (originalSize.height - targetSize.height) / 2,
- width: targetSize.width,
- height: targetSize.height
- )
- if let cgImage = self.cgImage?.cropping(to: cropRect) {
- return UIImage(cgImage: cgImage, scale: self.scale, orientation: self.imageOrientation)
- }
- return nil
- }
-
- /// 判断图片是否大于指定大小(默认10MB)
- func isLargerThan(byteSize: Int) -> Bool {
- // // 优先尝试JPEG压缩(更接近实际文件大小)
- // if let jpegData = self.jpegData(compressionQuality: 1.0) {
- // print("JPEG格式大小: \(Double(jpegData.count) / (1024 * 1024)) MB")
- // return jpegData.count > byteSize
- // }
-
- // 透明图片回退到PNG
- if let pngData = self.pngData() {
- print("PNG格式大小: \(Double(pngData.count) / (1024 * 1024)) MB")
- return pngData.count > byteSize
- }
-
- return false // 无法获取数据时默认不限制
- }
- }
- //旋转图片
- public extension UIImage {
- /// 按角度旋转图片
- /// - Parameter degrees: 旋转正数为顺时针,负数为逆时针)
- /// - Returns: 旋转后的新图片
- func rotated(byDegrees degrees: CGFloat) -> UIImage? {
- let radians = degrees * .pi / 180
- return rotated(byRadians: radians)
- }
-
- /// 按弧度旋转图片
- /// - Parameter radians: 旋转弧度
- /// - Returns: 旋转后的新图片
- func rotated(byRadians radians: CGFloat) -> UIImage? {
- // 计算旋转后的新边界大小
- let rotatedSize = CGRect(origin: .zero, size: size)
- .applying(CGAffineTransform(rotationAngle: radians))
- .integral.size
-
- // 开始图形上下文
- UIGraphicsBeginImageContextWithOptions(rotatedSize, false, scale)
- guard let context = UIGraphicsGetCurrentContext() else { return nil }
-
- // 移动和旋转坐标系
- context.translateBy(x: rotatedSize.width / 2, y: rotatedSize.height / 2)
- context.rotate(by: radians)
-
- // 绘制图像
- draw(in: CGRect(
- x: -size.width / 2,
- y: -size.height / 2,
- width: size.width,
- height: size.height
- ))
-
- // 获取旋转后的图像
- let rotatedImage = UIGraphicsGetImageFromCurrentImageContext()
- UIGraphicsEndImageContext()
-
- return rotatedImage
- }
-
- /// 固定角度旋转(90度、180度、270度)
- /// - Parameter rotation: 旋转角度
- /// - Returns: 旋转后的新图片
- func rotated(by rotation: Rotation) -> UIImage? {
- switch rotation {
- case .degrees90:
- return rotated(byDegrees: 90)
- case .degrees180:
- return rotated(byDegrees: 180)
- case .degrees270:
- return rotated(byDegrees: 270)
- }
- }
-
- // MARK: - 辅助类型
-
- enum Rotation {
- case degrees90
- case degrees180
- case degrees270
- }
-
- /// 保存图片到文件系统
- /// - Parameters:
- /// - url: 目标URL
- /// - compressionQuality: JPEG压缩质量(0.0-1.0)
- /// - Throws: 可能抛出错误
- func saveToFile(at url: URL, compressionQuality: CGFloat = 1.0) {
- guard let data = self.jpegData(compressionQuality: compressionQuality) else {
- debugPrint("无法转换为JPEG数据")
- return
- }
-
- do {
- try data.write(to: url)
- } catch {
- debugPrint(error)
- }
- }
- }
- public extension UIImage {
- // 压缩图片到指定尺寸
- func compressImageSize(to size: CGSize) -> UIImage {
- let targetSize = size
- if self.size.width > targetSize.width || self.size.height > targetSize.height {
- return kf.resize(to: targetSize)
- }
- return self
- }
-
- }
|