├── .github
└── FUNDING.yml
├── .gitignore
├── .swiftpm
└── xcode
│ ├── package.xcworkspace
│ └── contents.xcworkspacedata
│ └── xcshareddata
│ └── xcschemes
│ └── Harbeth.xcscheme
├── CATALOGUE.txt
├── Demo
├── Harbeth-Demo.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── Harbeth-iOS-Demo.xcscheme
│ │ └── Harbeth-macOS-Demo.xcscheme
├── Harbeth-SwiftUI-Demo
│ ├── ContentView.swift
│ ├── Harbeth-SwiftUI-Demo.entitlements
│ ├── HarbethExamples.swift
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ ├── Resources
│ │ ├── Assets.xcassets
│ │ │ ├── AX.imageset
│ │ │ │ ├── AX.jpg
│ │ │ │ └── Contents.json
│ │ │ ├── AccentColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── IMG_0020.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── IMG_0020.jpg
│ │ │ ├── IMG_2606.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── IMG_2606.jpg
│ │ │ ├── IMG_4931.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── IMG_4931.png
│ │ │ ├── SP.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── SP.png
│ │ │ ├── SampleImage.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── SampleImage.jpg
│ │ │ ├── lut.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── lut.png
│ │ │ └── yuan002.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── yuan002.jpeg
│ │ ├── ErrorView.swift
│ │ ├── Extensions.swift
│ │ ├── ImageLoader.swift
│ │ ├── Res.swift
│ │ ├── violet.CUBE
│ │ └── vista200 v1.CUBE
│ └── Views
│ │ ├── BlendView.swift
│ │ ├── CoreImageViews.swift
│ │ ├── CubeView.swift
│ │ ├── CustomViews.swift
│ │ ├── MetalKernelViews.swift
│ │ └── SwiftUIView.swift
├── Harbeth-iOS-Demo
│ ├── AppDelegate.swift
│ ├── Collector
│ │ ├── C7Collector.swift
│ │ ├── C7CollectorCamera.swift
│ │ └── C7CollectorVideo.swift
│ ├── HomeViewController.swift
│ ├── HomeViewModel.swift
│ ├── HomeViewType+Ext.swift
│ ├── HomeViewType.swift
│ ├── Modules
│ │ ├── CameraViewController.swift
│ │ ├── ImageViewController.swift
│ │ ├── PlayerViewController.swift
│ │ └── UnitTestViewController.swift
│ └── Resources
│ │ ├── Assets.xcassets
│ │ ├── AX.imageset
│ │ │ ├── AX.jpg
│ │ │ └── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── logoiPhoneApp_60pt@2x.png
│ │ │ ├── logoiPhoneApp_60pt@3x.png
│ │ │ ├── logoiPhoneNotification_20pt@2x.png
│ │ │ ├── logoiPhoneNotification_20pt@3x.png
│ │ │ ├── logoiPhoneSpootlight5_29pt@2x.png
│ │ │ ├── logoiPhoneSpootlight5_29pt@3x.png
│ │ │ ├── logoiPhoneSpootlight7_40pt@2x.png
│ │ │ ├── logoiPhoneSpootlight7_40pt@3x.png
│ │ │ └── logostore_1024pt.png
│ │ ├── Contents.json
│ │ ├── IMG_1668.imageset
│ │ │ ├── Contents.json
│ │ │ └── IMG_1668.jpg
│ │ ├── IMG_2606.imageset
│ │ │ ├── Contents.json
│ │ │ └── IMG_2606.jpg
│ │ ├── IMG_2623.imageset
│ │ │ ├── Contents.json
│ │ │ └── test.jpeg
│ │ ├── IMG_3960.imageset
│ │ │ ├── Contents.json
│ │ │ └── IMG_3960.heic
│ │ ├── P1040808.imageset
│ │ │ ├── Contents.json
│ │ │ └── P1040808.jpg
│ │ ├── Zlookup
│ │ │ ├── Contents.json
│ │ │ ├── ll.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── ll.png
│ │ │ └── lut_abao.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── lut_abao.png
│ │ ├── timg-2.imageset
│ │ │ ├── Contents.json
│ │ │ └── timg-2.jpeg
│ │ ├── timg-3.imageset
│ │ │ ├── Contents.json
│ │ │ └── timg-3.jpeg
│ │ ├── yuan000.imageset
│ │ │ ├── 9.jpeg
│ │ │ └── Contents.json
│ │ ├── yuan001.imageset
│ │ │ ├── 10.jpeg
│ │ │ └── Contents.json
│ │ ├── yuan002.imageset
│ │ │ ├── 11.jpeg
│ │ │ └── Contents.json
│ │ ├── yuan003.imageset
│ │ │ ├── 12.jpeg
│ │ │ └── Contents.json
│ │ ├── yuan004.imageset
│ │ │ ├── 17.jpg
│ │ │ └── Contents.json
│ │ └── yuan005.imageset
│ │ │ ├── 18.jpg
│ │ │ └── Contents.json
│ │ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ │ ├── Color.xcassets
│ │ ├── Contents.json
│ │ ├── background.colorset
│ │ │ └── Contents.json
│ │ ├── background2.colorset
│ │ │ └── Contents.json
│ │ └── defaultTint.colorset
│ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── SceneDelegate.swift
│ │ └── Skateboarding.mp4
└── Harbeth-macOS-Demo
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AR.imageset
│ │ ├── 11.jpeg
│ │ └── Contents.json
│ ├── AX.imageset
│ │ ├── AX.jpg
│ │ └── Contents.json
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Contents.json
│ ├── lut_abao.imageset
│ │ ├── Contents.json
│ │ └── lut_abao.png
│ └── lut_ll.imageset
│ │ ├── Contents.json
│ │ └── lut_ll.png
│ ├── Base.lproj
│ └── Main.storyboard
│ ├── DisplayLink.swift
│ ├── Harbeth_macOS_Demo.entitlements
│ └── ViewController.swift
├── Document
├── Metal.pdf
└── Shader.pdf
├── Harbeth.podspec
├── Harbeth.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ └── xcschemes
│ └── Harbeth.xcscheme
├── Harbeth.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── LICENSE
├── Language
├── Language.metal
└── Metal.metal
├── Package.swift
├── README.md
├── README_CN.md
├── Screenshot
├── 001.png
├── EdgeGlow.gif
├── M.jpeg
├── Mix.png
├── Mix2.png
├── ShiftGlitch.gif
├── Soul.gif
├── SoulOut.gif
├── WechatIMG1.jpg
├── WechatIMG2.jpg
├── flow.png
└── launch.jpeg
└── Sources
├── Basic
├── Core
│ ├── Compute.swift
│ ├── Device.swift
│ ├── Filtering.swift
│ ├── Rendering.swift
│ ├── Shared.swift
│ └── TextureLoader.swift
├── Extensions
│ ├── C7Color+Driver.swift
│ ├── C7Color+Ext.swift
│ ├── C7Image+Ext.swift
│ ├── C7Image+iOS.swift
│ ├── C7Image+macOS.swift
│ ├── C7View+iOS.swift
│ ├── CATransform3D+Ext.swift
│ ├── CGContext+Ext.swift
│ ├── CGImage+Ext.swift
│ ├── CGPath+Ext.swift
│ ├── CGPoint+Ext.swift
│ ├── CGRect+Ext.swift
│ ├── CGSize+Ext.swift
│ ├── CIImage+Ext.swift
│ ├── CMSampleBuffer+Ext.swift
│ ├── CVPixelBuffer+Ext.swift
│ ├── Data+Ext.swift
│ ├── MTLCommandBuffer+Ext.swift
│ ├── MTLSize+Ext.swift
│ ├── MTLTexture+Ext.swift
│ ├── String+Ext.swift
│ └── URL+Ext.swift
├── Matrix
│ ├── Matrix.swift
│ ├── Matrix3x3.swift
│ ├── Matrix4x4.swift
│ ├── Matrix4x5.swift
│ ├── Vector3.swift
│ └── Vector4.swift
├── Outputs
│ ├── Destype.swift
│ ├── HarbethIO.swift
│ ├── HugeImage.swift
│ ├── Operators.swift
│ ├── Outputable.swift
│ ├── RenderImageView.swift
│ ├── RenderView.swift
│ └── Renderable.swift
└── Setup
│ ├── Cacheable.swift
│ ├── Clamping.swift
│ ├── Degree.swift
│ ├── Error.swift
│ ├── Files.swift
│ ├── Locked.swift
│ ├── Mirrorable.swift
│ ├── ParameterRange.swift
│ ├── Pixel.swift
│ ├── Placement.swift
│ ├── Point2D.swift
│ ├── R.swift
│ ├── RGBA.swift
│ ├── ResizingMode.swift
│ ├── Size.swift
│ ├── Typealias.swift
│ ├── Wrapper.swift
│ └── ZeroOneRange.swift
├── Compute
├── Blend
│ ├── C7Blend.swift
│ ├── C7BlendChromaKey.metal
│ ├── C7BlendColorAdd.metal
│ ├── C7BlendColorAlpha.metal
│ ├── C7BlendColorBurn.metal
│ ├── C7BlendColorDodge.metal
│ ├── C7BlendDarken.metal
│ ├── C7BlendDifference.metal
│ ├── C7BlendDissolve.metal
│ ├── C7BlendDivide.metal
│ ├── C7BlendExclusion.metal
│ ├── C7BlendHardLight.metal
│ ├── C7BlendHue.metal
│ ├── C7BlendLighten.metal
│ ├── C7BlendLinearBurn.metal
│ ├── C7BlendLuminosity.metal
│ ├── C7BlendMask.metal
│ ├── C7BlendMultiply.metal
│ ├── C7BlendNormal.metal
│ ├── C7BlendOverlay.metal
│ ├── C7BlendScreen.metal
│ ├── C7BlendSoftLight.metal
│ ├── C7BlendSourceOver.metal
│ └── C7BlendSubtract.metal
├── Blur
│ ├── C7BilateralBlur.metal
│ ├── C7BilateralBlur.swift
│ ├── C7CircleBlur.metal
│ ├── C7CircleBlur.swift
│ ├── C7GaussianBlur.metal
│ ├── C7GaussianBlur.swift
│ ├── C7MeanBlur.metal
│ ├── C7MeanBlur.swift
│ ├── C7MotionBlur.metal
│ ├── C7MotionBlur.swift
│ ├── C7RedMonochromeBlur.metal
│ ├── C7RedMonochromeBlur.swift
│ ├── C7ZoomBlur.metal
│ └── C7ZoomBlur.swift
├── Combination
│ ├── C7CombinationBeautiful.metal
│ ├── C7CombinationBeautiful.swift
│ └── C7CombinationBilateralBlur.swift
├── Coordinate
│ ├── C7Bulge.metal
│ ├── C7Bulge.swift
│ ├── C7ColorCGASpace.metal
│ ├── C7ColorCGASpace.swift
│ ├── C7ColorPacking.metal
│ ├── C7ColorPacking.swift
│ ├── C7Fluctuate.metal
│ ├── C7Fluctuate.swift
│ ├── C7GlassSphere.metal
│ ├── C7GlassSphere.swift
│ ├── C7Glitch.metal
│ ├── C7Glitch.swift
│ ├── C7Halftone.metal
│ ├── C7Halftone.swift
│ ├── C7Kuwahara.metal
│ ├── C7Kuwahara.swift
│ ├── C7OilPainting.metal
│ ├── C7OilPainting.swift
│ ├── C7Pinch.metal
│ ├── C7Pinch.swift
│ ├── C7Pixellated.metal
│ ├── C7Pixellated.swift
│ ├── C7PolarPixellate.metal
│ ├── C7PolarPixellate.swift
│ ├── C7PolkaDot.metal
│ ├── C7PolkaDot.swift
│ ├── C7RGBADilation.metal
│ ├── C7RGBADilation.swift
│ ├── C7Sharpen.metal
│ ├── C7Sharpen.swift
│ ├── C7Sketch.metal
│ ├── C7Sketch.swift
│ ├── C7SoulOut.metal
│ ├── C7SoulOut.swift
│ ├── C7SphereRefraction.metal
│ ├── C7SphereRefraction.swift
│ ├── C7SplitScreen.metal
│ ├── C7SplitScreen.swift
│ ├── C7Storyboard.metal
│ ├── C7Storyboard.swift
│ ├── C7Swirl.metal
│ ├── C7Swirl.swift
│ ├── C7ThresholdSketch.metal
│ ├── C7ThresholdSketch.swift
│ ├── C7Toon.metal
│ ├── C7Toon.swift
│ ├── C7WaterRipple.metal
│ └── C7WaterRipple.swift
├── Generator
│ ├── C7ColorGradient.metal
│ ├── C7ColorGradient.swift
│ ├── C7SolidColor.metal
│ └── C7SolidColor.swift
├── Lookup
│ ├── C7LookupSplit.metal
│ ├── C7LookupSplit.swift
│ ├── C7LookupTable.metal
│ └── C7LookupTable.swift
├── Matrix
│ ├── C7ColorMatrix4x4.metal
│ ├── C7ColorMatrix4x4.swift
│ ├── C7ColorMatrix4x5.metal
│ ├── C7ColorMatrix4x5.swift
│ ├── C7ColorVector4.metal
│ ├── C7ColorVector4.swift
│ ├── C7ConvolutionMatrix3x3.metal
│ ├── C7ConvolutionMatrix3x3.swift
│ ├── C7EdgeGlow.metal
│ ├── C7EdgeGlow.swift
│ ├── C7Nostalgic.metal
│ ├── C7Nostalgic.swift
│ ├── C7Sepia.metal
│ └── C7Sepia.swift
├── Pixel
│ ├── C7Brightness.metal
│ ├── C7Brightness.swift
│ ├── C7ChromaKey.metal
│ ├── C7ChromaKey.swift
│ ├── C7ColorConvert.metal
│ ├── C7ColorConvert.swift
│ ├── C7ColorRGBA.metal
│ ├── C7ColorRGBA.swift
│ ├── C7ColorSpace.metal
│ ├── C7ColorSpace.swift
│ ├── C7ComicStrip.metal
│ ├── C7ComicStrip.swift
│ ├── C7Contrast.metal
│ ├── C7Contrast.swift
│ ├── C7Crosshatch.metal
│ ├── C7Crosshatch.swift
│ ├── C7DepthLuminance.metal
│ ├── C7DepthLuminance.swift
│ ├── C7Exposure.metal
│ ├── C7Exposure.swift
│ ├── C7FalseColor.metal
│ ├── C7FalseColor.swift
│ ├── C7Gamma.metal
│ ├── C7Gamma.swift
│ ├── C7Granularity.metal
│ ├── C7Granularity.swift
│ ├── C7Grayed.metal
│ ├── C7Grayed.swift
│ ├── C7Haze.metal
│ ├── C7Haze.swift
│ ├── C7HighlightShadow.metal
│ ├── C7HighlightShadow.swift
│ ├── C7HighlightShadowTint.metal
│ ├── C7HighlightShadowTint.swift
│ ├── C7Hue.metal
│ ├── C7Hue.swift
│ ├── C7Levels.metal
│ ├── C7Levels.swift
│ ├── C7Luminance.metal
│ ├── C7Luminance.swift
│ ├── C7LuminanceRangeReduction.metal
│ ├── C7LuminanceRangeReduction.swift
│ ├── C7LuminanceThreshold.metal
│ ├── C7LuminanceThreshold.swift
│ ├── C7Monochrome.metal
│ ├── C7Monochrome.swift
│ ├── C7Opacity.metal
│ ├── C7Opacity.swift
│ ├── C7Posterize.metal
│ ├── C7Posterize.swift
│ ├── C7Pow.metal
│ ├── C7Pow.swift
│ ├── C7Saturation.metal
│ ├── C7Saturation.swift
│ ├── C7ShiftGlitch.metal
│ ├── C7ShiftGlitch.swift
│ ├── C7Sobel.metal
│ ├── C7Sobel.swift
│ ├── C7Vibrance.metal
│ ├── C7Vibrance.swift
│ ├── C7Vignette.metal
│ ├── C7Vignette.swift
│ ├── C7VoronoiOverlay.metal
│ ├── C7VoronoiOverlay.swift
│ ├── C7WhiteBalance.metal
│ └── C7WhiteBalance.swift
└── Shape
│ ├── C7Crop.metal
│ ├── C7Crop.swift
│ ├── C7Flip.metal
│ ├── C7Flip.swift
│ ├── C7Resize.metal
│ ├── C7Resize.swift
│ ├── C7Rotate.metal
│ ├── C7Rotate.swift
│ ├── C7Transform.metal
│ └── C7Transform.swift
├── CoreImage
├── CIBrightness.swift
├── CIColorControls.swift
├── CIColorCube.swift
├── CIColorMonochrome.swift
├── CIContrast.swift
├── CIExposure.swift
├── CIFade.swift
├── CIGaussianBlur.swift
├── CIHighlight.swift
├── CILookupTable.swift
├── CINoiseReduction.swift
├── CIPhotoEffect.swift
├── CIResizedSmooth.swift
├── CISaturation.swift
├── CIShadows.swift
├── CISharpen.swift
├── CISketch.swift
├── CITemperature.swift
├── CIUnsharpMask.swift
├── CIVignette.swift
└── CIWhitePoint.swift
├── Harbeth.h
├── MPS
├── MPSBoxBlur.swift
├── MPSGaussianBlur.swift
└── MPSHistogram.swift
└── SwiftUI
├── Color+Ext.swift
├── HarbethView.swift
├── HarbethViewInput.swift
├── Image+Ext.swift
└── Published_Image.swift
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [yangKJ]
4 | buy_me_a_coffee: yangkj3102
5 | custom: ["https://raw.githubusercontent.com/yangKJ/Harbeth/master/Screenshot/WechatIMG2.jpg", "https://raw.githubusercontent.com/yangKJ/Harbeth/master/Screenshot/WechatIMG1.jpg"]
6 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/Harbeth-Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/Harbeth-Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Harbeth-SwiftUI-Demo.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/HarbethExamples.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HarbethExamples.swift
3 | // Harbeth-SwiftUI-Demo
4 | //
5 | // Created by Condy on 2023/3/21.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct HarbethExamples: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | ContentView()
15 | #if os(macOS)
16 | .frame(width: 888, height: 600)
17 | #endif
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/AX.imageset/AX.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/AX.imageset/AX.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/AX.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AX.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/IMG_0020.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IMG_0020.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/IMG_0020.imageset/IMG_0020.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/IMG_0020.imageset/IMG_0020.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/IMG_2606.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IMG_2606.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/IMG_2606.imageset/IMG_2606.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/IMG_2606.imageset/IMG_2606.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/IMG_4931.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IMG_4931.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/IMG_4931.imageset/IMG_4931.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/IMG_4931.imageset/IMG_4931.png
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/SP.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "SP.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/SP.imageset/SP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/SP.imageset/SP.png
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/SampleImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "SampleImage.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/SampleImage.imageset/SampleImage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/SampleImage.imageset/SampleImage.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/lut.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "lut.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/lut.imageset/lut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/lut.imageset/lut.png
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/yuan002.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "yuan002.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/yuan002.imageset/yuan002.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-SwiftUI-Demo/Resources/Assets.xcassets/yuan002.imageset/yuan002.jpeg
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/Res.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Res.swift
3 | // Harbeth-SwiftUI-Demo
4 | //
5 | // Created by Condy on 2023/7/29.
6 | //
7 |
8 | import Foundation
9 | import Harbeth
10 |
11 | struct Res {
12 |
13 | public static func rgUVB1Gradient(_ size: CGSize = .onePixel) throws -> MTLTexture {
14 | let texture = try TextureLoader.makeTexture(at: size)
15 | let filter = C7ColorGradient(with: .rgUVB1)
16 | var dest = HarbethIO(element: texture, filter: filter)
17 | //dest.createDestTexture = false
18 | return try dest.output()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Demo/Harbeth-SwiftUI-Demo/Resources/violet.CUBE:
--------------------------------------------------------------------------------
1 | #Created by: Adobe Photoshop Export Color Lookup Plugin
2 | TITLE "violet.psd"
3 |
4 | #LUT size
5 | LUT_3D_SIZE 2
6 |
7 | #data domain
8 | DOMAIN_MIN 0.0 0.0 0.0
9 | DOMAIN_MAX 1.0 1.0 1.0
10 |
11 | #LUT data points
12 | 0 0 0
13 | 0.1 0 1
14 | 0 1 0
15 | 1 1 0
16 | 0 0 1
17 | 1 0 1
18 | 0 1 1
19 | 1 1 1
20 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AX.imageset/AX.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AX.imageset/AX.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AX.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AX.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneApp_60pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneApp_60pt@2x.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneApp_60pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneApp_60pt@3x.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneNotification_20pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneNotification_20pt@2x.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneNotification_20pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneNotification_20pt@3x.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneSpootlight5_29pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneSpootlight5_29pt@2x.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneSpootlight5_29pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneSpootlight5_29pt@3x.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneSpootlight7_40pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneSpootlight7_40pt@2x.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneSpootlight7_40pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logoiPhoneSpootlight7_40pt@3x.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logostore_1024pt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/AppIcon.appiconset/logostore_1024pt.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_1668.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IMG_1668.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_1668.imageset/IMG_1668.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_1668.imageset/IMG_1668.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_2606.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IMG_2606.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_2606.imageset/IMG_2606.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_2606.imageset/IMG_2606.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_2623.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "test.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_2623.imageset/test.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_2623.imageset/test.jpeg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_3960.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "IMG_3960.heic",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_3960.imageset/IMG_3960.heic:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/IMG_3960.imageset/IMG_3960.heic
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/P1040808.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "P1040808.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/P1040808.imageset/P1040808.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/P1040808.imageset/P1040808.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/Zlookup/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/Zlookup/ll.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "ll.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/Zlookup/ll.imageset/ll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/Zlookup/ll.imageset/ll.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/Zlookup/lut_abao.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "lut_abao.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/Zlookup/lut_abao.imageset/lut_abao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/Zlookup/lut_abao.imageset/lut_abao.png
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/timg-2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "timg-2.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/timg-2.imageset/timg-2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/timg-2.imageset/timg-2.jpeg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/timg-3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "timg-3.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/timg-3.imageset/timg-3.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/timg-3.imageset/timg-3.jpeg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan000.imageset/9.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan000.imageset/9.jpeg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan000.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "9.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan001.imageset/10.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan001.imageset/10.jpeg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan001.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "10.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan002.imageset/11.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan002.imageset/11.jpeg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan002.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "11.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan003.imageset/12.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan003.imageset/12.jpeg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan003.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "12.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan004.imageset/17.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan004.imageset/17.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan004.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "17.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan005.imageset/18.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan005.imageset/18.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Assets.xcassets/yuan005.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "18.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Color.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Color.xcassets/background.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.957",
9 | "green" : "0.953",
10 | "red" : "0.953"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "light"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "0.957",
27 | "green" : "0.953",
28 | "red" : "0.953"
29 | }
30 | },
31 | "idiom" : "universal"
32 | },
33 | {
34 | "appearances" : [
35 | {
36 | "appearance" : "luminosity",
37 | "value" : "dark"
38 | }
39 | ],
40 | "color" : {
41 | "color-space" : "srgb",
42 | "components" : {
43 | "alpha" : "1.000",
44 | "blue" : "0.090",
45 | "green" : "0.078",
46 | "red" : "0.067"
47 | }
48 | },
49 | "idiom" : "universal"
50 | }
51 | ],
52 | "info" : {
53 | "author" : "xcode",
54 | "version" : 1
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Color.xcassets/background2.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.262",
9 | "green" : "0.176",
10 | "red" : "0.833"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "1.000",
27 | "green" : "0.602",
28 | "red" : "0.033"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Color.xcassets/defaultTint.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.010",
9 | "green" : "0.000",
10 | "red" : "0.000"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "1.000",
27 | "green" : "1.000",
28 | "red" : "1.000"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | $(PRODUCT_MODULE_NAME).SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Demo/Harbeth-iOS-Demo/Resources/Skateboarding.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-iOS-Demo/Resources/Skateboarding.mp4
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Harbeth-macOS-Demo
4 | //
5 | // Created by Condy on 2023/2/9.
6 | //
7 |
8 | import Cocoa
9 |
10 | @main
11 | class AppDelegate: NSObject, NSApplicationDelegate {
12 |
13 | lazy var window: NSWindow = {
14 | let rect = NSMakeRect(0, 0, 700, 700)
15 | let mask = [.titled, .resizable, .miniaturizable, .closable, .fullSizeContentView] as NSWindow.StyleMask
16 | let window = NSWindow(contentRect: rect, styleMask: mask, backing: .buffered, defer: false)
17 | window.minSize = window.frame.size
18 | window.maxSize = window.frame.size
19 | window.center()
20 | return window
21 | }()
22 |
23 | func applicationDidFinishLaunching(_ aNotification: Notification) {
24 | // Insert code here to initialize your application
25 | window.makeKeyAndOrderFront(nil)
26 | NSApplication.shared.mainWindow?.title = "Unit testing"
27 | let vc = ViewController()
28 | window.contentViewController = vc
29 | }
30 |
31 | func applicationWillTerminate(_ aNotification: Notification) {
32 | // Insert code here to tear down your application
33 | }
34 |
35 | func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
36 | return true
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/AR.imageset/11.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-macOS-Demo/Assets.xcassets/AR.imageset/11.jpeg
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/AR.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "11.jpeg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/AX.imageset/AX.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-macOS-Demo/Assets.xcassets/AX.imageset/AX.jpg
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/AX.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AX.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "scale" : "1x",
6 | "size" : "16x16"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "scale" : "2x",
11 | "size" : "16x16"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "scale" : "1x",
16 | "size" : "32x32"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "scale" : "2x",
21 | "size" : "32x32"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "scale" : "1x",
26 | "size" : "128x128"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "scale" : "2x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "scale" : "1x",
36 | "size" : "256x256"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "scale" : "2x",
41 | "size" : "256x256"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "1x",
46 | "size" : "512x512"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "scale" : "2x",
51 | "size" : "512x512"
52 | }
53 | ],
54 | "info" : {
55 | "author" : "xcode",
56 | "version" : 1
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/lut_abao.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "lut_abao.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/lut_abao.imageset/lut_abao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-macOS-Demo/Assets.xcassets/lut_abao.imageset/lut_abao.png
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/lut_ll.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "lut_ll.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Assets.xcassets/lut_ll.imageset/lut_ll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Demo/Harbeth-macOS-Demo/Assets.xcassets/lut_ll.imageset/lut_ll.png
--------------------------------------------------------------------------------
/Demo/Harbeth-macOS-Demo/Harbeth_macOS_Demo.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Document/Metal.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Document/Metal.pdf
--------------------------------------------------------------------------------
/Document/Shader.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Document/Shader.pdf
--------------------------------------------------------------------------------
/Harbeth.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Harbeth.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Harbeth.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Harbeth.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 AT
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Screenshot/001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/001.png
--------------------------------------------------------------------------------
/Screenshot/EdgeGlow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/EdgeGlow.gif
--------------------------------------------------------------------------------
/Screenshot/M.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/M.jpeg
--------------------------------------------------------------------------------
/Screenshot/Mix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/Mix.png
--------------------------------------------------------------------------------
/Screenshot/Mix2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/Mix2.png
--------------------------------------------------------------------------------
/Screenshot/ShiftGlitch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/ShiftGlitch.gif
--------------------------------------------------------------------------------
/Screenshot/Soul.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/Soul.gif
--------------------------------------------------------------------------------
/Screenshot/SoulOut.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/SoulOut.gif
--------------------------------------------------------------------------------
/Screenshot/WechatIMG1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/WechatIMG1.jpg
--------------------------------------------------------------------------------
/Screenshot/WechatIMG2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/WechatIMG2.jpg
--------------------------------------------------------------------------------
/Screenshot/flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/flow.png
--------------------------------------------------------------------------------
/Screenshot/launch.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangKJ/Harbeth/c195eed9192c8686eb28d2434269077e12371d0b/Screenshot/launch.jpeg
--------------------------------------------------------------------------------
/Sources/Basic/Extensions/CGRect+Ext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CGRect+Ext.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/8.
6 | //
7 |
8 | import Foundation
9 |
10 | extension CGRect: HarbethCompatible { }
11 |
12 | extension HarbethWrapper where Base == CGRect {
13 |
14 | public func radius(_ value: Float, max: Float) -> Float {
15 | let base = Float(sqrt(pow(base.width, 2) + pow(base.height, 2)))
16 | return base / 20 * value / max
17 | }
18 |
19 | public func toPoint2D(with size: C7Size) -> C7Point2D {
20 | C7Point2D(x: Float(base.origin.x) / Float(size.width),
21 | y: Float(base.origin.y) / Float(size.height))
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Basic/Extensions/Data+Ext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Data+Ext.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/10/27.
6 | //
7 |
8 | import Foundation
9 | import MetalKit
10 |
11 | extension Data: HarbethCompatible { }
12 |
13 | extension HarbethWrapper where Base == Data {
14 |
15 | /// Image data to texture
16 | ///
17 | /// Texture loader can not load image data to create texture
18 | /// If image orientation is not up, texture loader may not load texture from image data.
19 | /// Create a UIImage from image data to get metal texture
20 | /// Draw image and create texture
21 | /// - Parameter options: Dictonary of MTKTextureLoaderOptions
22 | /// - Returns: MTLTexture
23 | public func toTexture(options: [MTKTextureLoader.Option: Any]? = nil) -> MTLTexture? {
24 | return try? TextureLoader.init(with: base, options: options).texture
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Basic/Extensions/MTLCommandBuffer+Ext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MTLCommandBuffer+Ext.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/8.
6 | //
7 |
8 | import Foundation
9 | import MetalKit
10 |
11 | extension MTLCommandBuffer {
12 |
13 | /// Asynchronous submission of texture drawing.
14 | func asyncCommit(complete: @escaping (Result) -> Void) {
15 | self.addCompletedHandler { (buffer) in
16 | switch buffer.status {
17 | case .completed:
18 | complete(.success(()))
19 | case .error where buffer.error != nil:
20 | complete(.failure(.error(buffer.error!)))
21 | default:
22 | break
23 | }
24 | }
25 | self.commit()
26 | }
27 |
28 | func commitAndWaitUntilCompleted() {
29 | // Commit a command buffer so it can be executed as soon as possible.
30 | self.commit()
31 | // Wait to make sure that output texture contains new data.
32 | self.waitUntilCompleted()
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/Basic/Extensions/URL+Ext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Ext.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/12/8.
6 | //
7 |
8 | import Foundation
9 |
10 | extension URL: HarbethCompatible { }
11 |
12 | extension HarbethWrapper where Base == URL {
13 |
14 | public func loadCGImage() -> CGImage? {
15 | #if os(macOS)
16 | guard let nsImage = C7Image(contentsOf: base),
17 | let tiffData = nsImage.tiffRepresentation,
18 | let cgImageSource = CGImageSourceCreateWithData(tiffData as CFData, nil),
19 | let cgImage = CGImageSourceCreateImageAtIndex(cgImageSource, 0, nil) else {
20 | return nil
21 | }
22 | return cgImage
23 | #else
24 | guard let uiImage = C7Image(contentsOfFile: base.path) else {
25 | return nil
26 | }
27 | return uiImage.cgImage
28 | #endif
29 | }
30 |
31 | public var isLocalResource: Bool {
32 | base.scheme == "file" || base.scheme == "data"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/Basic/Matrix/Matrix.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Matrix.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/18.
6 | //
7 |
8 | import Foundation
9 | import QuartzCore
10 |
11 | public protocol Matrix {
12 | associatedtype MatrixType
13 |
14 | static var size: Int { get }
15 |
16 | var values: [Float] { get set }
17 |
18 | init(values: [Float])
19 |
20 | func to_factor() -> MatrixType
21 | }
22 |
23 | extension Matrix {
24 | public static var size: Int {
25 | MemoryLayout.size
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Basic/Matrix/Matrix4x5.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Matrix4x5.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/11.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 4 x 5 颜色矩阵
11 | public struct Matrix4x5 {
12 |
13 | public let matrix4x4: Matrix4x4
14 | public let vector4: Vector4
15 |
16 | public init(values: [Float]) {
17 | if values.count != 20 {
18 | HarbethError.failed("There must be twenty values for 4x5 Matrix.")
19 | }
20 | var matrix = [Float]()
21 | var vector = [Float]()
22 | for (index, value) in values.enumerated() {
23 | if (index+7) % 5 == 1 {
24 | vector.append(value)
25 | } else {
26 | matrix.append(value)
27 | }
28 | }
29 | self.matrix4x4 = Matrix4x4(values: matrix)
30 | self.vector4 = Vector4(values: vector)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/Basic/Matrix/Vector3.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Vector3.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/11.
6 | //
7 |
8 | import Foundation
9 | import simd
10 |
11 | /// 3维向量
12 | public struct Vector3: Matrix {
13 |
14 | public typealias MatrixType = vector_float3
15 |
16 | public var values: [Float]
17 |
18 | public init(values: [Float]) {
19 | if values.count != 3 {
20 | HarbethError.failed("There must be three values for Vector3.")
21 | }
22 | self.values = values
23 | }
24 |
25 | public init(color: C7Color) {
26 | let (red, green, blue, _) = color.c7.toRGBA()
27 | self.init(values: [red, green, blue])
28 | }
29 |
30 | public func to_factor() -> vector_float3 {
31 | vector_float3.init(values[0], values[1], values[2])
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Basic/Outputs/HugeImage.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HugeImage.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2024/3/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 超大图像
11 | public struct HugeImage {
12 |
13 | public let image: C7Image
14 |
15 | public init(image: C7Image) {
16 | self.image = image
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/Basic/Outputs/RenderImageView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RenderView.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2024/3/20.
6 | //
7 |
8 | import Foundation
9 | import MetalKit
10 |
11 | public final class RenderImageView: C7ImageView, Renderable {
12 |
13 | public typealias Element = C7Image
14 |
15 | public override var image: C7Image? {
16 | didSet {
17 | if lockedSource {
18 | return
19 | }
20 | self.setupInputSource()
21 | self.filtering()
22 | }
23 | }
24 | }
25 |
26 | extension Renderable where Self: C7ImageView {
27 |
28 | public func setupInputSource() {
29 | if lockedSource {
30 | return
31 | }
32 | if let image = self.image {
33 | self.inputSource = try? TextureLoader(with: image).texture
34 | }
35 | }
36 |
37 | public func setupOutputDest(_ dest: MTLTexture) {
38 | DispatchQueue.main.async {
39 | if let image = self.image {
40 | self.lockedSource = true
41 | self.image = try? dest.c7.fixImageOrientation(refImage: image)
42 | self.lockedSource = false
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/Clamping.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Clamping.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/1/8.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Range wrapper.
11 | /// Example: ``@Clamping(0...2) var radius: Float = 1.0``
12 | @propertyWrapper public struct Clamping {
13 | private var value: Value
14 | private let range: ClosedRange
15 |
16 | public var wrappedValue: Value {
17 | get { value }
18 | set { value = Swift.min(Swift.max(newValue, range.lowerBound), range.upperBound) }
19 | }
20 |
21 | public init(wrappedValue: Value, _ range: ClosedRange) {
22 | self.value = Swift.min(Swift.max(wrappedValue, range.lowerBound), range.upperBound)
23 | self.range = range
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/Degree.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Degree.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/11.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct Degree {
11 |
12 | public let value: Float
13 |
14 | public init(value: Float) {
15 | self.value = value
16 | }
17 |
18 | public var radians: Float {
19 | return Float(value * Float.pi / 180.0)
20 | }
21 | }
22 |
23 | // MARK: - Negative Degrees
24 | public prefix func -(degree: Degree) -> Degree {
25 | return Degree(value: -1 * degree.value)
26 | }
27 |
28 | /// `0.0 ..< 360.0` 范围角度区间属性包装器
29 | @propertyWrapper public struct DegreeRange {
30 |
31 | public var wrappedValue: Float {
32 | didSet {
33 | let value = wrappedValue.truncatingRemainder(dividingBy: 360.0)
34 | wrappedValue = value >= 0 ? value : 360 + value
35 | }
36 | }
37 |
38 | public init(wrappedValue: Float) {
39 | let value = wrappedValue.truncatingRemainder(dividingBy: 360.0)
40 | self.wrappedValue = value >= 0 ? value : 360 + value
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/Mirrorable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Mirrorable.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/12/8.
6 | //
7 |
8 | import Foundation
9 |
10 | public protocol Mirrorable {
11 | /// Parametric description.
12 | var parameterDescription: [String: Any] { get }
13 | }
14 |
15 | extension Mirrorable {
16 | public var parameterDescription: [String: Any] {
17 | mapDictionary(mirror: Mirror(reflecting: self))
18 | }
19 | }
20 |
21 | extension Mirrorable {
22 | private func mapDictionary(mirror: Mirror) -> [String: Any] {
23 | var dict: [String: Any] = [:]
24 | for child in mirror.children {
25 | // If there is no labe, it will be discarded.
26 | if let label = child.label {
27 | //_ = Mirror(reflecting: child.value)
28 | dict[label] = child.value
29 | }
30 | }
31 | if let superMirror = mirror.superclassMirror {
32 | let superDic = mapDictionary(mirror: superMirror)
33 | for x in superDic {
34 | dict[x.key] = x.value
35 | }
36 | }
37 | return dict
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/ParameterRange.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ParameterRange.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/10/14.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct ParameterRange {
11 |
12 | public let min: T
13 | public let max: T
14 | public let value: T
15 |
16 | /// Initialize the parameter range.
17 | /// - Parameters:
18 | /// - min: Indicates the minimum value
19 | /// - max: Indicates the maximum value
20 | /// - value: Indicates the default value
21 | public init(min: T, max: T, value: T) {
22 | self.min = min
23 | self.max = max
24 | self.value = value
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/Pixel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Pixel.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2024/2/28.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct Pixel {
11 | /// 颜色通道
12 | public enum Channel: Int {
13 | case red = 0
14 | case green
15 | case blue
16 | case alpha
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/Point2D.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Point2D.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/10/12.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 对于 2D 纹理,采用归一化之后的纹理坐标, 在 x 轴和 y 轴方向上都是从 0.0 到 1.0
11 | /// 2D textures, normalized texture coordinates are used, from 0.0 to 1.0 in both x and y directions
12 | public struct C7Point2D {
13 |
14 | public static let maximum = C7Point2D(x: 1.0, y: 1.0)
15 | public static let center = C7Point2D(x: 0.5, y: 0.5)
16 | public static let zero = C7Point2D(x: 0.0, y: 0.0)
17 |
18 | @ZeroOneRange public var x: Float
19 | @ZeroOneRange public var y: Float
20 |
21 | public init(x: Float, y: Float) {
22 | self.x = x
23 | self.y = y
24 | }
25 |
26 | /// Initialize the normalized texture coordinates.
27 | /// - Parameters:
28 | /// - point: Current coordinate point.
29 | /// - size: Image size.
30 | public init(point: CGPoint, size: CGSize) {
31 | let x_ = Float(point.x / size.width)
32 | let y_ = Float(point.y / size.height)
33 | self.init(x: x_, y: y_)
34 | }
35 | }
36 |
37 | extension C7Point2D {
38 | public func toXY() -> [Float] {
39 | [x, y]
40 | }
41 | }
42 |
43 | extension C7Point2D: Equatable {
44 |
45 | public static func == (lhs: C7Point2D, rhs: C7Point2D) -> Bool {
46 | lhs.x == rhs.x && lhs.y == rhs.y
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/Size.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Size.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/10/12.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Size {
11 |
12 | public static let zero = C7Size(width: 0, height: 0)
13 |
14 | public var width: Int
15 | public var height: Int
16 |
17 | public init(width: Int, height: Int) {
18 | self.width = width
19 | self.height = height
20 | }
21 | }
22 |
23 | extension C7Size {
24 | public func toFloatArray() -> [Float] {
25 | [Float(width), Float(height)]
26 | }
27 | }
28 |
29 | extension C7Size: Equatable {
30 |
31 | public static func == (lhs: C7Size, rhs: C7Size) -> Bool {
32 | lhs.width == rhs.width && lhs.height == rhs.height
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/Typealias.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Typealias.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/16.
6 | //
7 |
8 | import Foundation
9 | @_exported import MetalKit
10 | @_exported import CoreVideo
11 | @_exported import CoreImage
12 | @_exported import CoreMedia
13 | @_exported import AVFoundation
14 | import ImageIO
15 |
16 | #if os(iOS) || os(tvOS) || os(watchOS)
17 | import UIKit
18 | public typealias C7View = UIView
19 | public typealias C7Color = UIColor
20 | public typealias C7Image = UIImage
21 | public typealias C7EdgeInsets = UIEdgeInsets
22 | public typealias C7ImageView = UIImageView
23 | public typealias C7ImageOrientation = UIImage.Orientation
24 | #elseif os(macOS)
25 | import AppKit
26 | public typealias C7View = NSView
27 | public typealias C7Color = NSColor
28 | public typealias C7Image = NSImage
29 | public typealias C7EdgeInsets = NSEdgeInsets
30 | public typealias C7ImageView = NSImageView
31 | public typealias C7ImageOrientation = CGImagePropertyOrientation
32 | #endif
33 |
34 | public typealias C7InputTextures = [MTLTexture]
35 | public typealias C7FilterImageCallback = (_ image: C7Image) -> Void
36 |
37 | typealias C7KernelFunction = String
38 |
39 | // Make sure to run on the main thread.
40 | //@inline(__always) func make_run_on_main_thread() {
41 | // assert(Thread.isMainThread)
42 | //}
43 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/Wrapper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Wrapper.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Add the `c7` prefix namespace.
11 | public struct HarbethWrapper {
12 | /// Stores the type or meta-type of any extended type.
13 | public private(set) var base: Base
14 | /// Create an instance from the provided value.
15 | public init(base: Base) {
16 | self.base = base
17 | }
18 | }
19 |
20 | /// Protocol describing the `c7` extension points for Alamofire extended types.
21 | public protocol HarbethCompatible { }
22 |
23 | extension HarbethCompatible {
24 |
25 | public var c7: HarbethWrapper {
26 | get { return HarbethWrapper(base: self) }
27 | set { }
28 | }
29 |
30 | public static var c7: HarbethWrapper.Type {
31 | HarbethWrapper.self
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Basic/Setup/ZeroOneRange.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ZeroOneRange.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/25.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 0.0 ~ 1.0 范围区间属性包装器
11 | /// 0.0 ~ 1.0 Range Interval Property Packer.
12 | @propertyWrapper public struct ZeroOneRange {
13 |
14 | public var wrappedValue: Float {
15 | didSet {
16 | wrappedValue = min(1.0, max(0.0, wrappedValue))
17 | }
18 | }
19 |
20 | public init(wrappedValue: Float) {
21 | self.wrappedValue = min(1.0, max(0.0, wrappedValue))
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendColorAlpha.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendColorAlpha.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendColorAlpha(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *mixturePercent [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 outColor(mix(inColor.rgb, overlay.rgb, overlay.a * half(*mixturePercent)), inColor.a);
22 |
23 | outputTexture.write(outColor, grid);
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendColorBurn.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendColorBurn.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendColorBurn(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 whiteColor = half4(1.0h);
22 | const half4 outColor = whiteColor - (whiteColor - inColor) / overlay;
23 | const half4 output = mix(inColor, outColor, half(*intensity));
24 |
25 | outputTexture.write(output, grid);
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendDarken.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendDarken.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendDarken(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 outColor(min(overlay.rgb * inColor.a, inColor.rgb * overlay.a) + overlay.rgb * (1.0h - inColor.a) + inColor.rgb * (1.0h - overlay.a), 1.0h);
22 |
23 | const half4 output = mix(inColor, outColor, half(*intensity));
24 |
25 | outputTexture.write(output, grid);
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendDifference.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendDifference.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendDifference(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 outColor(abs(overlay.rgb - inColor.rgb), inColor.a);
22 |
23 | const half4 output = mix(inColor, outColor, half(*intensity));
24 |
25 | outputTexture.write(output, grid);
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendDissolve.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendDissolve.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendDissolve(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 outColor = mix(inColor, overlay, half(*intensity));
22 |
23 | outputTexture.write(outColor, grid);
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendExclusion.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendExclusion.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendExclusion(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half3 excolor = half3(overlay.rgb * inColor.a + inColor.rgb * overlay.a - 2.0h * overlay.rgb * inColor.rgb) + overlay.rgb * (1.0h - inColor.a) + inColor.rgb * (1.0h - overlay.a);
22 | const half4 outColor = half4(excolor, inColor.a);
23 | const half4 output = mix(inColor, outColor, half(*intensity));
24 |
25 | outputTexture.write(output, grid);
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendLighten.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendLighten.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendLighten(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 outColor = max(inColor, overlay);
22 | const half4 output = mix(inColor, outColor, half(*intensity));
23 |
24 | outputTexture.write(output, grid);
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendLinearBurn.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendLinearBurn.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendLinearBurn(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 outColor = half4(clamp(inColor.rgb + overlay.rgb - half3(1.0h), half3(0.0h), half3(1.0h)), inColor.a);
22 | const half4 output = mix(inColor, outColor, half(*intensity));
23 |
24 | outputTexture.write(output, grid);
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendMask.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendMask.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendMask(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half newAlpha = dot(overlay.rgb, half3(.33333334, .33333334, .33333334)) * overlay.a;
22 | const half4 outColor = half4(inColor.rgb, newAlpha);
23 | const half4 output = mix(inColor, outColor, half(*intensity));
24 |
25 | outputTexture.write(output, grid);
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendMultiply.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendMultiply.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendMultiply(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 outColor = overlay * inColor + overlay * (1.0h - inColor.a) + inColor * (1.0h - overlay.a);
22 | const half4 output = mix(inColor, outColor, half(*intensity));
23 |
24 | outputTexture.write(output, grid);
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendNormal.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendNormal.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendNormal(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | half4 outColor;
22 | outColor.rgb = overlay.rgb + inColor.rgb * inColor.a * (1 - overlay.a);
23 | outColor.a = overlay.a + inColor.a * (1 - overlay.a);
24 |
25 | const half4 output = mix(inColor, outColor, half(*intensity));
26 |
27 | outputTexture.write(output, grid);
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendScreen.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendScreen.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendScreen(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 whiteColor = half4(1.0);
22 | const half4 outColor = whiteColor - ((whiteColor - overlay) * (whiteColor - inColor));
23 | const half4 output = mix(inColor, outColor, half(*intensity));
24 |
25 | outputTexture.write(output, grid);
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendSoftLight.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendSoftLight.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendSoftLight(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half alphaDivisor = inColor.a + step(inColor.a, 0.0h);
22 | const half4 outColor = inColor * (overlay.a * (inColor / alphaDivisor) + (2.0h * overlay * (1.0h - (inColor / alphaDivisor)))) + overlay * (1.0h - inColor.a) + inColor * (1.0h - overlay.a);
23 | const half4 output = mix(inColor, outColor, half(*intensity));
24 |
25 | outputTexture.write(output, grid);
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendSourceOver.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendSourceOver.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendSourceOver(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 outColor = mix(inColor, overlay, overlay.a);
22 | const half4 output = mix(inColor, outColor, half(*intensity));
23 |
24 | outputTexture.write(output, grid);
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Blend/C7BlendSubtract.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7BlendSubtract.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7BlendSubtract(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | texture2d inputTexture2 [[texture(2)]],
14 | constant float *intensity [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 | const half4 overlay = inputTexture2.sample(quadSampler, textureCoordinate);
20 |
21 | const half4 outColor = half4(inColor.rgb - overlay.rgb, inColor.a);
22 | const half4 output = mix(inColor, outColor, half(*intensity));
23 |
24 | outputTexture.write(output, grid);
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7BilateralBlur.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7BilateralBlur.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/2.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 双边模糊
11 | public struct C7BilateralBlur: C7FilterProtocol {
12 |
13 | public var radius: Float = 1
14 |
15 | public var offect: C7Point2D = C7Point2D.center
16 |
17 | public var modifier: Modifier {
18 | return .compute(kernel: "C7BilateralBlur")
19 | }
20 |
21 | public var factors: [Float] {
22 | return [radius, offect.x, offect.y]
23 | }
24 |
25 | public init(radius: Float = 1) {
26 | self.radius = radius
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7CircleBlur.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7CircleBlur.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/17.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7CircleBlur(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *blurRadius [[buffer(0)]],
14 | constant float *sampleCountPointer [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
17 | const float2 textureCoordinate = float2(grid) / float2(outputTexture.get_width(), outputTexture.get_height());
18 | const half radius = half(*blurRadius) / 100.0h;
19 | const half sampleCount = half(*sampleCountPointer);
20 |
21 | half4 result = half4(0.0h);
22 | for (int i = 0; i < sampleCount; ++i) {
23 | float fraction = float(i) / sampleCount;
24 | float x = textureCoordinate.x;
25 | float y = textureCoordinate.y;
26 | float angle = fraction * M_PI_F * 2;
27 | x += cos(angle) * radius;
28 | y += sin(angle) * radius;
29 | const half4 sample = inputTexture.sample(quadSampler, float2(x, y));
30 | result += sample;
31 | }
32 |
33 | const half4 outColor = result / sampleCount;
34 | outputTexture.write(outColor, grid);
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7CircleBlur.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7CircleBlur.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/17.
6 | //
7 |
8 | import Foundation
9 |
10 | // See: https://www.imgonline.com.ua/eng/blur-angular.php
11 | // https://support.apple.com/en-in/guide/motion/motn169f953e/mac
12 | public struct C7CircleBlur: C7FilterProtocol {
13 |
14 | public static let range: ParameterRange = .init(min: 0, max: 100, value: 10)
15 |
16 | /// Sets the radius of the circle defining the blurred area. You can also drag the onscreen controls in the canvas.
17 | public var radius: Float = range.value
18 |
19 | /// Sets the amount of the blur.
20 | public var amount: Int = 20
21 |
22 | public var modifier: Modifier {
23 | return .compute(kernel: "C7CircleBlur")
24 | }
25 |
26 | public var factors: [Float] {
27 | return [radius, Float(amount)]
28 | }
29 |
30 | public init(radius: Float = range.value, amount: Int = 20) {
31 | self.radius = radius
32 | self.amount = amount
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7GaussianBlur.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7GaussianBlur.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/2.
6 | //
7 |
8 | // 理论知识
9 | // https://juejin.cn/post/6944757638005686286
10 |
11 | #include
12 | using namespace metal;
13 |
14 | kernel void C7GaussianBlur(texture2d outputTexture [[texture(0)]],
15 | texture2d inputTexture [[texture(1)]],
16 | constant float *blurRadius [[buffer(0)]],
17 | uint2 grid [[thread_position_in_grid]]) {
18 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
19 | const float2 textureCoordinate = float2(grid) / float2(outputTexture.get_width(), outputTexture.get_height());
20 | const half radius = half(*blurRadius) / 100.0h;
21 | const float x = textureCoordinate.x;
22 | const float y = textureCoordinate.y;
23 |
24 | // 高斯模糊卷积核
25 | const half3x3 matrix = half3x3({1.0, 2.0, 1.0}, {2.0, 4.0, 2.0}, {1.0, 2.0, 1.0});
26 | half4 result = half4(0.0h);
27 | for (int i = 0; i < 9; i++) {
28 | int a = i % 3; int b = i / 3;
29 | const half4 sample = inputTexture.sample(quadSampler, float2(x + (a-1) * radius, y + (b-1) * radius));
30 | result += sample * matrix[a][b];
31 | }
32 |
33 | const half4 outColor = result / 16.0h;
34 | outputTexture.write(outColor, grid);
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7GaussianBlur.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7GaussianBlur.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/2.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7GaussianBlur: C7FilterProtocol {
11 |
12 | public static let range: ParameterRange = .init(min: 0, max: 100, value: 10)
13 |
14 | /// Sets the radius of the blur.
15 | public var radius: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .compute(kernel: "C7GaussianBlur")
19 | }
20 |
21 | public var factors: [Float] {
22 | return [radius]
23 | }
24 |
25 | public init(radius: Float = range.value) {
26 | self.radius = radius
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7MeanBlur.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7MeanBlur.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/2.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | // 均值模糊原理其实很简单通过多个纹理叠加,每个纹理偏移量设置不同达到一点重影效果来实现模糊
12 | kernel void C7MeanBlur(texture2d outputTexture [[texture(0)]],
13 | texture2d inputTexture [[texture(1)]],
14 | constant float *blurRadius [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
17 | const float2 coordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
18 | const half radius = half(*blurRadius) / 100.0h;
19 |
20 | const half4 sample1 = inputTexture.sample(quadSampler, float2(coordinate.x - radius, coordinate.y - radius));
21 | const half4 sample2 = inputTexture.sample(quadSampler, float2(coordinate.x + radius, coordinate.y + radius));
22 | const half4 sample3 = inputTexture.sample(quadSampler, float2(coordinate.x + radius, coordinate.y - radius));
23 | const half4 sample4 = inputTexture.sample(quadSampler, float2(coordinate.x - radius, coordinate.y + radius));
24 |
25 | const half4 outColor = (sample1 + sample2 + sample3 + sample4) / 4.0h;
26 | outputTexture.write(outColor, grid);
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7MeanBlur.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7MeanBlur.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/2.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 均值模糊效果
11 | /// https://docs.gimp.org/2.10/en/gimp-filter-median-blur.html
12 | public struct C7MeanBlur: C7FilterProtocol {
13 |
14 | public static let range: ParameterRange = .init(min: 0, max: 100, value: 10)
15 |
16 | /// The radius of the neighborhood. Increasing radius increases blur.
17 | /// Contrary to the “Gaussian” filter, edges are not blurred. Corners are rounded and convex surfaces are eroded.
18 | public var radius: Float = range.value
19 |
20 | public var modifier: Modifier {
21 | return .compute(kernel: "C7MeanBlur")
22 | }
23 |
24 | public var factors: [Float] {
25 | return [radius]
26 | }
27 |
28 | public init(radius: Float = range.value) {
29 | self.radius = radius
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7MotionBlur.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7MotionBlur.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 移动模糊
11 | public struct C7MotionBlur: C7FilterProtocol {
12 |
13 | /// A multiplier for the blur size
14 | public var radius: Float = 0
15 |
16 | /// The angular direction of the blur, in degrees, with a default of 0.0
17 | public var blurAngle: Float = 0
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7MotionBlur")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [radius, blurAngle]
25 | }
26 |
27 | public init(radius: Float = 0, blurAngle: Float = 0) {
28 | self.radius = radius
29 | self.blurAngle = blurAngle
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7RedMonochromeBlur.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7RedMonochromeBlur.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/16.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 红色单色模糊效果,呈黑白状态。
11 | /// Red monochrome blur effect, single channel expansion.
12 | public struct C7RedMonochromeBlur: C7FilterProtocol {
13 |
14 | /// Radius in pixel, with a default of 0.0
15 | public var pixelRadius: Int = 0
16 |
17 | /// Whether to blurred in horizontal direction.
18 | public var horizontal: Bool = true
19 |
20 | /// Whether to blurred in vertical direction.
21 | public var vertical: Bool = true
22 |
23 | public var modifier: Modifier {
24 | return .compute(kernel: "C7RedMonochromeBlur")
25 | }
26 |
27 | public var factors: [Float] {
28 | return [Float(pixelRadius), vertical ? 1:0, horizontal ? 1:0]
29 | }
30 |
31 | public init(pixelRadius: Int = 0) {
32 | self.pixelRadius = pixelRadius
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/Compute/Blur/C7ZoomBlur.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ZoomBlur.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/10.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 缩放模糊效果
11 | /// See: https://support.apple.com/en-in/guide/motion/motn169fc244/mac
12 | public struct C7ZoomBlur: C7FilterProtocol {
13 |
14 | /// A multiplier for the blur size, ranging from 0.0 on up, with a default of 0.0
15 | /// Sets the radius of the blur. Drag the small circle (above the Center onscreen control) in the canvas to adjust the blur amount.
16 | public var radius: Float = 0
17 |
18 | /// Sets the position of the center of the blur. Drag the Center onscreen control in the canvas to adjust the center position.
19 | public var blurCenter: C7Point2D = C7Point2D.center
20 |
21 | public var modifier: Modifier {
22 | return .compute(kernel: "C7ZoomBlur")
23 | }
24 |
25 | public var factors: [Float] {
26 | return [blurCenter.x, blurCenter.y, radius]
27 | }
28 |
29 | public init(radius: Float = 0) {
30 | self.radius = radius
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Bulge.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Bulge.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Bulge: C7FilterProtocol {
11 |
12 | /// 2D textures, normalized texture coordinates are used, from 0.0 to 1.0 in both x and y directions
13 | public var center: C7Point2D = C7Point2D.center
14 | /// The radius from the center to apply the distortion, with a default of 0.25
15 | public var radius: Float = 0.25
16 | /// The amount of distortion to apply, from -1.0 to 1.0, with a default of 0.5
17 | public var scale: Float = 0.5
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7Bulge")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [center.x, center.y, radius, scale]
25 | }
26 |
27 | public init(radius: Float = 0.25, scale: Float = 0.5) {
28 | self.radius = radius
29 | self.scale = scale
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7ColorCGASpace.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorCGASpace.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/11.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 图像CGA色彩滤镜,形成黑、浅蓝、紫色块的画面
11 | public struct C7ColorCGASpace: C7FilterProtocol {
12 | /// Intensity range, used to adjust the mixing ratio of filters and sources.
13 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
14 |
15 | public var modifier: Modifier {
16 | return .compute(kernel: "C7ColorCGASpace")
17 | }
18 |
19 | public var factors: [Float] {
20 | return [intensity]
21 | }
22 |
23 | public init() { }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7ColorPacking.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorPacking.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/11.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 色彩丢失/模糊效果
11 | public struct C7ColorPacking: C7FilterProtocol {
12 |
13 | /// The larger the transverse offset, the more the green contour shadow offset to the right.
14 | /// The texel width and height determines how far out to sample from this texel.
15 | public var horizontalTexel: Float
16 | /// The larger the vertical offset, the more the blue contour shadow offset downward.
17 | public var verticalTexel: Float
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7ColorPacking")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [horizontalTexel, verticalTexel]
25 | }
26 |
27 | public init(horizontalTexel: Float = 0, verticalTexel: Float = 0) {
28 | self.horizontalTexel = horizontalTexel
29 | self.verticalTexel = verticalTexel
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Fluctuate.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Fluctuate.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/30.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Fluctuate(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *extent [[buffer(0)]],
14 | constant float *amplitude [[buffer(1)]],
15 | constant float *fluctuate [[buffer(2)]],
16 | uint2 grid [[thread_position_in_grid]]) {
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | const float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
19 |
20 | float2 offset = float2(0, 0);
21 | offset.x = sin(grid.x * *extent + *fluctuate) * *amplitude;
22 | offset.y = cos(grid.y * *extent + *fluctuate) * *amplitude;
23 |
24 | const float2 tx = textureCoordinate + offset;
25 | const half4 outColor = inputTexture.sample(quadSampler, tx);
26 |
27 | outputTexture.write(outColor, grid);
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Fluctuate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Fluctuate.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/30.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 波动效果,还可类似涂鸦效果
11 | public struct C7Fluctuate: C7FilterProtocol {
12 |
13 | /// 控制振幅的大小,越大图像越夸张
14 | /// Control the size of the amplitude, the larger the image, the more exaggerated the image.
15 | public var amplitude: Float = 0.002
16 | public var extent: Float = 50.0
17 | public var fluctuate: Float = 0.5
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7Fluctuate")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [extent, amplitude, fluctuate]
25 | }
26 |
27 | public init(extent: Float = 50.0, amplitude: Float = 0.002, fluctuate: Float = 0.5) {
28 | self.extent = extent
29 | self.amplitude = amplitude
30 | self.fluctuate = fluctuate
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7GlassSphere.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7GlassSphere.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/16.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7GlassSphere: C7FilterProtocol {
11 |
12 | public var radius: Float = 0.25
13 | public var refractiveIndex: Float = 0.71
14 | public var aspectRatio: Float = 1
15 | public var center: C7Point2D = C7Point2D.center
16 |
17 | public var modifier: Modifier {
18 | return .compute(kernel: "C7GlassSphere")
19 | }
20 |
21 | public var factors: [Float] {
22 | return [radius, refractiveIndex, aspectRatio, center.x, center.y]
23 | }
24 |
25 | public init(radius: Float = 0.25, refractiveIndex: Float = 0.71, aspectRatio: Float = 1) {
26 | self.radius = radius
27 | self.refractiveIndex = refractiveIndex
28 | self.aspectRatio = aspectRatio
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Glitch.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Glitch.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/17.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Glitch: C7FilterProtocol {
11 |
12 | /// The adjusted glitch, from 0.0 to 1.0, with a default of 0.5
13 | public var glitch: Float = 0.5
14 |
15 | /// Maximum jitter ratio.
16 | public var maxJitter: Float = 0.06
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Glitch")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [glitch, maxJitter]
24 | }
25 |
26 | public init(glitch: Float = 0.5, maxJitter: Float = 0.06) {
27 | self.glitch = glitch
28 | self.maxJitter = maxJitter
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Halftone.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Halftone.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Halftone: C7FilterProtocol {
11 |
12 | /// How large the halftone dots are, as a fraction of the width of the image, default of 0.01
13 | public var fractionalWidth: Float = 0.01
14 |
15 | public var modifier: Modifier {
16 | return .compute(kernel: "C7Halftone")
17 | }
18 |
19 | public var factors: [Float] {
20 | return [fractionalWidth]
21 | }
22 |
23 | public init(fractionalWidth: Float = 0.01) {
24 | self.fractionalWidth = fractionalWidth
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Kuwahara.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Kuwahara.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Kuwahara: C7FilterProtocol {
11 |
12 | /// The radius to sample from when creating the brush-stroke effect, with a default of 3.
13 | /// The larger the radius, the slower the filter.
14 | public var radius: Int = 3
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7Kuwahara")
18 | }
19 |
20 | public var factors: [Float] {
21 | return [Float(radius)]
22 | }
23 |
24 | public init(radius: Int = 3) {
25 | self.radius = radius
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7OilPainting.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7OilPainting.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/29.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 油画滤镜
11 | public struct C7OilPainting: C7FilterProtocol {
12 |
13 | public var radius: Float = 3.0
14 | public var pixel: Int = 1
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7OilPainting")
18 | }
19 |
20 | public var factors: [Float] {
21 | return [radius, Float(pixel)]
22 | }
23 |
24 | public init(radius: Float = 3.0, pixel: Int = 1) {
25 | self.radius = radius
26 | self.pixel = pixel
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Pinch.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Pinch.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Pinch: C7FilterProtocol {
11 |
12 | public var center: C7Point2D = C7Point2D.center
13 | /// The radius from the center to apply the distortion, with a default of 0.25
14 | public var radius: Float = 0.5
15 | /// The amount of distortion to apply, from -2.0 to 2.0, with a default of 0.5
16 | public var scale: Float = 0.5
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Pinch")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [center.x, center.y, radius, scale]
24 | }
25 |
26 | public init(radius: Float = 0.5, scale: Float = 0.5) {
27 | self.radius = radius
28 | self.scale = scale
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Pixellated.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Pixellated.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Pixellated(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *pixelScale [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
16 |
17 | const float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
18 | const float2 scale = float2(*pixelScale, *pixelScale);
19 | const float2 samplePos = textureCoordinate - fmod(textureCoordinate, scale) + scale * 0.5;
20 |
21 | const half4 outColor = inputTexture.sample(quadSampler, samplePos);
22 |
23 | outputTexture.write(outColor, grid);
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Pixellated.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Pixellated.swift
3 | // MetalDemo
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 马赛克像素化
11 | public struct C7Pixellated: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 0.05)
14 |
15 | /// Adjust the pixel color block size, from 0.0 to 1.0, with a default of 0.05
16 | @ZeroOneRange public var scale: Float = range.value
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Pixellated")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [scale]
24 | }
25 |
26 | public init(scale: Float = range.value) {
27 | self.scale = scale
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7PolarPixellate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7PolarPixellate.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7PolarPixellate: C7FilterProtocol {
11 |
12 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 0.05)
13 |
14 | public var center: C7Point2D = C7Point2D.center
15 |
16 | /// The fractional pixel size, from 0.0 to 1.0, with a default of 0.05
17 | @ZeroOneRange public var scale: Float = range.value
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7PolarPixellate")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [scale, center.x, center.y]
25 | }
26 |
27 | public init(scale: Float = range.value) {
28 | self.scale = scale
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7PolkaDot.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7PolkaDot.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7PolkaDot: C7FilterProtocol {
11 |
12 | /// How large the dots are, as a fraction of the width and height of the image, default of 0.05
13 | public var fractionalWidth: Float = 0.05
14 | /// What fraction of each grid space is taken up by a dot, default of 0.9
15 | public var dotScaling: Float = 0.9
16 |
17 | public var modifier: Modifier {
18 | return .compute(kernel: "C7PolkaDot")
19 | }
20 |
21 | public var factors: [Float] {
22 | return [fractionalWidth, dotScaling]
23 | }
24 |
25 | public init(fractionalWidth: Float = 0.05, dotScaling: Float = 0.9) {
26 | self.fractionalWidth = fractionalWidth
27 | self.dotScaling = dotScaling
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7RGBADilation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7RGBADilation.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/16.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Find the maximum value of each color channel in the range of radius, and set the maximum value to the current pixel.
11 | public struct C7RGBADilation: C7FilterProtocol {
12 |
13 | /// Radius in pixel, with a default of 0.0
14 | public var pixelRadius: Int = 0
15 |
16 | public var vertical: Bool = false
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7RGBADilation")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [Float(pixelRadius), vertical ? 1 : 0]
24 | }
25 |
26 | public init(pixelRadius: Int = 0) {
27 | self.pixelRadius = pixelRadius
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Sharpen.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Sharpen.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Sharpen: C7FilterProtocol {
11 |
12 | public static let range: ParameterRange = .init(min: -4.0, max: 4.0, value: 0.0)
13 |
14 | /// Change the opacity of an image, from -4.0 to 4.0, with a default of 0.0
15 | public var sharpeness: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .compute(kernel: "C7Sharpen")
19 | }
20 |
21 | public var factors: [Float] {
22 | return [sharpeness]
23 | }
24 |
25 | public init(sharpeness: Float = range.value) {
26 | self.sharpeness = sharpeness
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Sketch.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Sketch.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Sketch: C7FilterProtocol {
11 |
12 | /// Adjusts the dynamic range of the filter.
13 | /// Higher values lead to stronger edges, but can saturate the intensity colorspace.
14 | public var edgeStrength: Float = 1
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7Sketch")
18 | }
19 |
20 | public var factors: [Float] {
21 | return [edgeStrength]
22 | }
23 |
24 | public init(edgeStrength: Float = 1) {
25 | self.edgeStrength = edgeStrength
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7SoulOut.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7SoulOut.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/17.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 灵魂出窍效果
11 | public struct C7SoulOut: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 0.5)
14 |
15 | /// The adjusted soul, from 0.0 to 1.0, with a default of 0.5
16 | @ZeroOneRange public var soul: Float = range.value
17 | public var maxScale: Float = 1.5
18 | @ZeroOneRange public var maxAlpha: Float = 0.5
19 |
20 | public var modifier: Modifier {
21 | return .compute(kernel: "C7SoulOut")
22 | }
23 |
24 | public var factors: [Float] {
25 | return [soul, maxScale, maxAlpha]
26 | }
27 |
28 | public init(soul: Float = range.value, maxScale: Float = 1.5, maxAlpha: Float = 0.5) {
29 | self.soul = soul
30 | self.maxScale = maxScale
31 | self.maxAlpha = maxAlpha
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7SphereRefraction.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7SphereRefraction.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/16.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7SphereRefraction: C7FilterProtocol {
11 |
12 | public var radius: Float = 0.25
13 | public var refractiveIndex: Float = 0.71
14 | public var aspectRatio: Float = 1
15 | public var center: C7Point2D = C7Point2D.center
16 |
17 | public var modifier: Modifier {
18 | return .compute(kernel: "C7SphereRefraction")
19 | }
20 |
21 | public var factors: [Float] {
22 | return [radius, refractiveIndex, aspectRatio, center.x, center.y]
23 | }
24 |
25 | public init(radius: Float = 0.25, refractiveIndex: Float = 0.71, aspectRatio: Float = 1) {
26 | self.radius = radius
27 | self.refractiveIndex = refractiveIndex
28 | self.aspectRatio = aspectRatio
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7SplitScreen.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7SplitScreen.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/17.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7SplitScreen(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *screen [[buffer(0)]],
14 | constant float *direction [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const float x = float(grid.x) / outputTexture.get_width();
17 | const float y = float(grid.y) / outputTexture.get_height();
18 |
19 | float temp = (*direction) ? y : x;
20 | if (*screen == 2.0) {
21 | temp += temp < 0.5 ? 0.25 : -0.25;
22 | } else if (*screen == 3.0) {
23 | temp += temp < 1.0/3.0 ? 1.0/3.0 : (temp > 2.0/3.0) ? -1.0/3.0 : 0.0;
24 | }
25 | const float2 xy = (*direction) ? float2(x, temp) : float2(temp, y);
26 |
27 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
28 | const half4 outColor = inputTexture.sample(quadSampler, xy);
29 | outputTexture.write(outColor, grid);
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7SplitScreen.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7SplitScreen.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/17.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7SplitScreen: C7FilterProtocol {
11 |
12 | public enum ScreenType: Int {
13 | case two = 2
14 | case three = 3
15 | }
16 |
17 | public enum DirectionType: Int {
18 | case horizontal
19 | case vertical
20 | }
21 |
22 | public var type: ScreenType = .two
23 |
24 | public var direction: DirectionType = .vertical
25 |
26 | public var modifier: Modifier {
27 | return .compute(kernel: "C7SplitScreen")
28 | }
29 |
30 | public var factors: [Float] {
31 | return [Float(type.rawValue), Float(direction.rawValue)]
32 | }
33 |
34 | public init(type: ScreenType = .two, direction: DirectionType = .vertical) {
35 | self.type = type
36 | self.direction = direction
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Storyboard.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Storyboard.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/2.
6 | //
7 |
8 | // See:https://www.shadertoy.com/view/7sscDX
9 |
10 | #include
11 | using namespace metal;
12 |
13 | kernel void C7Storyboard(texture2d outputTexture [[texture(0)]],
14 | texture2d inputTexture [[texture(1)]],
15 | constant float *few [[buffer(0)]],
16 | uint2 grid [[thread_position_in_grid]]) {
17 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
18 | const float x = float(grid.x) / outputTexture.get_width();
19 | const float y = float(grid.y) / outputTexture.get_height();
20 | const float2 textureCoordinate = float2(x, y);
21 | const int N = int(*few);
22 | const float2 uv = fmod(textureCoordinate, 1.0 / N) * N;
23 |
24 | const half4 outColor = inputTexture.sample(quadSampler, uv);
25 |
26 | outputTexture.write(outColor, grid);
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Storyboard.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Storyboard.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/2.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 分镜滤镜
11 | public struct C7Storyboard: C7FilterProtocol {
12 |
13 | /// It is divided into `ranks²` screens.
14 | @Clamping(1...Int.max) public var ranks: Int = 2
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7Storyboard")
18 | }
19 |
20 | public var factors: [Float] {
21 | return [Float(ranks)]
22 | }
23 |
24 | public init(ranks: Int = 2) {
25 | self.ranks = ranks
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Swirl.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Swirl.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Swirl: C7FilterProtocol {
11 |
12 | public var center: C7Point2D = C7Point2D.center
13 | /// The radius from the center to apply the distortion, with a default of 0.25
14 | public var radius: Float = 0.5
15 | /// The amount of twist to apply to the image
16 | public var angle: Float = 1
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Swirl")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [center.x, center.y, radius, angle]
24 | }
25 |
26 | public init(radius: Float = 0.5, angle: Float = 1) {
27 | self.radius = radius
28 | self.angle = angle
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7ThresholdSketch.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ThresholdSketch.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 阀值素描感滤镜
11 | public struct C7ThresholdSketch: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 0.25)
14 |
15 | /// Any edge above this threshold will be black, and anything below white. Ranges from 0.0 to 1.0
16 | @ZeroOneRange public var threshold: Float = range.value
17 |
18 | /// Adjusts the dynamic range of the filter.
19 | /// Higher values lead to stronger edges, but can saturate the intensity colorspace.
20 | public var edgeStrength: Float = 1
21 |
22 | public var modifier: Modifier {
23 | return .compute(kernel: "C7ThresholdSketch")
24 | }
25 |
26 | public var factors: [Float] {
27 | return [edgeStrength, threshold]
28 | }
29 |
30 | public init(edgeStrength: Float = 1, threshold: Float = range.value) {
31 | self.edgeStrength = edgeStrength
32 | self.threshold = threshold
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7Toon.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Toon.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Toon: C7FilterProtocol {
11 |
12 | public static let thresholdRange: ParameterRange = .init(min: 0.0, max: 1.0, value: 0.2)
13 |
14 | /// The sensitivity of the edge detection, with lower values being more sensitive. Ranges from 0.0 to 1.0
15 | @ZeroOneRange public var threshold: Float = thresholdRange.value
16 |
17 | /// The number of color levels to represent in the final image. Default is 10.0
18 | public var quantizationLevels: Float = 10
19 |
20 | public var modifier: Modifier {
21 | return .compute(kernel: "C7Toon")
22 | }
23 |
24 | public var factors: [Float] {
25 | return [threshold, quantizationLevels]
26 | }
27 |
28 | public init(quantizationLevels: Float = 10, threshold: Float = thresholdRange.value) {
29 | self.quantizationLevels = quantizationLevels
30 | self.threshold = threshold
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/Compute/Coordinate/C7WaterRipple.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7WaterRipple.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/21.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 水波纹效果
11 | public struct C7WaterRipple: C7FilterProtocol {
12 |
13 | public static let rippleRange: ParameterRange = .init(min: 0.0, max: 1.0, value: 0.0)
14 |
15 | /// The waves, from 0.0 to 1.0
16 | @ZeroOneRange public var ripple: Float = rippleRange.value
17 | /// Click location, normalized
18 | public var touchCenter: C7Point2D = C7Point2D.center
19 | /// The wave size
20 | public var boundary: Float = 0.06
21 |
22 | public var modifier: Modifier {
23 | return .compute(kernel: "C7WaterRipple")
24 | }
25 |
26 | public var factors: [Float] {
27 | return [touchCenter.x, touchCenter.y, ripple, boundary]
28 | }
29 |
30 | public init(ripple: Float = rippleRange.value, boundary: Float = 0.06) {
31 | self.ripple = ripple
32 | self.boundary = boundary
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/Compute/Generator/C7ColorGradient.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorGradient.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/7/27.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 常见渐变色滤镜
11 | public struct C7ColorGradient: C7FilterProtocol {
12 |
13 | public enum GradientType {
14 | case rgUV
15 | case rgUVB1
16 | case radial
17 | }
18 |
19 | /// There is no need to create a new output texture, just use the input texture.
20 | public var needCreateDestTexture: Bool = false
21 |
22 | public var modifier: Modifier {
23 | return .compute(kernel: type.kernel)
24 | }
25 |
26 | let type: GradientType
27 |
28 | public init(with type: GradientType) {
29 | self.type = type
30 | }
31 | }
32 |
33 | extension C7ColorGradient.GradientType {
34 | public var kernel: String {
35 | switch self {
36 | case .rgUV:
37 | return "C7RGUVGradient"
38 | case .rgUVB1:
39 | return "C7RGUVB1Gradient"
40 | case .radial:
41 | return "C7RadialGradient"
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/Compute/Generator/C7SolidColor.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7SolidColor.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/10/10.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | // Bytes are being bound at index 0 to a shader argument with write access enabled.'
12 | // If use `device` and then throw the error as above.
13 | // See: https://developer.apple.com/forums/thread/658233
14 |
15 | kernel void C7SolidColor(texture2d outputTexture [[texture(0)]],
16 | texture2d inputTexture [[texture(1)]],
17 | constant float4 *colorVector [[buffer(0)]],
18 | uint2 grid [[thread_position_in_grid]]) {
19 | const half4 outColor = half4(*colorVector);
20 |
21 | outputTexture.write(outColor, grid);
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/Compute/Generator/C7SolidColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7SolidColor.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/10/10.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 纯色滤镜
11 | public struct C7SolidColor: C7FilterProtocol {
12 |
13 | /// There is no need to create a new output texture, just use the input texture.
14 | public var needCreateDestTexture: Bool = false
15 |
16 | public var color: C7Color = .white
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7SolidColor")
20 | }
21 |
22 | public func setupSpecialFactors(for encoder: MTLCommandEncoder, index: Int) {
23 | guard let computeEncoder = encoder as? MTLComputeCommandEncoder else { return }
24 | var factor = Vector4.init(color: color).to_factor()
25 | computeEncoder.setBytes(&factor, length: Vector4.size, index: index + 1)
26 | }
27 |
28 | public init(color: C7Color = .white) {
29 | self.color = color
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Compute/Lookup/C7LookupTable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7LookupTable.swift
3 | // MetalQueenDemo
4 | //
5 | // Created by Condy on 2021/8/9.
6 | //
7 |
8 | import Foundation
9 | import MetalKit
10 |
11 | /// LUT映射滤镜
12 | /// See: https://juejin.cn/post/7169096223100829709
13 | public struct C7LookupTable: C7FilterProtocol {
14 |
15 | /// Intensity range, used to adjust the mixing ratio of filters and sources.
16 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7LookupTable")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [intensity]
24 | }
25 |
26 | public var otherInputTextures: C7InputTextures {
27 | return lookupTexture == nil ? [] : [lookupTexture!]
28 | }
29 |
30 | private let lookupImage: C7Image?
31 | private let lookupTexture: MTLTexture?
32 |
33 | public init(image: C7Image?) {
34 | self.lookupImage = image
35 | self.lookupTexture = image?.cgImage?.c7.toTexture()
36 | }
37 |
38 | public init(name: String) {
39 | self.init(image: R.image(name))
40 | }
41 |
42 | public init(lookupTexture: MTLTexture) {
43 | self.lookupImage = nil
44 | self.lookupTexture = lookupTexture
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/Compute/Matrix/C7ColorMatrix4x4.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorMatrix4x4.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/21.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 4x4 color matrix.
11 | public struct C7ColorMatrix4x4: C7FilterProtocol {
12 |
13 | /// The degree to which the new transformed color replaces the original color for each pixel, default 1
14 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
15 | /// Color offset for each channel.
16 | public var offset: Vector4 = .zero
17 | public var matrix: Matrix4x4
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7ColorMatrix4x4")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [intensity] + offset.values
25 | }
26 |
27 | public func setupSpecialFactors(for encoder: MTLCommandEncoder, index: Int) {
28 | guard let computeEncoder = encoder as? MTLComputeCommandEncoder else { return }
29 | var factor = matrix.to_factor()
30 | computeEncoder.setBytes(&factor, length: Matrix4x4.size, index: index + 1)
31 | }
32 |
33 | public init(matrix: Matrix4x4) {
34 | self.matrix = matrix
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/Compute/Matrix/C7ColorMatrix4x5.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorMatrix4x5.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/11.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 4 x 5 color matrix.
11 | public struct C7ColorMatrix4x5: C7FilterProtocol {
12 |
13 | /// The degree to which the new transformed color replaces the original color for each pixel, default 1
14 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
15 |
16 | public var matrix: Matrix4x5
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7ColorMatrix4x5")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [intensity]
24 | }
25 |
26 | public func setupSpecialFactors(for encoder: MTLCommandEncoder, index: Int) {
27 | guard let computeEncoder = encoder as? MTLComputeCommandEncoder else { return }
28 | var factor = matrix.matrix4x4.to_factor()
29 | computeEncoder.setBytes(&factor, length: Matrix4x4.size, index: index + 1)
30 | var factor2 = matrix.vector4.to_factor()
31 | computeEncoder.setBytes(&factor2, length: Vector4.size, index: index + 2)
32 | }
33 |
34 | public init(matrix: Matrix4x5) {
35 | self.matrix = matrix
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/Compute/Matrix/C7ColorVector4.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorVector4.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/11.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7ColorVector4(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *intensity [[buffer(0)]],
14 | constant float4 *vector [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 |
18 | const half4 outColor = inColor + half4(*vector);
19 | const half4 output = mix(inColor, outColor, half(*intensity));
20 |
21 | outputTexture.write(output, grid);
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/Compute/Matrix/C7ColorVector4.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorVector4.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/11.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 四维向量颜色
11 | public struct C7ColorVector4: C7FilterProtocol {
12 |
13 | /// The degree to which the new transformed color replaces the original color for each pixel, default 1
14 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
15 |
16 | public var vector: Vector4
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7ColorVector4")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [intensity]
24 | }
25 |
26 | public func setupSpecialFactors(for encoder: MTLCommandEncoder, index: Int) {
27 | guard let computeEncoder = encoder as? MTLComputeCommandEncoder else { return }
28 | var factor = vector.to_factor()
29 | computeEncoder.setBytes(&factor, length: Vector4.size, index: index + 1)
30 | }
31 |
32 | public init(vector: Vector4) {
33 | self.vector = vector
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/Compute/Matrix/C7EdgeGlow.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7EdgeGlow.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/25.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7EdgeGlow: C7FilterProtocol {
11 |
12 | /// The adjusted time, from 0.0 to 1.0, with a default of 0.5
13 | public var time: Float = 0.5
14 | /// The edge span is larger than this. form 0.0 to 1.0
15 | public var spacing: Float = 0.5
16 |
17 | public var lineColor: C7Color = C7Color.green
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7EdgeGlow")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [time, spacing]
25 | }
26 |
27 | public func setupSpecialFactors(for encoder: MTLCommandEncoder, index: Int) {
28 | guard let computeEncoder = encoder as? MTLComputeCommandEncoder else { return }
29 | var factor = Vector4.init(color: lineColor).to_factor()
30 | computeEncoder.setBytes(&factor, length: Vector4.size, index: index + 1)
31 | }
32 |
33 | public init(time: Float = 0.5, spacing: Float = 0.5, lineColor: C7Color = .green) {
34 | self.time = time
35 | self.spacing = spacing
36 | self.lineColor = lineColor
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/Compute/Matrix/C7Nostalgic.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Nostalgic.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/3.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Nostalgic(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *intensity [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half4x4 matrix = half4x4({0.272, 0.534, 0.131, 0.0},
18 | {0.349, 0.686, 0.168, 0.0},
19 | {0.393, 0.769, 0.189, 0.0},
20 | {0.000, 0.000, 0.000, 1.0});
21 | const half4 outColor = half(*intensity) * (inColor * matrix) + (1.0h - half(*intensity)) * inColor;
22 |
23 | outputTexture.write(outColor, grid);
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Compute/Matrix/C7Nostalgic.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Nostalgic.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/3.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 怀旧滤镜
11 | public struct C7Nostalgic: C7FilterProtocol {
12 |
13 | /// Intensity range, used to adjust the mixing ratio of filters and sources.
14 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7Nostalgic")
18 | }
19 |
20 | public var factors: [Float] {
21 | return [intensity]
22 | }
23 |
24 | public init(intensity: Float = R.intensityRange.value) {
25 | self.intensity = intensity
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Matrix/C7Sepia.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Sepia.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/23.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Sepia(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *intensity [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half4x4 matrix = half4x4({0.3588, 0.7044, 0.1368, 0.0},
18 | {0.2990, 0.5870, 0.1140, 0.0},
19 | {0.2392, 0.4696, 0.0912, 0.0},
20 | {0.0000, 0.0000, 0.0000, 1.0});
21 | const half4 outColor = half(*intensity) * (inColor * matrix) + (1.0h - half(*intensity)) * inColor;
22 |
23 | outputTexture.write(outColor, grid);
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Compute/Matrix/C7Sepia.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Sepia.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/23.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 棕褐色,老照片
11 | public struct C7Sepia: C7FilterProtocol {
12 |
13 | /// The degree to which tan replaces normal image color, from 0.0 to 1.0
14 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7Sepia")
18 | }
19 |
20 | public var factors: [Float] {
21 | return [intensity]
22 | }
23 |
24 | public init(intensity: Float = R.intensityRange.value) {
25 | self.intensity = intensity
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Brightness.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Brightness.metal
3 | // MetalQueen
4 | //
5 | // Created by Condy on 2021/8/7.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Brightness(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *brightness [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half4 outColor = half4(inColor.rgb + half3(*brightness), inColor.a);
18 |
19 | outputTexture.write(outColor, grid);
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Brightness.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Brightness.swift
3 | // MetalQueen
4 | //
5 | // Created by Condy on 2021/8/7.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 亮度
11 | public struct C7Brightness: C7FilterProtocol {
12 |
13 | /// The adjusted brightness, from -1.0 to 1.0, with a default of 0.0 being the original picture.
14 | public static let range: ParameterRange = .init(min: -1.0, max: 1.0, value: 0.0)
15 |
16 | @Clamping(range.min...range.max) public var brightness: Float = range.value
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Brightness")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [brightness]
24 | }
25 |
26 | public init(brightness: Float = range.value) {
27 | self.brightness = brightness
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7ColorConvert.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorConvert.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2021/8/8.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 颜色通道`RGB`位置转换
11 | public struct C7ColorConvert: C7FilterProtocol {
12 |
13 | public enum ColorType: String, CaseIterable {
14 | case invert = "C7ColorInvert"
15 | case gray = "C7Color2Gray"
16 | case bgra = "C7Color2BGRA"
17 | case brga = "C7Color2BRGA"
18 | case gbra = "C7Color2GBRA"
19 | case grba = "C7Color2GRBA"
20 | case rbga = "C7Color2RBGA"
21 | case y = "C7Color2Y"
22 | }
23 |
24 | /// Intensity range, used to adjust the mixing ratio of filters and sources.
25 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
26 |
27 | private let type: ColorType
28 |
29 | public var modifier: Modifier {
30 | return .compute(kernel: type.rawValue)
31 | }
32 |
33 | public var factors: [Float] {
34 | return [intensity]
35 | }
36 |
37 | public init(with type: ColorType) {
38 | self.type = type
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7ColorRGBA.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorRGBA.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7ColorRGBA(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *intensity [[buffer(0)]],
14 | constant float4 *colorVector [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 |
18 | const half4 outColor(inColor * half4(*colorVector));
19 | const half4 output = mix(inColor, outColor, half(*intensity));
20 |
21 | outputTexture.write(output, grid);
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7ColorRGBA.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorRGBA.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7ColorRGBA: C7FilterProtocol {
11 |
12 | /// Intensity range, used to adjust the mixing ratio of filters and sources.
13 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
14 |
15 | /// Transparent colors are not processed, Will directly modify the overall color scheme
16 | public var color: C7Color = .white
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7ColorRGBA")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [intensity]
24 | }
25 |
26 | public func setupSpecialFactors(for encoder: MTLCommandEncoder, index: Int) {
27 | guard let computeEncoder = encoder as? MTLComputeCommandEncoder else { return }
28 | var factor = Vector4.init(color: color).to_factor()
29 | computeEncoder.setBytes(&factor, length: Vector4.size, index: index + 1)
30 | }
31 |
32 | public init(color: C7Color = .white) {
33 | self.color = color
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7ColorSpace.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ColorSpace.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/12/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 色彩空间转换
11 | public struct C7ColorSpace: C7FilterProtocol {
12 |
13 | public enum SwapType: String, CaseIterable {
14 | case rgb_to_yiq = "C7ColorSpaceRGB2YIQ"
15 | case yiq_to_rgb = "C7ColorSpaceYIQ2RGB"
16 | case rgb_to_yuv = "C7ColorSpaceRGB2YUV"
17 | case yuv_to_rgb = "C7ColorSpaceYUV2RGB"
18 | }
19 |
20 | private let type: SwapType
21 |
22 | public var modifier: Modifier {
23 | return .compute(kernel: type.rawValue)
24 | }
25 |
26 | public init(with type: SwapType) {
27 | self.type = type
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7ComicStrip.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7ComicStrip.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/3.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7ComicStrip(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *intensity [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 | const half r = inColor.r;
17 | const half g = inColor.g;
18 | const half b = inColor.b;
19 |
20 | const half R = half(abs(g - b + g + r) * r);
21 | const half G = half(abs(b - g + b + r) * r);
22 | const half B = half(abs(b - g + b + r) * g);
23 |
24 | const half4 outColor = half4(R, G, B, inColor.a);
25 | const half4 output = mix(inColor, outColor, half(*intensity));
26 |
27 | outputTexture.write(output, grid);
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7ComicStrip.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ComicStrip.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/3.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 连环画滤镜
11 | public struct C7ComicStrip: C7FilterProtocol {
12 |
13 | /// Intensity range, used to adjust the mixing ratio of filters and sources.
14 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7ComicStrip")
18 | }
19 |
20 | public var factors: [Float] {
21 | return [intensity]
22 | }
23 |
24 | public init() { }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Contrast.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Contrast.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Contrast(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *contrast [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half3 zero = half3(0.5h);
18 | const half4 outColor = half4((zero + (inColor.rgb - zero) * (*contrast)), inColor.a);
19 |
20 | outputTexture.write(outColor, grid);
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Contrast.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Contrast.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 对比度
11 | public struct C7Contrast: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0, max: 2.0, value: 1.0)
14 |
15 | /// The adjusted contrast, from 0 to 2.0, with a default of 1.0 being the original picture.
16 | public var contrast: Float = range.value
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Contrast")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [contrast]
24 | }
25 |
26 | public init(contrast: Float = range.value) {
27 | self.contrast = contrast
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Crosshatch.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Crosshatch.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 绘制阴影线
11 | public struct C7Crosshatch: C7FilterProtocol {
12 |
13 | /// The fractional width of the image to use as the spacing for the crosshatch, default of 0.03
14 | public var crosshatchSpacing: Float = 0.03
15 | /// A relative width for the crosshatch lines, default of 0.003
16 | public var lineWidth: Float = 0.003
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Crosshatch")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [crosshatchSpacing, lineWidth]
24 | }
25 |
26 | public init(crosshatchSpacing: Float = 0.03, lineWidth: Float = 0.003) {
27 | self.crosshatchSpacing = crosshatchSpacing
28 | self.lineWidth = lineWidth
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7DepthLuminance.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7DepthLuminance.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7DepthLuminance(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *offset [[buffer(0)]],
14 | constant float *range [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 textureCoordinate = inputTexture.read(grid);
17 |
18 | half depth = textureCoordinate.x;
19 | // Normalize the value between 0 and 1.
20 | depth = (depth - half(*offset)) / half(*range);
21 |
22 | const half4 outputColor = half4(half3(depth), 1.0h);
23 |
24 | outputTexture.write(outputColor, grid);
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7DepthLuminance.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7DepthLuminance.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7DepthLuminance: C7FilterProtocol {
11 |
12 | public var offect: Float = 0
13 | public var range: Float = 0
14 |
15 | public var modifier: Modifier {
16 | return .compute(kernel: "C7DepthLuminance")
17 | }
18 |
19 | public var factors: [Float] {
20 | return [offect, range]
21 | }
22 |
23 | public init(offect: Float = 0, range: Float = 0) {
24 | self.offect = offect
25 | self.range = range
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Exposure.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Exposure.metal
3 | // MetalQueenDemo
4 | //
5 | // Created by Condy on 2021/8/8.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Exposure(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *exposure [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half4 outColor = half4((inColor.rgb * pow(2.0, *exposure)), inColor.a);
18 |
19 | outputTexture.write(outColor, grid);
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Exposure.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Exposure.swift
3 | // MetalQueenDemo
4 | //
5 | // Created by Condy on 2021/8/8.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 曝光效果
11 | /// See: https://docs.unity3d.com/cn/Packages/com.unity.render-pipelines.high-definition@10.4/manual/Override-Exposure.html
12 | public struct C7Exposure: C7FilterProtocol {
13 |
14 | public static let range: ParameterRange = .init(min: -10.0, max: 10.0, value: 0.0)
15 |
16 | /// The adjusted exposure, from -10.0 to 10.0, with a default of 0.0
17 | public var exposure: Float = range.value
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7Exposure")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [exposure]
25 | }
26 |
27 | public init(exposure: Float = range.value) {
28 | self.exposure = exposure
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7FalseColor.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7FalseColor.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/16.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7FalseColor(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float3 *firstVector [[buffer(0)]],
14 | constant float3 *secondVector [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 |
18 | const half3 luminanceWeighting = half3(0.2125, 0.7154, 0.0721);
19 | const half luminance = dot(inColor.rgb, luminanceWeighting);
20 | const half3 color1 = half3(*firstVector);
21 | const half3 color2 = half3(*secondVector);
22 | const half4 outColor = half4(mix(color1.rgb, color2.rgb, half3(luminance)), inColor.a);
23 |
24 | outputTexture.write(outColor, grid);
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7FalseColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7FalseColor.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/16.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 使用图像的亮度在两种用户指定的颜色之间进行混合
11 | /// Uses the luminance of the image to mix between two user-specified colors
12 | public struct C7FalseColor: C7FilterProtocol {
13 |
14 | /// The first and second colors specify what colors replace the dark and light areas of the image, respectively.
15 | public var fristColor: C7Color = .zero
16 |
17 | public var secondColor: C7Color = .zero
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7FalseColor")
21 | }
22 |
23 | public func setupSpecialFactors(for encoder: MTLCommandEncoder, index: Int) {
24 | guard let computeEncoder = encoder as? MTLComputeCommandEncoder else { return }
25 | var fristFactor = Vector3.init(color: fristColor).to_factor()
26 | computeEncoder.setBytes(&fristFactor, length: Vector3.size, index: index + 1)
27 | var secondFactor = Vector3(color: secondColor).to_factor()
28 | computeEncoder.setBytes(&secondFactor, length: Vector3.size, index: index + 2)
29 | }
30 |
31 | public init(fristColor: C7Color = .zero, secondColor: C7Color = .zero) {
32 | self.fristColor = fristColor
33 | self.secondColor = secondColor
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Gamma.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Gamma.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Gamma(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *gamma [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half4 outColor = half4(pow(inColor.rgb, half3(*gamma)), inColor.a);
18 |
19 | outputTexture.write(outColor, grid);
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Gamma.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Gamma.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 灰度系数
11 | public struct C7Gamma: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 3.0, value: 1.0)
14 |
15 | /// The adjusted gamma, from 0 to 3.0, with a default of 1.0
16 | public var gamma: Float = range.value
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Gamma")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [gamma]
24 | }
25 |
26 | public init(gamma: Float = range.value) {
27 | self.gamma = gamma
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Granularity.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Granularity.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/21.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Granularity(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *grain [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 | const float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
17 |
18 | const float d = dot(textureCoordinate, float2(12.9898, 78.233) * 2.0);
19 | const half noise = half(fract(sin(d) * 43758.5453h));
20 | const half4 outColor = half4(inColor - noise * (*grain));
21 |
22 | outputTexture.write(outColor, grid);
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Granularity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Granularity.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/21.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 调节胶片颗粒感
11 | public struct C7Granularity: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 0.5, value: 0.3)
14 |
15 | /// The grain size is adjusted by adjusting the grain parameter. The grain size ranges from 0.0 to 0.5,
16 | /// Where 0.0 represents the original image,
17 | public var grain: Float = range.value
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7Granularity")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [grain]
25 | }
26 |
27 | public init(grain: Float = range.value) {
28 | self.grain = grain
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Haze.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Haze.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Haze(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *hazeDistance [[buffer(0)]],
14 | constant float *slope [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 |
18 | const half4 white = half4(1.0h);
19 | const half dd = half(grid.y) / half(inputTexture.get_height()) * half(*slope) + half(*hazeDistance);
20 | const half4 outColor = half4((inColor - dd * white) / (1.0h - dd));
21 |
22 | outputTexture.write(outColor, grid);
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Haze.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Haze.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 去雾,类似于UV过滤器
11 | public struct C7Haze: C7FilterProtocol {
12 |
13 | /// Strength of the color applied.
14 | public var distance: Float = 0
15 | /// Amount of color change.
16 | public var slope: Float = 0
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Haze")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [distance, slope]
24 | }
25 |
26 | public init(distance: Float = 0, slope: Float = 0) {
27 | self.distance = distance
28 | self.slope = slope
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7HighlightShadow.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7HighlightShadow.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7HighlightShadow(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *shadows [[buffer(0)]],
14 | constant float *highlights [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 |
18 | const half3 luminanceWeighting = half3(0.2125, 0.7154, 0.0721);
19 | const half luminance = dot(inColor.rgb, luminanceWeighting);
20 | const half shadow = clamp((pow(luminance, 1.0h / (half(*shadows) + 1.0h)) + (-0.76) * pow(luminance, 2.0h / (half(*shadows) + 1.0h))) - luminance, 0.0, 1.0);
21 | const half highlight = clamp((1.0 - (pow(1.0 - luminance, 1.0 / (2.0 - half(*highlights))) + (-0.8) * pow(1.0 - luminance, 2.0 / (2.0 - half(*highlights))))) - luminance, -1.0, 0.0);
22 | const half3 result = half3(0.0, 0.0, 0.0) + ((luminance + shadow + highlight) - 0.0) * ((inColor.rgb - half3(0.0, 0.0, 0.0)) / (luminance - 0.0));
23 | const half4 outColor = half4(result.rgb, inColor.a);
24 |
25 | outputTexture.write(outColor, grid);
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7HighlightShadow.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7HighlightShadow.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 高光阴影
11 | public struct C7HighlightShadow: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 0.0)
14 |
15 | /// Increase to lighten shadows, from 0.0 to 1.0, with 0.0 as the default.
16 | @ZeroOneRange public var shadows: Float = range.value
17 |
18 | /// Decrease to darken highlights, from 1.0 to 0.0, with 1.0 as the default.
19 | @ZeroOneRange public var highlights: Float = range.value
20 |
21 | public var modifier: Modifier {
22 | return .compute(kernel: "C7HighlightShadow")
23 | }
24 |
25 | public var factors: [Float] {
26 | return [shadows, highlights]
27 | }
28 |
29 | public init(highlights: Float = range.value, shadows: Float = range.value) {
30 | self.highlights = highlights
31 | self.shadows = shadows
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Hue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Hue.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/13.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Hue: C7FilterProtocol {
11 |
12 | /// Hue adjustment, unit is degree
13 | @DegreeRange public var hue: Float = 90.0
14 |
15 | public var modifier: Modifier {
16 | return .compute(kernel: "C7Hue")
17 | }
18 |
19 | public var factors: [Float] {
20 | return [Degree(value: hue).radians]
21 | }
22 |
23 | public init(hue: Float = 90.0) {
24 | self.hue = hue
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Luminance.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Luminance.metal
3 | // MetalQueenDemo
4 | //
5 | // Created by Condy on 2021/8/8.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Luminance(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *luminance [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half3 luminanceWeighting = half3(0.2125, 0.7154, 0.0721); // 亮度常量
18 | const half _luminance = dot(inColor.rgb, luminanceWeighting);
19 | const half4 outColor = half4(mix(half3(_luminance), inColor.rgb, half3(*luminance)), inColor.a);
20 |
21 | outputTexture.write(outColor, grid);
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Luminance.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Luminance.swift
3 | // MetalQueenDemo
4 | //
5 | // Created by Condy on 2021/8/8.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 亮度
11 | public struct C7Luminance: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 1.0)
14 |
15 | @ZeroOneRange public var luminance: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .compute(kernel: "C7Luminance")
19 | }
20 |
21 | public var factors: [Float] {
22 | return [luminance]
23 | }
24 |
25 | public init(luminance: Float = range.value) {
26 | self.luminance = luminance
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7LuminanceRangeReduction.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7LuminanceRangeReduction.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/23.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7LuminanceRangeReduction(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *rangeReductionFactor [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half3 luminanceWeighting = half3(0.2125, 0.7154, 0.0721); // 亮度常量
18 | const half _luminance = dot(inColor.rgb, luminanceWeighting);
19 | half luminanceRatio = ((0.5h - _luminance) * half(*rangeReductionFactor));
20 | const half4 outColor = half4(half3((inColor.rgb) + (luminanceRatio)), inColor.w);
21 |
22 | outputTexture.write(outColor, grid);
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7LuminanceRangeReduction.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7LuminanceRangeReduction.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/23.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7LuminanceRangeReduction: C7FilterProtocol {
11 |
12 | public var rangeReductionFactor: Float = 0.6
13 |
14 | public var modifier: Modifier {
15 | return .compute(kernel: "C7LuminanceRangeReduction")
16 | }
17 |
18 | public var factors: [Float] {
19 | return [rangeReductionFactor]
20 | }
21 |
22 | public init(rangeReductionFactor: Float = 0.6) {
23 | self.rangeReductionFactor = rangeReductionFactor
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7LuminanceThreshold.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7LuminanceThreshold.metal
3 | // MetalQueenDemo
4 | //
5 | // Created by Condy on 2021/8/8.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | // 阈值滤镜 阈值的大小是动态(根据图片情况)
12 | kernel void C7LuminanceThreshold(texture2d outputTexture [[texture(0)]],
13 | texture2d inputTexture [[texture(1)]],
14 | constant float *threshold [[buffer(0)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const half4 inColor = inputTexture.read(grid);
17 |
18 | const half3 luminanceWeighting = half3(0.2125, 0.7154, 0.0721); // 亮度常量
19 | const half luminance = dot(inColor.rgb, luminanceWeighting);
20 |
21 | // step luminance >= half(*threshold) 的值为1,小于则为0
22 | half thresholdResult = step(half(*threshold), luminance);
23 | const half4 outColor = half4(half3(thresholdResult), inColor.w);
24 |
25 | outputTexture.write(outColor, grid);
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7LuminanceThreshold.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7LuminanceThreshold.swift
3 | // MetalQueenDemo
4 | //
5 | // Created by Condy on 2021/8/8.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 阈值滤镜 阈值的大小是动态(根据图片情况)
11 | /// Threshold filter threshold size is dynamic (according to the image)
12 | public struct C7LuminanceThreshold: C7FilterProtocol {
13 |
14 | public var threshold: Float = 0.5
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7LuminanceThreshold")
18 | }
19 |
20 | public var factors: [Float] {
21 | return [threshold]
22 | }
23 |
24 | public init(threshold: Float = 0.5) {
25 | self.threshold = threshold
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Monochrome.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Monochrome.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 将图像转换为单色版本,根据每个像素的亮度进行着色
11 | public struct C7Monochrome: C7FilterProtocol {
12 |
13 | /// The degree to which the specific color replaces the normal image color
14 | @ZeroOneRange public var intensity: Float = R.intensityRange.value
15 |
16 | /// Keep the color scheme
17 | public var color: C7Color = .zero
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7Monochrome")
21 | }
22 |
23 | public var factors: [Float] {
24 | let rgb = color.c7.toRGBA()
25 | return [intensity] + [rgb.red, rgb.green, rgb.blue]
26 | }
27 |
28 | public init(intensity: Float = R.intensityRange.value, color: C7Color = .zero) {
29 | self.intensity = intensity
30 | self.color = color
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Opacity.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Opacity.metal
3 | // MetalQueenDemo
4 | //
5 | // Created by Condy on 2021/8/8.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Opacity(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *opacity [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half4 outColor = half4(inColor.rgb, half(*opacity) * inColor.a);
18 |
19 | outputTexture.write(outColor, grid);
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Opacity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Opacity.swift
3 | // MetalQueenDemo
4 | //
5 | // Created by Condy on 2021/8/8.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 透明度调整,核心就是改变`alpha`
11 | public struct C7Opacity: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 1.0)
14 |
15 | /// Change the opacity of an image, from 0.0 to 1.0, with a default of 1.0
16 | @ZeroOneRange public var opacity: Float = range.value
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Opacity")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [opacity]
24 | }
25 |
26 | public init(opacity: Float = range.value) {
27 | self.opacity = opacity
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Posterize.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Posterize.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Posterize(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *colorLevelsPointer [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half colorLevels = half(*colorLevelsPointer);
18 | const half4 outColor = floor((inColor * colorLevels) + half4(0.5h)) / colorLevels;
19 |
20 | outputTexture.write(outColor, grid);
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Posterize.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Posterize.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 海报化效果滤镜
11 | public struct C7Posterize: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 1.0, max: 255.0, value: 10.0)
14 |
15 | /// The number of color levels to reduce the image space to.
16 | /// This ranges from 1 to 256, with a default of 10
17 | @Clamping(range.min...range.max) public var colorLevels: Float = range.value
18 |
19 | public var modifier: Modifier {
20 | return .compute(kernel: "C7Posterize")
21 | }
22 |
23 | public var factors: [Float] {
24 | return [colorLevels]
25 | }
26 |
27 | public init(colorLevels: Float = range.value) {
28 | self.colorLevels = colorLevels
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Pow.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Pow.metal
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/7/28.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Pow(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *value [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half4 outColor = half4(pow(inColor.rgb, (*value)), 1.0);
18 |
19 | outputTexture.write(outColor, grid);
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Pow.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Pow.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/7/28.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Pow: C7FilterProtocol {
11 |
12 | public var value: Float = 0.2
13 |
14 | public var modifier: Modifier {
15 | return .compute(kernel: "C7Pow")
16 | }
17 |
18 | public var factors: [Float] {
19 | return [value]
20 | }
21 |
22 | public init(value: Float = 0.2) {
23 | self.value = value
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Saturation.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Saturation.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Saturation(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *saturation [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half3 luminanceWeighting = half3(0.2125, 0.7154, 0.0721);
18 | const half luminance = dot(inColor.rgb, luminanceWeighting);
19 | const half4 outColor = half4(mix(half3(luminance), inColor.rgb, half(*saturation)), inColor.a);
20 |
21 | outputTexture.write(outColor, grid);
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Saturation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Saturation.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 饱和度
11 | public struct C7Saturation: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 2.0, value: 1.0)
14 |
15 | /// Saturation refers to the brightness of the colors of images, which is adjusted by adjusting saturation.
16 | /// Saturation ranges from 0.0 to 2.0, in which 1.0 refers to the original figure.
17 | /// The greater the saturation is, the brighter the colors are. Otherwise, the more monotonous the colors are.
18 | public var saturation: Float = range.value
19 |
20 | public var modifier: Modifier {
21 | return .compute(kernel: "C7Saturation")
22 | }
23 |
24 | public var factors: [Float] {
25 | return [saturation]
26 | }
27 |
28 | public init(saturation: Float = range.value) {
29 | self.saturation = saturation
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7ShiftGlitch.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7ShiftGlitch.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/2/25.
6 | //
7 |
8 | import Foundation
9 |
10 | /// RGB Shift Glitch
11 | public struct C7ShiftGlitch: C7FilterProtocol {
12 |
13 | /// The adjusted time, from 0.0 to 1.0, with a default of 0.5
14 | public var time: Float = 0.5
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7ShiftGlitch")
18 | }
19 |
20 | public var factors: [Float] {
21 | return [time]
22 | }
23 |
24 | public init(time: Float = 0.5) {
25 | self.time = time
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Sobel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Sobel.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/16.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 特征提取,基于Sobel算子
11 | /// Feature extraction, based on Sobel operator
12 | public struct C7Sobel: C7FilterProtocol {
13 |
14 | /// Adjusts the dynamic range of the filter. default is 1.0
15 | /// Higher values lead to stronger edges, but can saturate the intensity colorspace.
16 | public var edgeStrength: Float = 1.0
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Sobel")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [edgeStrength]
24 | }
25 |
26 | public init(edgeStrength: Float = 1.0) {
27 | self.edgeStrength = edgeStrength
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Vibrance.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Vibrance.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Vibrance(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *vibrance [[buffer(0)]],
14 | uint2 grid [[thread_position_in_grid]]) {
15 | const half4 inColor = inputTexture.read(grid);
16 |
17 | const half average = (inColor.r + inColor.g + inColor.b) / 3.0h;
18 | const half mx = max(inColor.r, max(inColor.g, inColor.b));
19 | const half amt = (mx - average) * (-half(*vibrance) * 3.0h);
20 | const half4 outColor = half4(mix(inColor.rgb, half3(mx), amt), inColor.a);
21 |
22 | outputTexture.write(outColor, grid);
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Vibrance.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Vibrance.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 自然饱和度
11 | public struct C7Vibrance: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: -1.2, max: 1.2, value: 0.0)
14 |
15 | /// Change the vibrance of an image, from -1.2 to 1.2, with a default of 0.0
16 | public var vibrance: Float = range.value
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7Vibrance")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [vibrance]
24 | }
25 |
26 | public init(vibrance: Float = range.value) {
27 | self.vibrance = vibrance
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Vignette.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Vignette.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Vignette(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *centerX [[buffer(0)]],
14 | constant float *centerY [[buffer(1)]],
15 | constant float *start [[buffer(2)]],
16 | constant float *end [[buffer(3)]],
17 | constant float3 *colorVector [[buffer(4)]],
18 | uint2 grid [[thread_position_in_grid]]) {
19 | const half4 inColor = inputTexture.read(grid);
20 | const float2 textureCoordinate = float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height());
21 |
22 | const half2 center = half2(*centerX, *centerY);
23 | const float dd = distance(textureCoordinate, float2(center));
24 | const half percent = smoothstep(*start, *end, dd);
25 | const half4 outColor = half4(mix(inColor.rgb, half3(*colorVector), percent), inColor.a);
26 |
27 | outputTexture.write(outColor, grid);
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7Vignette.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Vignette.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/14.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 渐晕效果,使边缘的图像淡化
11 | public struct C7Vignette: C7FilterProtocol {
12 |
13 | /// The normalized distance from the center where the vignette effect starts, with a default of 0.3
14 | public var start: Float = 0.3
15 | /// The normalized distance from the center where the vignette effect ends, with a default of 0.75
16 | public var end: Float = 0.75
17 | public var center: C7Point2D = C7Point2D.center
18 | /// Keep the color scheme
19 | public var color: C7Color = .zero
20 |
21 | public var modifier: Modifier {
22 | return .compute(kernel: "C7Vignette")
23 | }
24 |
25 | public var factors: [Float] {
26 | return [center.x, center.y, start, end]
27 | }
28 |
29 | public func setupSpecialFactors(for encoder: MTLCommandEncoder, index: Int) {
30 | guard let computeEncoder = encoder as? MTLComputeCommandEncoder else { return }
31 | var factor = Vector3.init(color: color).to_factor()
32 | computeEncoder.setBytes(&factor, length: Vector3.size, index: index + 1)
33 | }
34 |
35 | public init(start: Float = 0.3, end: Float = 0.75, color: C7Color = .zero) {
36 | self.start = start
37 | self.end = end
38 | self.color = color
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7VoronoiOverlay.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7VoronoiOverlay.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/3/1.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 泰森多边形法叠加效果
11 | /// 改变`Voronoi`模式中的距离度量以获得不同的形状
12 | public struct C7VoronoiOverlay: C7FilterProtocol {
13 |
14 | public var time: Float = 0.5
15 | public var alpha: Float = 0.05
16 | public var iResolution: C7Point2D = C7Point2D.center
17 |
18 | public var modifier: Modifier {
19 | return .compute(kernel: "C7VoronoiOverlay")
20 | }
21 |
22 | public var factors: [Float] {
23 | return [time, alpha, iResolution.x, iResolution.y]
24 | }
25 |
26 | public init(time: Float = 0.5, alpha: Float = 0.05) {
27 | self.time = time
28 | self.alpha = alpha
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Compute/Pixel/C7WhiteBalance.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7WhiteBalance.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 基于色温调整白平衡
11 | public struct C7WhiteBalance: C7FilterProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 4000, max: 7000, value: 5000)
14 |
15 | /// The tint to adjust the image by. A value of -200 is very green and 200 is very pink.
16 | @Clamping(-200...200) public var tint: Float = 0
17 | /// The temperature to adjust the image by, in ºK. A value of 4000 is very cool and 7000 very warm.
18 | /// Note that the scale between 4000 and 5000 is nearly as visually significant as that between 5000 and 7000.
19 | @Clamping(range.min...range.max) public var temperature: Float = range.value
20 |
21 | public var modifier: Modifier {
22 | return .compute(kernel: "C7WhiteBalance")
23 | }
24 |
25 | public var factors: [Float] {
26 | return [temperature, tint]
27 | }
28 |
29 | public init(temperature: Float = range.value, tint: Float = 0) {
30 | self.temperature = temperature
31 | self.tint = tint
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Compute/Shape/C7Crop.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Crop.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Crop(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *originX [[buffer(0)]],
14 | constant float *originY [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
17 |
18 | const float minX = inputTexture.get_width() * (*originX);
19 | const float minY = inputTexture.get_height() * (*originY);
20 | const half4 outColor = inputTexture.sample(quadSampler, float2((grid.x + minX) / inputTexture.get_width(), (grid.y + minY) / inputTexture.get_height()));
21 |
22 | outputTexture.write(outColor, grid);
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Compute/Shape/C7Flip.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Flip.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Flip(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | constant float *horizontal [[buffer(0)]],
14 | constant float *vertical [[buffer(1)]],
15 | uint2 grid [[thread_position_in_grid]]) {
16 | const uint x = (*horizontal) ? inputTexture.get_width() - 1 - grid.x : grid.x;
17 | const uint y = (*vertical) ? inputTexture.get_height() - 1 - grid.y : grid.y;
18 | // Read the pixels that have been transformed from coordinates
19 | const half4 outColor = inputTexture.read(uint2(x, y));
20 |
21 | outputTexture.write(outColor, grid);
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/Compute/Shape/C7Flip.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Flip.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Flip: C7FilterProtocol {
11 |
12 | /// Whether to flip horizontally or not
13 | public var horizontal: Bool = false
14 | /// Whether to flip vertically or not
15 | public var vertical: Bool = false
16 |
17 | public var modifier: Modifier {
18 | return .compute(kernel: "C7Flip")
19 | }
20 |
21 | public var factors: [Float] {
22 | return [horizontal ? 1.0 : 0.0, vertical ? 1.0 : 0.0]
23 | }
24 |
25 | public init(horizontal: Bool = false, vertical: Bool = false) {
26 | self.horizontal = horizontal
27 | self.vertical = vertical
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Compute/Shape/C7Resize.metal:
--------------------------------------------------------------------------------
1 | //
2 | // C7Resize.metal
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | #include
9 | using namespace metal;
10 |
11 | kernel void C7Resize(texture2d outputTexture [[texture(0)]],
12 | texture2d inputTexture [[texture(1)]],
13 | uint2 grid [[thread_position_in_grid]]) {
14 | constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
15 |
16 | const half4 outColor = inputTexture.sample(quadSampler, float2(float(grid.x) / outputTexture.get_width(), float(grid.y) / outputTexture.get_height()));
17 |
18 | outputTexture.write(outColor, grid);
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/Compute/Shape/C7Resize.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Resize.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Pull and compress the picture, the picture will be distorted
11 | public struct C7Resize: C7FilterProtocol {
12 |
13 | public var width: Float
14 | public var height: Float
15 |
16 | public var modifier: Modifier {
17 | return .compute(kernel: "C7Resize")
18 | }
19 |
20 | public func resize(input size: C7Size) -> C7Size {
21 | return Placement.fit.resize(width: width, height: height, size: size)
22 | }
23 |
24 | public init(size: CGSize) {
25 | self.width = Float(size.width)
26 | self.height = Float(size.height)
27 | }
28 |
29 | public init(width: Float, height: Float) {
30 | self.width = width
31 | self.height = height
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Compute/Shape/C7Rotate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // C7Rotate.swift
3 | // ATMetalBand
4 | //
5 | // Created by Condy on 2022/2/15.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct C7Rotate: C7FilterProtocol {
11 |
12 | /// Angle to rotate, unit is degree
13 | @DegreeRange public var angle: Float
14 |
15 | public var modifier: Modifier {
16 | return .compute(kernel: "C7Rotate")
17 | }
18 |
19 | public var factors: [Float] {
20 | return [Degree(value: angle).radians]
21 | }
22 |
23 | public func resize(input size: C7Size) -> C7Size {
24 | return mode.rotate(angle: Degree(value: angle).radians, size: size)
25 | }
26 |
27 | private var mode: Placement = .fit
28 |
29 | public init(mode: Placement = .fit, angle: Float = 0) {
30 | self.angle = angle
31 | self.mode = mode
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIBrightness.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIBrightness.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CIBrightness: CoreImageProtocol {
12 |
13 | /// The adjusted brightness, from -1.0 to 1.0, with a default of 0.0 being the original picture.
14 | public static let range: ParameterRange = .init(min: -1.0, max: 1.0, value: 0.0)
15 |
16 | @Clamping(range.min...range.max) public var brightness: Float = range.value
17 |
18 | public var modifier: Modifier {
19 | return .coreimage(CIName: "CIColorControls")
20 | }
21 |
22 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
23 | filter.setValue(brightness, forKey: kCIInputBrightnessKey)
24 | return ciImage
25 | }
26 |
27 | public init(brightness: Float = range.value) {
28 | self.brightness = brightness
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIColorControls.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIColorControls.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | /// 调整亮度、饱和度和对比度
12 | public struct CIColorControls: CoreImageProtocol {
13 |
14 | /// The adjusted brightness, from -1.0 to 1.0, with a default of 0.0.
15 | @Clamping(CIBrightness.range.min...CIBrightness.range.max) public var brightness: Float = CIBrightness.range.value
16 |
17 | /// The adjusted saturation, from -1.0 to 1.0, with a default of 0.0.
18 | @Clamping(CISaturation.range.min...CISaturation.range.max) public var saturation: Float = CISaturation.range.value
19 |
20 | /// The adjusted contrast, from -0.18 to 0.18, with a default of 0.0.
21 | @Clamping(CIContrast.range.min...CIContrast.range.max) public var contrast: Float = CIContrast.range.value
22 |
23 | public var modifier: Modifier {
24 | return .coreimage(CIName: "CIColorControls")
25 | }
26 |
27 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
28 | filter.setValue(brightness, forKey: kCIInputBrightnessKey)
29 | filter.setValue(saturation + 1, forKey: kCIInputSaturationKey)
30 | filter.setValue(contrast + 1, forKey: kCIInputContrastKey)
31 | return ciImage
32 | }
33 |
34 | public init() { }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIColorMonochrome.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIColorMonochrome.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2024/3/3.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | /// 单色滤镜
12 | public struct CIColorMonochrome: CoreImageProtocol {
13 |
14 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 1.0)
15 |
16 | @Clamping(range.min...range.max) public var intensity: Float = range.value
17 |
18 | /// A color to use as the white point.
19 | public var color: C7Color = .white {
20 | didSet {
21 | self.ciColor = CIColor.init(color: color)
22 | }
23 | }
24 |
25 | public var modifier: Modifier {
26 | return .coreimage(CIName: "CIColorMonochrome")
27 | }
28 |
29 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
30 | filter.setValue(intensity, forKey: kCIInputIntensityKey)
31 | filter.setValue(ciColor, forKey: kCIInputColorKey)
32 | return ciImage
33 | }
34 |
35 | private var ciColor: CIColor!
36 |
37 | public init(color: C7Color = .white) {
38 | self.color = color
39 | self.ciColor = CIColor.init(color: color)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIContrast.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIContrast.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CIContrast: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: -1.0, max: 1.0, value: 0.0)
14 |
15 | @Clamping(range.min...range.max) public var contrast: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .coreimage(CIName: "CIColorControls")
19 | }
20 |
21 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
22 | filter.setValue(contrast + 1, forKey: kCIInputContrastKey)
23 | return ciImage
24 | }
25 |
26 | public init(contrast: Float = range.value) {
27 | self.contrast = contrast
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIExposure.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIExposure.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CIExposure: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: -1.8, max: 1.8, value: 0.0)
14 |
15 | @Clamping(range.min...range.max) public var exposure: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .coreimage(CIName: "CIExposureAdjust")
19 | }
20 |
21 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
22 | filter.setValue(exposure, forKey: kCIInputEVKey)
23 | return ciImage
24 | }
25 |
26 | public init(exposure: Float = range.value) {
27 | self.exposure = exposure
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIFade.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIFade.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CIFade: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 0.0)
14 |
15 | @Clamping(range.min...range.max) public var intensity: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .coreimage(CIName: "CISourceOverCompositing")
19 | }
20 |
21 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
22 | let mFilter = CIFilter(name: "CIConstantColorGenerator", parameters: [
23 | kCIInputColorKey : CIColor(red: 1, green: 1, blue: 1, alpha: CGFloat(intensity))
24 | ])
25 | guard let foreground = mFilter?.outputImage else {
26 | throw HarbethError.outputCIImage("CIConstantColorGenerator")
27 | }
28 | filter.setValue(ciImage, forKey: kCIInputBackgroundImageKey)
29 | return foreground
30 | }
31 |
32 | public init(intensity: Float = range.value) {
33 | self.intensity = intensity
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIGaussianBlur.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIGaussianBlur.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CIGaussianBlur: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0, max: 100, value: 10.0)
14 |
15 | @Clamping(range.min...range.max) public var radius: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .coreimage(CIName: "CIGaussianBlur")
19 | }
20 |
21 | public var croppedOutputImage: Bool {
22 | return true
23 | }
24 |
25 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
26 | let radius = ciImage.extent.c7.radius(radius, max: Self.range.max)
27 | filter.setValue(radius, forKey: kCIInputRadiusKey)
28 | // Return a new infinite image by replicating the edge pixels of a rectangle.
29 | // Cut the blurred area next to it.
30 | return ciImage.clamped(to: ciImage.extent)
31 | }
32 |
33 | public init(radius: Float = range.value) {
34 | self.radius = radius
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIHighlight.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIHighlight.swift
3 | // Harbeth
4 | //
5 | // Created by 77。 on 2022/7/13.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | /// 高光
12 | /// https://cifilter.io/CIHighlightShadowAdjust/
13 | public struct CIHighlight: CoreImageProtocol {
14 |
15 | public static let range: ParameterRange = .init(min: 0.0, max: 1.0, value: 0.0)
16 |
17 | @ZeroOneRange public var highlight: Float = range.value
18 |
19 | public var modifier: Modifier {
20 | return .coreimage(CIName: "CIHighlightShadowAdjust")
21 | }
22 |
23 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
24 | filter.setValue(1 - highlight, forKey: "inputHighlightAmount")
25 | return ciImage
26 | }
27 |
28 | public init(highlight: Float = range.value) {
29 | self.highlight = highlight
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CINoiseReduction.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CINoiseReduction.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2024/3/25.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CINoiseReduction: CoreImageProtocol {
12 |
13 | public var noiseLevel: Float = 0.02
14 |
15 | public var modifier: Modifier {
16 | return .coreimage(CIName: "CINoiseReduction")
17 | }
18 |
19 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
20 | filter.setValue(noiseLevel, forKey: "inputNoiseLevel")
21 | return ciImage
22 | }
23 |
24 | public init(noiseLevel: Float = 0.02) {
25 | self.noiseLevel = noiseLevel
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIResizedSmooth.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIResizedSmooth.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2024/4/8.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CIResizedSmooth: CIImageDisplaying {
12 |
13 | public var modifier: Modifier {
14 | return .coreimage(CIName: "CILanczosScaleTransform")
15 | }
16 |
17 | public var ciFilter: CIFilter?
18 |
19 | public var postProcessing: (CIImage) -> CIImage = { $0 }
20 |
21 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
22 | let scale = targetSize.height / ciImage.extent.height
23 | let aspectRatio = targetSize.width / (ciImage.extent.width) * scale
24 | filter.setValue(scale, forKey: kCIInputScaleKey)
25 | filter.setValue(aspectRatio, forKey: kCIInputAspectRatioKey)
26 | return ciImage
27 | }
28 |
29 | public var targetSize: CGSize
30 |
31 | public init(targetSize: CGSize) {
32 | self.targetSize = targetSize
33 | self.ciFilter = CIFilter(name: "CILanczosScaleTransform")
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CISaturation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CISaturation.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CISaturation: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: -1.0, max: 1.0, value: 0.0)
14 |
15 | @Clamping(range.min...range.max) public var saturation: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .coreimage(CIName: "CIColorControls")
19 | }
20 |
21 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
22 | filter.setValue(saturation + 1, forKey: kCIInputSaturationKey)
23 | return ciImage
24 | }
25 |
26 | public init(saturation: Float = range.value) {
27 | self.saturation = saturation
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIShadows.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIShadows.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CIShadows: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: -1, max: 1, value: 0.0)
14 |
15 | @Clamping(range.min...range.max) public var shadows: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .coreimage(CIName: "CIHighlightShadowAdjust")
19 | }
20 |
21 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
22 | filter.setValue(shadows, forKey: "inputShadowAmount")
23 | return ciImage
24 | }
25 |
26 | public init(shadows: Float = range.value) {
27 | self.shadows = shadows
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CISharpen.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CISharpen.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CISharpen: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0, max: 1.0, value: 0.0)
14 |
15 | @Clamping(range.min...range.max) public var sharpness: Float = range.value
16 |
17 | public var radius: Float = 0.0
18 |
19 | public var modifier: Modifier {
20 | return .coreimage(CIName: "CISharpenLuminance")
21 | }
22 |
23 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
24 | let radius = ciImage.extent.c7.radius(radius, max: Self.range.max)
25 | filter.setValue(radius, forKey: kCIInputRadiusKey)
26 | filter.setValue(sharpness, forKey: kCIInputSharpnessKey)
27 | return ciImage
28 | }
29 |
30 | public init(sharpness: Float = range.value, radius: Float = 0.0) {
31 | self.radius = radius
32 | self.sharpness = sharpness
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CITemperature.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CITemperature.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CITemperature: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: -3000, max: 3000, value: 0.0)
14 |
15 | @Clamping(range.min...range.max) public var temperature: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .coreimage(CIName: "CITemperatureAndTint")
19 | }
20 |
21 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
22 | filter.setValue(CIVector.init(x: CGFloat(temperature) + 6500, y: 0), forKey: "inputNeutral")
23 | filter.setValue(CIVector.init(x: 6500, y: 0), forKey: "inputTargetNeutral")
24 | return ciImage
25 | }
26 |
27 | public init(temperature: Float = range.value) {
28 | self.temperature = temperature
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIUnsharpMask.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIUnsharpMask.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CIUnsharpMask: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0, max: 0.3, value: 0.0)
14 |
15 | @Clamping(range.min...range.max) public var intensity: Float = range.value
16 |
17 | @ZeroOneRange public var radius: Float = 0.0
18 |
19 | public var modifier: Modifier {
20 | return .coreimage(CIName: "CIUnsharpMask")
21 | }
22 |
23 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
24 | let radius = ciImage.extent.c7.radius(radius, max: Self.range.max)
25 | filter.setValue(radius, forKey: kCIInputRadiusKey)
26 | filter.setValue(intensity, forKey: kCIInputIntensityKey)
27 | return ciImage
28 | }
29 |
30 | public init(intensity: Float = range.value, radius: Float = 0) {
31 | self.radius = radius
32 | self.intensity = intensity
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIVignette.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIVignette.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/8/6.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | public struct CIVignette: CoreImageProtocol {
12 |
13 | public static let range: ParameterRange = .init(min: 0, max: 2, value: 0.0)
14 |
15 | @Clamping(range.min...range.max) public var vignette: Float = range.value
16 |
17 | public var modifier: Modifier {
18 | return .coreimage(CIName: "CIVignette")
19 | }
20 |
21 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
22 | let radius = ciImage.extent.c7.radius(vignette, max: Self.range.max)
23 | filter.setValue(radius, forKey: kCIInputRadiusKey)
24 | filter.setValue(vignette, forKey: kCIInputIntensityKey)
25 | return ciImage
26 | }
27 |
28 | public init(vignette: Float = range.value) {
29 | self.vignette = vignette
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/CoreImage/CIWhitePoint.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIWhitePoint.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2022/11/24.
6 | //
7 |
8 | import Foundation
9 | import CoreImage
10 |
11 | /// Adjusts the reference white point for an image and maps all colors in the source using the new reference.
12 | /// https://cifilter.io/CIWhitePointAdjust/
13 | public struct CIWhitePoint: CoreImageProtocol {
14 |
15 | /// A color to use as the white point.
16 | public var color: C7Color = .white {
17 | didSet {
18 | self.ciColor = CIColor(color: color)
19 | }
20 | }
21 |
22 | public var modifier: Modifier {
23 | return .coreimage(CIName: "CIWhitePointAdjust")
24 | }
25 |
26 | public func coreImageApply(filter: CIFilter, input ciImage: CIImage) throws -> CIImage {
27 | filter.setValue(ciColor, forKey: kCIInputColorKey)
28 | return ciImage
29 | }
30 |
31 | private var ciColor: CIColor!
32 |
33 | public init(color: C7Color = .white) {
34 | self.color = color
35 | self.ciColor = CIColor(color: color)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/SwiftUI/Color+Ext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Color+Ext.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/12/1.
6 | //
7 |
8 | import Foundation
9 | import SwiftUI
10 |
11 | @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
12 | extension Color {
13 |
14 | /// Creates a color from an hex integer, e.g. 0xD6A5A4.
15 | /// - Parameter hex: A hexa-decimal UInt64 that represents a color.
16 | public init(hex: Int) {
17 | let mask = 0xFF
18 | let r = Double((hex >> 16) & mask) / 255
19 | let g = Double((hex >> 8) & mask) / 255
20 | let b = Double((hex) & mask) / 255
21 | self.init(red: r, green: g, blue: b, opacity: 1.0)
22 | }
23 |
24 | /// Creates a color from an hex string, e.g. "#D6A5A4".
25 | /// Support hex string `#RGB`,`RGB`,`#RGBA`,`RGBA`,`#RRGGBB`,`RRGGBB`,`#RRGGBBAA`,`RRGGBBAA`.
26 | /// - Parameter hex: A hexa-decimal color string representation.
27 | public init(hex: String) {
28 | let (r, g, b, a) = hex.c7.hex2RGBA()
29 | self.init(red: r, green: g, blue: b, opacity: a)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/SwiftUI/HarbethViewInput.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HarbethViewInput.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2025/1/1.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct HarbethViewInput {
11 |
12 | public let texture: MTLTexture?
13 | /// A filters add into a data source.
14 | public var filters: [C7FilterProtocol] = []
15 | /// Whether to use asynchronous processing, the UI will not be updated in real time.
16 | public var asynchronousProcessing: Bool = false
17 | /// Placeholder image, without source data.
18 | public var placeholder: C7Image?
19 |
20 | public init(texture: MTLTexture?) {
21 | self.texture = texture
22 | }
23 |
24 | public init(image: C7Image) {
25 | self.init(texture: image.c7.toTexture())
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/SwiftUI/Image+Ext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Image+Ext.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/7/27.
6 | //
7 |
8 | import Foundation
9 | import SwiftUI
10 |
11 | @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
12 | extension Image {
13 |
14 | public init(cgImage: CGImage) {
15 | self.init(c7Image: cgImage.c7.toC7Image())
16 | }
17 |
18 | public init(c7Image: C7Image) {
19 | #if os(iOS)
20 | self.init(uiImage: c7Image)
21 | #elseif os(macOS)
22 | self.init(nsImage: c7Image)
23 | #else
24 | #error("Unsupported Platform")
25 | #endif
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/SwiftUI/Published_Image.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Published_Image.swift
3 | // Harbeth
4 | //
5 | // Created by Condy on 2023/12/5.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
11 | public final class Published_Image: ObservableObject {
12 |
13 | @Published public var image: C7Image
14 |
15 | public init(_ image: C7Image) {
16 | self.image = image
17 | }
18 | }
19 |
20 | @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
21 | public final class Published_Source: ObservableObject {
22 |
23 | @Published public var source: T
24 |
25 | public init(_ source: T) {
26 | self.source = source
27 | }
28 | }
29 |
--------------------------------------------------------------------------------