70 lines
2.5 KiB
Swift
70 lines
2.5 KiB
Swift
//
|
||
// WeChatThumbImageProcessor.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import UIKit
|
||
|
||
/// 微信分享缩略图处理器,将图片压缩到微信 32KB 限制内。
|
||
enum WeChatThumbImageProcessor {
|
||
/// 微信缩略图最大字节数。
|
||
static let maxThumbBytes = 32 * 1024
|
||
/// 微信小程序预览图最大字节数。
|
||
static let maxMiniProgramHDImageBytes = 128 * 1024
|
||
|
||
/// 将图片压缩为符合微信要求的缩略图数据。
|
||
static func makeThumbData(from image: UIImage, maxBytes: Int = maxThumbBytes) -> Data? {
|
||
guard maxBytes > 0 else { return nil }
|
||
|
||
let resized = resize(image, maxPixel: 120)
|
||
var quality: CGFloat = 0.82
|
||
var data = resized.jpegData(compressionQuality: quality)
|
||
|
||
while let current = data, current.count > maxBytes, quality > 0.12 {
|
||
quality -= 0.1
|
||
data = resized.jpegData(compressionQuality: quality)
|
||
}
|
||
|
||
guard let result = data, result.count <= maxBytes else { return nil }
|
||
return result
|
||
}
|
||
|
||
/// 将图片压缩为符合微信小程序分享要求的高清预览图数据。
|
||
static func makeMiniProgramHDImageData(
|
||
from image: UIImage,
|
||
maxBytes: Int = maxMiniProgramHDImageBytes
|
||
) -> Data? {
|
||
guard maxBytes > 0 else { return nil }
|
||
|
||
let resized = resize(image, maxPixel: 500)
|
||
var quality: CGFloat = 0.86
|
||
var data = resized.jpegData(compressionQuality: quality)
|
||
|
||
while let current = data, current.count > maxBytes, quality > 0.12 {
|
||
quality -= 0.08
|
||
data = resized.jpegData(compressionQuality: quality)
|
||
}
|
||
|
||
guard let result = data, result.count <= maxBytes else { return nil }
|
||
return result
|
||
}
|
||
|
||
/// 等比缩放图片,使最长边不超过指定像素。
|
||
static func resize(_ image: UIImage, maxPixel: CGFloat) -> UIImage {
|
||
let sourceSize = image.size
|
||
guard sourceSize.width > 0, sourceSize.height > 0 else { return image }
|
||
|
||
let maxSide = max(sourceSize.width, sourceSize.height)
|
||
guard maxSide > maxPixel else { return image }
|
||
|
||
let scale = maxPixel / maxSide
|
||
let targetSize = CGSize(width: sourceSize.width * scale, height: sourceSize.height * scale)
|
||
let format = UIGraphicsImageRendererFormat.default()
|
||
format.scale = 1
|
||
let renderer = UIGraphicsImageRenderer(size: targetSize, format: format)
|
||
return renderer.image { _ in
|
||
image.draw(in: CGRect(origin: .zero, size: targetSize))
|
||
}
|
||
}
|
||
}
|