Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CropAuxiliaryIndicatorConfig to allow custom CropAuxiliaryIndicator colors #403

Merged
merged 2 commits into from
Jul 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions Example/EmbeddedCropViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class EmbeddedCropViewController: UIViewController {
return
}

cropViewController?.update(image.addFilter(filter: .Mono))
cropViewController?.update(image.addFilter(filter: .mono))
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
Expand Down Expand Up @@ -185,28 +185,28 @@ extension EmbeddedCropViewController: CropViewControllerDelegate {
}
}

enum FilterType : String {
case Chrome = "CIPhotoEffectChrome"
case Fade = "CIPhotoEffectFade"
case Instant = "CIPhotoEffectInstant"
case Mono = "CIPhotoEffectMono"
case Noir = "CIPhotoEffectNoir"
case Process = "CIPhotoEffectProcess"
case Tonal = "CIPhotoEffectTonal"
case Transfer = "CIPhotoEffectTransfer"
enum FilterType: String {
case chrome = "CIPhotoEffectChrome"
case fade = "CIPhotoEffectFade"
case instant = "CIPhotoEffectInstant"
case mono = "CIPhotoEffectMono"
case noir = "CIPhotoEffectNoir"
case process = "CIPhotoEffectProcess"
case tonal = "CIPhotoEffectTonal"
case transfer = "CIPhotoEffectTransfer"
}

extension UIImage {
func addFilter(filter : FilterType) -> UIImage {
func addFilter(filter: FilterType) -> UIImage {
let filter = CIFilter(name: filter.rawValue)
// convert UIImage to CIImage and set as input
// Convert UIImage to CIImage and set as input
let ciInput = CIImage(image: self)
filter?.setValue(ciInput, forKey: "inputImage")
// get output CIImage, render as CGImage first to retain proper UIImage scale
// Get output CIImage, render as CGImage first to retain proper UIImage scale
let ciOutput = filter?.outputImage
let ciContext = CIContext()
let cgImage = ciContext.createCGImage(ciOutput!, from: (ciOutput?.extent)!)
//Return the image
// Return the image
return UIImage(cgImage: cgImage!)
}
}
19 changes: 2 additions & 17 deletions Example/zh-Hans.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="ipad7_9" orientation="portrait" layout="fullscreen" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
Expand Down Expand Up @@ -181,21 +181,6 @@
</objects>
<point key="canvasLocation" x="1117.5999999999999" y="5.8470764617691158"/>
</scene>
<!--Crop View Controller-->
<scene sceneID="djG-LZ-hRH">
<objects>
<viewController id="xJq-Ev-XcJ" customClass="CropViewController" customModule="Mantis" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="nLp-HP-0xC">
<rect key="frame" x="0.0" y="0.0" width="744" height="1133"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="0JZ-7h-zil"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="TRU-F3-FYg" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1042" y="819"/>
</scene>
</scenes>
<resources>
<image name="sunflower" width="3648" height="5472"/>
Expand Down
4 changes: 4 additions & 0 deletions Mantis.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
F24DCFE829AB0A7000D8E8C1 /* CropAuxiliaryIndicatorViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24DCFE729AB0A7000D8E8C1 /* CropAuxiliaryIndicatorViewTests.swift */; };
F24DCFEC29AF2A6000D8E8C1 /* CropAuxiliaryIndicatorView+Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24DCFEB29AF2A6000D8E8C1 /* CropAuxiliaryIndicatorView+Accessibility.swift */; };
F251B36E299B9A52006325B0 /* CropWorkbenchViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F251B36D299B9A52006325B0 /* CropWorkbenchViewTests.swift */; };
F28FF64A2C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = F28FF6492C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift */; };
F2AD53412A46DB8B00AE9C87 /* ImageAutoAdjustHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2AD53402A46DB8B00AE9C87 /* ImageAutoAdjustHelper.swift */; };
F2B4FDA42A3B661B00667F22 /* SlideDial.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2B4FDA32A3B661B00667F22 /* SlideDial.swift */; };
F2B4FDA72A3B69B600667F22 /* SlideRulerPositionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2B4FDA52A3B69B600667F22 /* SlideRulerPositionHelper.swift */; };
Expand Down Expand Up @@ -211,6 +212,7 @@
F24DCFE729AB0A7000D8E8C1 /* CropAuxiliaryIndicatorViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CropAuxiliaryIndicatorViewTests.swift; sourceTree = "<group>"; };
F24DCFEB29AF2A6000D8E8C1 /* CropAuxiliaryIndicatorView+Accessibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CropAuxiliaryIndicatorView+Accessibility.swift"; sourceTree = "<group>"; };
F251B36D299B9A52006325B0 /* CropWorkbenchViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CropWorkbenchViewTests.swift; sourceTree = "<group>"; };
F28FF6492C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CropAuxiliaryIndicatorConfig.swift; sourceTree = "<group>"; };
F2AD53402A46DB8B00AE9C87 /* ImageAutoAdjustHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageAutoAdjustHelper.swift; sourceTree = "<group>"; };
F2B4FDA32A3B661B00667F22 /* SlideDial.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlideDial.swift; sourceTree = "<group>"; };
F2B4FDA52A3B69B600667F22 /* SlideRulerPositionHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlideRulerPositionHelper.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -507,6 +509,7 @@
OBJ_36 /* Mantis.swift */,
6659429C2877DAE80096A5DB /* Config.swift */,
663FCF3728866DDA003D3B9E /* CropViewConfig.swift */,
F28FF6492C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift */,
663FCF3828866DDA003D3B9E /* CropToolbarConfig.swift */,
6659429E2877DC8A0096A5DB /* Enum.swift */,
665942A02877DD1C0096A5DB /* CropData.swift */,
Expand Down Expand Up @@ -795,6 +798,7 @@
FEDAAD8625205CC300D95667 /* RatioSelector.swift in Sources */,
OBJ_93 /* CropVisualEffectView.swift in Sources */,
269AF94227437EE400F7FAF6 /* RotationDialConfig.swift in Sources */,
F28FF64A2C4A492A002F5F06 /* CropAuxiliaryIndicatorConfig.swift in Sources */,
OBJ_94 /* RatioOptions.swift in Sources */,
OBJ_95 /* Angle.swift in Sources */,
OBJ_97 /* RotationCalculator.swift in Sources */,
Expand Down
41 changes: 41 additions & 0 deletions Sources/Mantis/CropAuxiliaryIndicatorConfig.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// CropAuxiliaryIndicatorConfig.swift
// Mantis
//
// Created by Yingtao Guo on 7/19/24.
//

import UIKit

public struct CropAuxiliaryIndicatorConfig {
/**
This value is for how easy to drag crop box. The bigger, the easier.
*/
public var cropBoxHotAreaUnit: CGFloat = 32 {
didSet {
assert(cropBoxHotAreaUnit > 0)
}
}

public var disableCropBoxDeformation = false
public var style: CropAuxiliaryIndicatorStyleType = .normal

public var borderNormalColor = UIColor.white

/**
The color of the border when showing which border is touched currently.
*/
public var borderHintColor = UIColor.white

public var cornerHandleColor = UIColor.white
public var edgeLineHandleColor = UIColor.white

public var gridMainColor = UIColor.white

/**
This property is only used when rotating the image
*/
public var gridSecondaryColor = UIColor.lightGray

public init() {}
}
43 changes: 27 additions & 16 deletions Sources/Mantis/CropView/CropAuxiliaryIndicatorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import UIKit

final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtocol {
private var boarderNormalColor = UIColor.white
private var boarderHintColor = UIColor.white
private var borderNormalColor = UIColor.white
private var borderHintColor = UIColor.white
private var cornerHandleColor = UIColor.white
private var edgeLineHandleColor = UIColor.white
private let cornerHandleLength = CGFloat(20.0)
private let edgeLineHandleLength = CGFloat(30.0)
private let handleThickness = CGFloat(3.0)
Expand Down Expand Up @@ -49,16 +51,22 @@ final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtoc
}
}

init(frame: CGRect,
cropBoxHotAreaUnit: CGFloat,
disableCropBoxDeformation: Bool = false,
style: CropAuxiliaryIndicatorStyleType = .normal) {
init(frame: CGRect, config: CropAuxiliaryIndicatorConfig = CropAuxiliaryIndicatorConfig()) {
super.init(frame: frame)
clipsToBounds = false
backgroundColor = .clear
self.cropBoxHotAreaUnit = cropBoxHotAreaUnit
self.disableCropBoxDeformation = disableCropBoxDeformation
self.style = style

cropBoxHotAreaUnit = config.cropBoxHotAreaUnit
disableCropBoxDeformation = config.disableCropBoxDeformation
style = config.style

borderNormalColor = config.borderNormalColor
borderHintColor = config.borderHintColor
cornerHandleColor = config.cornerHandleColor
edgeLineHandleColor = config.edgeLineHandleColor
gridMainColor = config.gridMainColor
gridSecondaryColor = config.gridSecondaryColor

setup()
}

Expand All @@ -67,15 +75,18 @@ final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtoc
backgroundColor = .clear
}

private func createNewLine() -> UIView {
private func createNewLine(withNormalColor normalColor: UIColor = .white) -> UIView {
let view = UIView()
view.frame = .zero

if style == .normal {
view.backgroundColor = .white
view.backgroundColor = normalColor
} else {
view.backgroundColor = .clear
}

addSubview(view)

return view
}

Expand All @@ -85,19 +96,19 @@ final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtoc
borderLine.layer.borderWidth = borderThickness

if style == .normal {
borderLine.layer.borderColor = boarderNormalColor.cgColor
hintLine.backgroundColor = boarderHintColor
borderLine.layer.borderColor = borderNormalColor.cgColor
hintLine.backgroundColor = borderHintColor
} else {
borderLine.layer.borderColor = UIColor.clear.cgColor
hintLine.backgroundColor = .clear
}

for _ in 0..<8 {
cornerHandles.append(createNewLine())
cornerHandles.append(createNewLine(withNormalColor: cornerHandleColor))
}

for _ in 0..<4 {
edgeLineHandles.append(createNewLine())
edgeLineHandles.append(createNewLine(withNormalColor: edgeLineHandleColor))
}

setupAccessibilityHelperViews()
Expand Down Expand Up @@ -177,7 +188,7 @@ final class CropAuxiliaryIndicatorView: UIView, CropAuxiliaryIndicatorViewProtoc
borderLine.layer.backgroundColor = UIColor.clear.cgColor
borderLine.layer.borderWidth = borderThickness
if style == .normal {
borderLine.layer.borderColor = boarderNormalColor.cgColor
borderLine.layer.borderColor = borderNormalColor.cgColor
} else {
borderLine.layer.borderColor = UIColor.clear.cgColor
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/Mantis/CropView/CropView+Touches.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extension CropView {
return rotationControlView.getTouchTarget(with: pointInRotationControlView)
}

if !cropViewConfig.disableCropBoxDeformation && isHitGridOverlayView(by: newPoint) {
if !cropViewConfig.cropAuxiliaryIndicatorConfig.disableCropBoxDeformation && isHitGridOverlayView(by: newPoint) {
return self
}

Expand All @@ -29,7 +29,7 @@ extension CropView {
}

private func isHitGridOverlayView(by touchPoint: CGPoint) -> Bool {
let hotAreaUnit = cropViewConfig.cropBoxHotAreaUnit
let hotAreaUnit = cropViewConfig.cropAuxiliaryIndicatorConfig.cropBoxHotAreaUnit

return cropAuxiliaryIndicatorView.frame.insetBy(dx: -hotAreaUnit/2, dy: -hotAreaUnit/2).contains(touchPoint)
&& !cropAuxiliaryIndicatorView.frame.insetBy(dx: hotAreaUnit/2, dy: hotAreaUnit/2).contains(touchPoint)
Expand Down
4 changes: 2 additions & 2 deletions Sources/Mantis/CropView/CropView+UIScrollViewDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extension CropView: UIScrollViewDelegate {
}

func scrollViewDidZoom(_ scrollView: UIScrollView) {
guard scrollView.subviews.count > 0 else {
guard !scrollView.subviews.isEmpty else {
return
}

Expand All @@ -34,7 +34,7 @@ extension CropView: UIScrollViewDelegate {
let offsetX: CGFloat = max((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5, 0.0)
let offsetY: CGFloat = max((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5, 0.0)

subView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, scrollView.contentSize.height * 0.5 + offsetY)
subView.center = CGPoint(x: scrollView.contentSize.width * 0.5 + offsetX, y: scrollView.contentSize.height * 0.5 + offsetY)
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
Expand Down
42 changes: 34 additions & 8 deletions Sources/Mantis/CropViewConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,38 @@ public struct CropViewConfig {
/**
This value is for how easy to drag crop box. The bigger, the easier.
*/
public var cropBoxHotAreaUnit: CGFloat = 32 {
didSet {
assert(cropBoxHotAreaUnit > 0)
@available(*, deprecated, message: "Use cropAuxiliaryIndicatorStyle.cropBoxHotAreaUnit instead")
public var cropBoxHotAreaUnit: CGFloat {
get {
cropAuxiliaryIndicatorConfig.cropBoxHotAreaUnit
}
set {
cropAuxiliaryIndicatorConfig.cropBoxHotAreaUnit = newValue
}
}

@available(*, deprecated, message: "Use cropAuxiliaryIndicatorStyle.disableCropBoxDeformation instead")
public var disableCropBoxDeformation: Bool {
get {
cropAuxiliaryIndicatorConfig.disableCropBoxDeformation
}
set {
cropAuxiliaryIndicatorConfig.disableCropBoxDeformation = newValue
}
}

@available(*, deprecated, message: "Use cropAuxiliaryIndicatorConfig.style instead")
public var cropAuxiliaryIndicatorStyle: CropAuxiliaryIndicatorStyleType {
get {
cropAuxiliaryIndicatorConfig.style
}
set {
cropAuxiliaryIndicatorConfig.style = newValue
}
}

public var cropAuxiliaryIndicatorConfig = CropAuxiliaryIndicatorConfig()

public var cropShapeType: CropShapeType = .rect

public var cropBorderWidth: CGFloat = 0 {
Expand All @@ -31,8 +57,6 @@ public struct CropViewConfig {

public var cropMaskVisualEffectType: CropMaskVisualEffectType = .blurDark

public var cropAuxiliaryIndicatorStyle: CropAuxiliaryIndicatorStyleType = .normal

public var presetTransformationType: PresetTransformationType = .none

public var minimumZoomScale: CGFloat = 1 {
Expand Down Expand Up @@ -66,9 +90,11 @@ public struct CropViewConfig {

public var rotateCropBoxFor90DegreeRotation = true

var minimumCropBoxSize: CGFloat = 42

public var disableCropBoxDeformation = false
public var minimumCropBoxSize: CGFloat = 42 {
didSet {
assert(minimumCropBoxSize >= 4)
}
}

public enum BuiltInRotationControlViewType {
case rotationDial(config: RotationDialConfig = .init())
Expand Down
6 changes: 2 additions & 4 deletions Sources/Mantis/Mantis.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,7 @@ private func buildCropView(withImage image: UIImage,
config cropViewConfig: CropViewConfig,
rotationControlView: RotationControlViewProtocol?) -> CropViewProtocol {
let cropAuxiliaryIndicatorView = CropAuxiliaryIndicatorView(frame: .zero,
cropBoxHotAreaUnit: cropViewConfig.cropBoxHotAreaUnit,
disableCropBoxDeformation: cropViewConfig.disableCropBoxDeformation,
style: cropViewConfig.cropAuxiliaryIndicatorStyle)
config: cropViewConfig.cropAuxiliaryIndicatorConfig)
let imageContainer = ImageContainer(image: image)
let cropView = CropView(image: image,
cropViewConfig: cropViewConfig,
Expand All @@ -116,7 +114,7 @@ private func buildCropView(withImage image: UIImage,
private func buildCropViewModel(with cropViewConfig: CropViewConfig) -> CropViewModelProtocol {
CropViewModel(
cropViewPadding: cropViewConfig.padding,
hotAreaUnit: cropViewConfig.cropBoxHotAreaUnit
hotAreaUnit: cropViewConfig.cropAuxiliaryIndicatorConfig.cropBoxHotAreaUnit
)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Mantis/MaskBackground/CropMaskProtocal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import UIKit

private let minOverLayerUnit: CGFloat = 30
private let minOverLayerUnit: CGFloat = 4
private let initialFrameLength: CGFloat = 1000

protocol CropMaskProtocol: UIView {
Expand Down