Skip to content

Commit

Permalink
0.2.4: 1.优化代码;2.正确获取视图信息(主线程获取)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rogue24 committed Oct 26, 2023
1 parent b3723df commit ec176fb
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 190 deletions.
4 changes: 2 additions & 2 deletions JPCrop.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Pod::Spec.new do |s|
s.name = 'JPCrop'
s.version = '0.2.3'
s.version = '0.2.4'
s.summary = 'A clipping tool that can fine tune the direction of rotation.'

# This description is used to generate tags and improve search results.
Expand All @@ -28,7 +28,7 @@ Pod::Spec.new do |s|
s.source = { :git => 'https://github.com/Rogue24/JPCrop.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

s.ios.deployment_target = '9.0'
s.ios.deployment_target = '11.0'

s.source_files = 'JPCrop/Classes/**/*'

Expand Down
64 changes: 25 additions & 39 deletions JPCrop/Classes/Croper+API.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
//
// API.swift
// Croper+API.swift
// JPCrop
//
// Created by Rogue24 on 2022/3/5.
//

// MARK: - 公开API
import UIKit

public extension Croper {

// MARK: 获取同步的Configure(当前的裁剪元素、状态)
/// 获取同步的Configure,可用于保存当前的裁剪状态,下一次打开恢复状态
func syncConfigure() -> Configure {
Configure(image,
cropWHRatio: cropWHRatio,
originAngle: originAngle,
angle: angle,
zoomScale: scrollView.zoomScale,
contentOffset: scrollView.contentOffset)
// MARK: 获取当前的Configure(当前的裁剪元素、状态)
/// 获取当前的`Configure`,可用于保存当前的裁剪状态,下一次打开恢复状态
func getCurrentConfigure() -> Configure {
var configure = Configure(image,
cropWHRatio: cropWHRatio,
originAngle: originAngle,
angle: angle)

Self.executeInMainQueue {
configure.zoomScale = self.scrollView.zoomScale
configure.contentOffset = self.scrollView.contentOffset
}

return configure
}

// MARK: 旋转
Expand Down Expand Up @@ -72,26 +77,28 @@ public extension Croper {
// MARK: 显示旋转网格
/// 显示旋转时的网格数
func showRotateGrid(animated: Bool = false) {
updateGrid(0, 1, animated: animated)
updateGridAlpha(0, 1, animated: animated)
}

// MARK: 隐藏旋转网格
/// 隐藏旋转时的网格数
func hideRotateGrid(animated: Bool = false) {
updateGrid(1, 0, animated: animated)
updateGridAlpha(1, 0, animated: animated)
}

// MARK: 恢复
/// 恢复:【调整角度 = 0】+【缩放比例 = 1】+【中心点】
func recover(animated: Bool = false) {
angle = 0

let factor = fitFactor()
let updateScrollView = {
self.scrollView.zoomScale = 1
self.scrollView.transform = factor.transform
self.scrollView.contentInset = factor.contentInset
self.scrollView.contentOffset = self.fitOffset(CGPoint(x: 0.5, y: 0.5), contentInset: factor.contentInset)
}

if animated {
UIView.animate(withDuration: Self.animDuration, delay: 0, options: .curveEaseOut, animations: updateScrollView, completion: nil)
} else {
Expand All @@ -105,17 +112,8 @@ public extension Croper {
/// - compressScale: 压缩比例,默认为1,即原图尺寸
func crop(_ compressScale: CGFloat = 1) -> UIImage? {
guard let imageRef = image.cgImage else { return nil }

let fromPoint = CGPoint(x: cropFrame.origin.x, y: cropFrame.maxY)
let convertTranslate = borderLayer.convert(fromPoint, to: imageView.layer)

return Self.crop(compressScale,
imageRef,
cropWHRatio > 0 ? cropWHRatio : fitCropWHRatio(imageWHRatio),
scaleValue(scrollView.transform) * scrollView.zoomScale,
convertTranslate,
actualRadian,
imageView.bounds.height)
let factor = getCropFactorSafely()
return Self.crop(compressScale, imageRef, factor)
}

// MARK: 异步裁剪
Expand All @@ -124,26 +122,14 @@ public extension Croper {
/// - compressScale: 压缩比例,默认为1,即原图尺寸
func asyncCrop(_ compressScale: CGFloat = 1, _ cropDone: @escaping (UIImage?) -> ()) {
guard let imageRef = image.cgImage else {
DispatchQueue.main.async { cropDone(nil) }
Self.executeInMainQueue(isAsync: true) { cropDone(nil) }
return
}

let cropWHRatio = self.cropWHRatio > 0 ? self.cropWHRatio : fitCropWHRatio(imageWHRatio)
let scale = scaleValue(scrollView.transform) * scrollView.zoomScale
let convertTranslate = borderLayer.convert(CGPoint(x: cropFrame.origin.x, y: cropFrame.maxY), to: imageView.layer)
let radian = actualRadian
let height = imageView.bounds.height

let factor = getCropFactorSafely()
DispatchQueue.global().async {
let result = Self.crop(compressScale,
imageRef,
cropWHRatio,
scale,
convertTranslate,
radian,
height)
let result = Self.crop(compressScale, imageRef, factor)
DispatchQueue.main.async { cropDone(result) }
}
}

}
41 changes: 23 additions & 18 deletions JPCrop/Classes/Croper+Calculation.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Calculation.swift
// Croper+Calculation.swift
// JPCrop_Example
//
// Created by Rogue24 on 2020/12/26.
Expand All @@ -8,26 +8,28 @@
import UIKit

extension Croper {
func scaleValue(_ t: CGAffineTransform) -> CGFloat {
sqrt(t.a * t.a + t.c * t.c)
}

func fitCropWHRatio(_ cropWHRatio: CGFloat, isCallBack: Bool = false) -> CGFloat {
let range = Self.cropWHRatioRange
if cropWHRatio <= 0 {
return 0
}

if cropWHRatio < range.lowerBound {
if isCallBack, let overstep = cropWHRatioRangeOverstep {
overstep(false, range.lowerBound)
}

return cropWHRatio <= 0 ? 0 : range.lowerBound
let range = Self.cropWHRatioRange
if range.contains(cropWHRatio) {
return cropWHRatio
}

if cropWHRatio > range.upperBound {
if isCallBack, let overstep = cropWHRatioRangeOverstep {
overstep(true, range.upperBound)
}

return range.upperBound
let isUpper = cropWHRatio > range.upperBound
let bound = isUpper ? range.upperBound : range.lowerBound

if isCallBack, let overstep = cropWHRatioRangeOverstep {
overstep(isUpper, bound)
}

return cropWHRatio
return bound
}

func fitAngle(_ angle: CGFloat) -> CGFloat {
Expand Down Expand Up @@ -63,6 +65,7 @@ extension Croper {
func fitImageSize() -> CGSize {
var imageW: CGFloat
var imageH: CGFloat

if isLandscapeImage {
imageH = cropFrame.height
imageW = imageH * imageWHRatio
Expand All @@ -78,6 +81,7 @@ extension Croper {
imageW = imageH * imageWHRatio
}
}

return CGSize(width: imageW, height: imageH)
}

Expand Down Expand Up @@ -128,9 +132,10 @@ extension Croper {
let bottom = verMargin + minMargin.bottom
let right = horMargin + minMargin.right

return (scale,
CGAffineTransform(rotationAngle: actualRadian).scaledBy(x: scale, y: scale),
UIEdgeInsets(top: top, left: left, bottom: bottom, right: right))
let transform = CGAffineTransform(rotationAngle: actualRadian).scaledBy(x: scale, y: scale)
let contentInset = UIEdgeInsets(top: top, left: left, bottom: bottom, right: right)

return RotateFactor(scale: scale, transform: transform, contentInset: contentInset)
}

func fitOffset(_ contentScalePoint: CGPoint, contentSize: CGSize? = nil, contentInset: UIEdgeInsets? = nil) -> CGPoint {
Expand Down
98 changes: 98 additions & 0 deletions JPCrop/Classes/Croper+Crop.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// Croper+Crop.swift
// JPCrop
//
// Created by Rogue24 on 2022/3/5.
//

import UIKit

extension Croper {
func getCropFactorSafely() -> CropFactor {
var ratio: CGFloat = 0
var scale: CGFloat = 0
var translate: CGPoint = .zero
var radian: CGFloat = 0
var height: CGFloat = 0

Self.executeInMainQueue {
ratio = self.cropWHRatio > 0 ? self.cropWHRatio : self.fitCropWHRatio(self.imageWHRatio)
scale = self.scaleValue(self.scrollView.transform) * self.scrollView.zoomScale
translate = self.borderLayer.convert(CGPoint(x: self.cropFrame.origin.x, y: self.cropFrame.maxY), to: self.imageView.layer)
radian = self.actualRadian
height = self.imageView.bounds.height
}

return CropFactor(cropWHRatio: ratio,
scale: scale,
convertTranslate: translate,
radian: radian,
imageBoundsHeight: height)
}

static func crop(_ compressScale: CGFloat,
_ imageRef: CGImage,
_ factor: CropFactor) -> UIImage? {
let width = CGFloat(imageRef.width) * compressScale
let height = CGFloat(imageRef.height) * compressScale

// 获取裁剪尺寸和裁剪区域
let cropWHRatio = factor.cropWHRatio
var rendSize: CGSize
if width > height {
rendSize = CGSize(width: height * cropWHRatio, height: height)
if rendSize.width > width {
rendSize = CGSize(width: width, height: width / cropWHRatio)
}
} else {
rendSize = CGSize(width: width, height: width / cropWHRatio)
if rendSize.height > height {
rendSize = CGSize(width: height * cropWHRatio, height: height)
}
}

var bitmapRawValue = CGBitmapInfo.byteOrder32Little.rawValue
let alphaInfo = imageRef.alphaInfo
if alphaInfo == .premultipliedLast ||
alphaInfo == .premultipliedFirst ||
alphaInfo == .last ||
alphaInfo == .first {
bitmapRawValue += CGImageAlphaInfo.premultipliedFirst.rawValue
} else {
bitmapRawValue += CGImageAlphaInfo.noneSkipFirst.rawValue
}

guard let context = CGContext(data: nil,
width: Int(rendSize.width),
height: Int(rendSize.height),
bitsPerComponent: 8,
bytesPerRow: 0,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: bitmapRawValue) else { return nil }

let scale = factor.scale
let radian = factor.radian

let ibHeight = factor.imageBoundsHeight
let iScale = CGFloat(imageRef.height) / (ibHeight * scale)
var translate = factor.convertTranslate
translate.y = ibHeight - translate.y // 左下点与底部的距离
translate.x *= -1 * scale * iScale
translate.y *= -1 * scale * iScale

var transform = CGAffineTransform(scaleX: scale, y: scale)
transform = transform.rotated(by: -radian)
transform = transform.translatedBy(x: translate.x, y: translate.y)

context.setShouldAntialias(true)
context.setAllowsAntialiasing(true)
context.interpolationQuality = .high
// 旋转+缩放+位移
context.concatenate(transform)
// 绘制
context.draw(imageRef, in: CGRect(x: 0, y: 0, width: width, height: height))

guard let newImageRef = context.makeImage() else { return nil }
return UIImage(cgImage: newImageRef)
}
}
Loading

0 comments on commit ec176fb

Please sign in to comment.