导入 XuXuCheck 工程(iOS 干化学尿液试纸分析 App)
从桌面工程复制而来,作为本仓库的 Xuxucheck/ 子目录。 为控制仓库体积做了两处删减: - 移除 Frameworks/opencv2.xcframework 下的两个 visionOS 切片 (xros-arm64、xros-arm64-simulator,合计约 106 MB),并同步删掉该 xcframework 内 Info.plist 里对应的两条 AvailableLibraries 记录, 只保留 ios-arm64 与 ios-arm64_x86_64-simulator。 - 移除全部 .DS_Store 与 xcuserdata/。 已用 xcodebuild 从本目录完整编译验证:BUILD SUCCEEDED, ProcessXCFramework 以 --platform ios 成功选中框架,产物含 3699 个 cv:: 符号 (OpenCV 确实链入),嵌入 framework 3 个,与移除无用 pod 之后的状态一致。 仓库约 206 MB,其中 OpenCV 203 MB、其余源码与依赖约 3 MB。
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* DynamicColor
|
||||
*
|
||||
* Copyright 2015-present Yannick Loriot.
|
||||
* http://yannickloriot.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
Defines the supported color spaces.
|
||||
*/
|
||||
public enum DynamicColorSpace {
|
||||
/// The RGB color space
|
||||
case rgb
|
||||
/// The HSL color space
|
||||
case hsl
|
||||
/// The HSB color space
|
||||
case hsb
|
||||
/// The Cie L*a*b* color space
|
||||
case lab
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* DynamicColor
|
||||
*
|
||||
* Copyright 2015-present Yannick Loriot.
|
||||
* http://yannickloriot.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
Defines the mode (i.e color space) used for grayscaling.
|
||||
|
||||
[More info](https://en.wikipedia.org/wiki/Lightness#Lightness_and_human_perception)
|
||||
*/
|
||||
public enum GrayscalingMode {
|
||||
/// XYZ luminance
|
||||
case luminance
|
||||
/// HSL lightness
|
||||
case lightness
|
||||
/// RGB average
|
||||
case average
|
||||
/// HSV value
|
||||
case value
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* DynamicColor
|
||||
*
|
||||
* Copyright 2015-present Yannick Loriot.
|
||||
* http://yannickloriot.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
||||
#if os(iOS) || os(tvOS) || os(watchOS)
|
||||
import UIKit
|
||||
#elseif os(OSX)
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
/// Hue-saturation-lightness structure to make the color manipulation easier.
|
||||
internal struct HSL {
|
||||
/// Hue value between 0.0 and 1.0 (0.0 = 0 degree, 1.0 = 360 degree).
|
||||
var h: CGFloat = 0.0
|
||||
/// Saturation value between 0.0 and 1.0.
|
||||
var s: CGFloat = 0.0
|
||||
/// Lightness value between 0.0 and 1.0.
|
||||
var l: CGFloat = 0.0
|
||||
/// Alpha value between 0.0 and 1.0.
|
||||
var a: CGFloat = 1.0
|
||||
|
||||
// MARK: - Initializing HSL Colors
|
||||
|
||||
/**
|
||||
Initializes and creates a HSL color from the hue, saturation, lightness and alpha components.
|
||||
|
||||
- parameter h: The hue component of the color object, specified as a value between 0.0 and 360.0 degree.
|
||||
- parameter s: The saturation component of the color object, specified as a value between 0.0 and 1.0.
|
||||
- parameter l: The lightness component of the color object, specified as a value between 0.0 and 1.0.
|
||||
- parameter a: The opacity component of the color object, specified as a value between 0.0 and 1.0.
|
||||
*/
|
||||
init(hue: CGFloat, saturation: CGFloat, lightness: CGFloat, alpha: CGFloat = 1.0) {
|
||||
h = hue.truncatingRemainder(dividingBy: 360.0) / 360.0
|
||||
s = clip(saturation, 0.0, 1.0)
|
||||
l = clip(lightness, 0.0, 1.0)
|
||||
a = clip(alpha, 0.0, 1.0)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes and creates a HSL (hue, saturation, lightness) color from a DynamicColor object.
|
||||
|
||||
- parameter color: A DynamicColor object.
|
||||
*/
|
||||
init(color: DynamicColor) {
|
||||
let rgba = color.toRGBAComponents()
|
||||
|
||||
let maximum = max(rgba.r, max(rgba.g, rgba.b))
|
||||
let minimum = min(rgba.r, min(rgba.g, rgba.b))
|
||||
|
||||
let delta = maximum - minimum
|
||||
|
||||
h = 0.0
|
||||
s = 0.0
|
||||
l = (maximum + minimum) / 2.0
|
||||
|
||||
if delta != 0.0 {
|
||||
if l < 0.5 {
|
||||
s = delta / (maximum + minimum)
|
||||
}
|
||||
else {
|
||||
s = delta / (2.0 - maximum - minimum)
|
||||
}
|
||||
|
||||
if rgba.r == maximum {
|
||||
h = ((rgba.g - rgba.b) / delta) + (rgba.g < rgba.b ? 6.0 : 0.0)
|
||||
}
|
||||
else if rgba.g == maximum {
|
||||
h = ((rgba.b - rgba.r) / delta) + 2.0
|
||||
}
|
||||
else if rgba.b == maximum {
|
||||
h = ((rgba.r - rgba.g) / delta) + 4.0
|
||||
}
|
||||
}
|
||||
|
||||
h /= 6.0
|
||||
a = rgba.a
|
||||
}
|
||||
|
||||
// MARK: - Transforming HSL Color
|
||||
|
||||
/**
|
||||
Returns the DynamicColor representation from the current HSV color.
|
||||
|
||||
- returns: A DynamicColor object corresponding to the current HSV color.
|
||||
*/
|
||||
func toDynamicColor() -> DynamicColor {
|
||||
let (r, g, b, a) = rgbaComponents()
|
||||
|
||||
return DynamicColor(red: r, green: g, blue: b, alpha: a)
|
||||
}
|
||||
|
||||
/// Returns the RGBA components from the current HSV color.
|
||||
func rgbaComponents() -> (CGFloat, CGFloat, CGFloat, CGFloat) {
|
||||
let m2 = l <= 0.5 ? l * (s + 1.0) : (l + s) - (l * s)
|
||||
let m1 = (l * 2.0) - m2
|
||||
|
||||
let r = hueToRGB(m1: m1, m2: m2, h: h + (1.0 / 3.0))
|
||||
let g = hueToRGB(m1: m1, m2: m2, h: h)
|
||||
let b = hueToRGB(m1: m1, m2: m2, h: h - (1.0 / 3.0))
|
||||
|
||||
return (r, g, b, CGFloat(a))
|
||||
}
|
||||
|
||||
/// Hue to RGB helper function
|
||||
private func hueToRGB(m1: CGFloat, m2: CGFloat, h: CGFloat) -> CGFloat {
|
||||
let hue = moda(h, m: 1)
|
||||
|
||||
if hue * 6 < 1.0 {
|
||||
return m1 + ((m2 - m1) * hue * 6.0)
|
||||
}
|
||||
else if hue * 2.0 < 1.0 {
|
||||
return m2
|
||||
}
|
||||
else if hue * 3.0 < 1.9999 {
|
||||
return m1 + ((m2 - m1) * ((2.0 / 3.0) - hue) * 6.0)
|
||||
}
|
||||
|
||||
return m1
|
||||
}
|
||||
|
||||
// MARK: - Deriving the Color
|
||||
|
||||
/**
|
||||
Returns a color with the hue rotated along the color wheel by the given amount.
|
||||
|
||||
- parameter amount: A float representing the number of degrees as ratio (usually between -360.0 degree and 360.0 degree).
|
||||
- returns: A HSL color with the hue changed.
|
||||
*/
|
||||
func adjustedHue(amount: CGFloat) -> HSL {
|
||||
return HSL(hue: (h * 360.0) + amount, saturation: s, lightness: l, alpha: a)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a color with the lightness increased by the given amount.
|
||||
|
||||
- parameter amount: CGFloat between 0.0 and 1.0.
|
||||
- returns: A lighter HSL color.
|
||||
*/
|
||||
func lighter(amount: CGFloat) -> HSL {
|
||||
return HSL(hue: h * 360.0, saturation: s, lightness: l + amount, alpha: a)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a color with the lightness decreased by the given amount.
|
||||
|
||||
- parameter amount: CGFloat between 0.0 and 1.0.
|
||||
- returns: A darker HSL color.
|
||||
*/
|
||||
func darkened(amount: CGFloat) -> HSL {
|
||||
return lighter(amount: amount * -1.0)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a color with the saturation increased by the given amount.
|
||||
|
||||
- parameter amount: CGFloat between 0.0 and 1.0.
|
||||
- returns: A HSL color more saturated.
|
||||
*/
|
||||
func saturated(amount: CGFloat) -> HSL {
|
||||
return HSL(hue: h * 360.0, saturation: s + amount, lightness: l, alpha: a)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a color with the saturation decreased by the given amount.
|
||||
|
||||
- parameter amount: CGFloat between 0.0 and 1.0.
|
||||
- returns: A HSL color less saturated.
|
||||
*/
|
||||
func desaturated(amount: CGFloat) -> HSL {
|
||||
return saturated(amount: amount * -1.0)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* DynamicColor
|
||||
*
|
||||
* Copyright 2015-present Yannick Loriot.
|
||||
* http://yannickloriot.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#if os(iOS) || os(tvOS) || os(watchOS)
|
||||
import UIKit
|
||||
#elseif os(OSX)
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
/**
|
||||
Clips the values in an interval.
|
||||
|
||||
Given an interval, values outside the interval are clipped to the interval
|
||||
edges. For example, if an interval of [0, 1] is specified, values smaller than
|
||||
0 become 0, and values larger than 1 become 1.
|
||||
|
||||
- Parameter v: The value to clipped.
|
||||
- Parameter minimum: The minimum edge value.
|
||||
- Parameter maximum: The maximum edgevalue.
|
||||
*/
|
||||
internal func clip<T: Comparable>(_ v: T, _ minimum: T, _ maximum: T) -> T {
|
||||
return max(min(v, maximum), minimum)
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the absolute value of the modulo operation.
|
||||
|
||||
- Parameter x: The value to compute.
|
||||
- Parameter m: The modulo.
|
||||
*/
|
||||
internal func moda(_ x: CGFloat, m: CGFloat) -> CGFloat {
|
||||
return (x.truncatingRemainder(dividingBy: m) + m).truncatingRemainder(dividingBy: m)
|
||||
}
|
||||
|
||||
/**
|
||||
Rounds the given float to a given decimal precision.
|
||||
|
||||
- Parameter x: The value to round.
|
||||
- Parameter m: The precision. Default to 10000.
|
||||
*/
|
||||
internal func roundDecimal(_ x: CGFloat, precision: CGFloat = 10000.0) -> CGFloat {
|
||||
return CGFloat(Int(round(x * precision))) / precision
|
||||
}
|
||||
|
||||
internal func roundToHex(_ x: CGFloat) -> UInt32 {
|
||||
guard x > 0 else { return 0 }
|
||||
let rounded: CGFloat = round(x * 255.0)
|
||||
|
||||
return UInt32(rounded)
|
||||
}
|
||||
Reference in New Issue
Block a user