版本记录
版本号 | 时间 |
---|---|
V1.0 | 2019.10.21 星期一 |
前言
App中很多时候都需要进行图像处理,包括各种缩放、滤镜和压缩等处理,好的图像处理不仅可以提高App的性能,也会给用户带来耳目一新的感觉,这里重新开了一个专题,专门讲述对图像的各种处理。感兴趣的可以看下面几篇文章。
1. 图像处理相关(一) —— 图像深度相关处理简单示例(一)
2. 图像处理相关(二) —— HEIC图像压缩(一)
源码
1. Swift
首先看下工程组织结构
接着就是sb了
下面就是源码了
1. MainViewController.swift
import UIKit
class MainViewController: UIViewController {
@IBOutlet var jpgSizeLabel: UILabel!
@IBOutlet var jpgTimeLabel: UILabel!
@IBOutlet var jpgActivityIndicator: UIActivityIndicatorView!
@IBOutlet var jpgImageView: UIImageView!
@IBOutlet var heicSizeLabel: UILabel!
@IBOutlet var heicTimeLabel: UILabel!
@IBOutlet var heicActivityIndicator: UIActivityIndicatorView!
@IBOutlet var heicImageView: UIImageView!
@IBOutlet var compressionSlider: UISlider!
private let numberFormatter = NumberFormatter()
private let compressionQueue = OperationQueue()
private var previousQuality: Float = 0
private var originalImage: UIImage = #imageLiteral(resourceName: "jeremy-thomas-unsplash")
override func viewDidLoad() {
super.viewDidLoad()
title = "Compressor"
navigationItem.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .add,
target: self,
action: #selector(addButtonPressed)
)
navigationItem.leftBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .action,
target: self,
action: #selector(shareButtonPressed)
)
#if targetEnvironment(simulator)
compressionSlider.addTarget(
self,
action: #selector(sliderEndedTouch),
for: [.touchUpInside, .touchUpOutside]
)
#else
compressionSlider.addTarget(
self,
action: #selector(sliderDidChange),
for: .valueChanged
)
#endif
numberFormatter.maximumSignificantDigits = 1
numberFormatter.maximumFractionDigits = 3
updateImages()
}
// MARK: - Helpers
private func resetLabels() {
jpgSizeLabel.text = "--"
jpgTimeLabel.text = "--"
heicSizeLabel.text = "--"
heicTimeLabel.text = "--"
}
private func elapsedTime(from startDate: Date) -> String? {
let endDate = Date()
let interval = endDate.timeIntervalSince(startDate)
let intervalNumber = NSNumber(value: interval)
return numberFormatter.string(from: intervalNumber)
}
private func compressJPGImage(with quality: CGFloat) {
let startDate = Date()
jpgImageView.image = nil
jpgActivityIndicator.startAnimating()
compressionQueue.addOperation {
guard let data = self.originalImage.jpegData(compressionQuality: quality) else {
return
}
DispatchQueue.main.async {
if let time = self.elapsedTime(from: startDate) {
self.jpgTimeLabel.text = "\(time) s"
}
self.jpgSizeLabel.text = data.prettySize
self.jpgImageView.image = UIImage(data: data)
self.navigationItem.leftBarButtonItem?.isEnabled = true
UIView.animate(withDuration: 0.3) {
self.jpgActivityIndicator.stopAnimating()
}
}
}
}
private func compressHEICImage(with quality: CGFloat) {
let startDate = Date()
heicImageView.image = nil
heicActivityIndicator.startAnimating()
compressionQueue.addOperation {
do {
let data = try self.originalImage.heicData(compressionQuality: quality)
DispatchQueue.main.async {
if let time = self.elapsedTime(from: startDate) {
self.heicTimeLabel.text = "\(time) s"
}
self.heicSizeLabel.text = data.prettySize
self.heicImageView.image = UIImage(data: data)
self.navigationItem.leftBarButtonItem?.isEnabled = true
UIView.animate(withDuration: 0.3) {
self.heicActivityIndicator.stopAnimating()
}
}
} catch {
print("Error creating HEIC data: \(error.localizedDescription)")
}
}
}
private func updateImages() {
let quality = CGFloat(compressionSlider.value)
resetLabels()
compressionQueue.cancelAllOperations()
navigationItem.leftBarButtonItem?.isEnabled = false
compressJPGImage(with: quality)
compressHEICImage(with: quality)
}
private func shareImage(_ image: UIImage) {
let avc = UIActivityViewController(
activityItems: [image],
applicationActivities: nil
)
present(avc, animated: true)
}
// MARK: - Actions
@objc private func addButtonPressed() {
let picker = UIImagePickerController()
picker.delegate = self
present(picker, animated: true)
}
@objc private func shareButtonPressed() {
let avc = UIAlertController(title: "Share", message: "How would you like to share?", preferredStyle: .alert)
if let jpgImage = jpgImageView.image {
avc.addAction(UIAlertAction(title: "JPG", style: .default) { _ in
self.shareImage(jpgImage)
})
}
if let heicImage = heicImageView.image {
avc.addAction(UIAlertAction(title: "HEIC", style: .default) { _ in
self.shareImage(heicImage)
})
}
avc.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(avc, animated: true)
}
@objc private func sliderEndedTouch() {
updateImages()
}
@objc private func sliderDidChange() {
let diff = abs(compressionSlider.value - previousQuality)
guard diff > 0.1 else {
return
}
previousQuality = compressionSlider.value
updateImages()
}
}
extension MainViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true)
guard let image = info[.originalImage] as? UIImage else {
return
}
originalImage = image
updateImages()
}
}
2. UIImage+Additions.swift
import UIKit
import AVFoundation
extension UIImage {
enum HEICError: Error {
case heicNotSupported
case cgImageMissing
case couldNotFinalize
}
func heicData(compressionQuality: CGFloat) throws -> Data {
let data = NSMutableData()
guard let imageDestination =
CGImageDestinationCreateWithData(
data, AVFileType.heic as CFString, 1, nil
)
else {
throw HEICError.heicNotSupported
}
guard let cgImage = self.cgImage else {
throw HEICError.cgImageMissing
}
let options: NSDictionary = [
kCGImageDestinationLossyCompressionQuality: compressionQuality
]
CGImageDestinationAddImage(imageDestination, cgImage, options)
guard CGImageDestinationFinalize(imageDestination) else {
throw HEICError.couldNotFinalize
}
return data as Data
}
}
3. Data+Additions.swift
import Foundation
extension Data {
var prettySize: String {
let formatter = ByteCountFormatter()
formatter.countStyle = .binary
return formatter.string(fromByteCount: Int64(count))
}
}
后记
本篇主要讲述了HEIC图像压缩,感兴趣的给个赞或者关注~~~