├── .gitignore ├── Default-568h@2x.png ├── LICENSE ├── MetalImage.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ ├── fengshi.xcuserdatad │ └── UserInterfaceState.xcuserstate │ ├── fengstone.xcuserdatad │ └── UserInterfaceState.xcuserstate │ └── stonefeng.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── MetalImage ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── 1024x1024.png │ │ ├── 120x120-1.png │ │ ├── 120x120.png │ │ ├── 152x152.png │ │ ├── 167x167.png │ │ ├── 180x180.png │ │ ├── 20x20.png │ │ ├── 29x29.png │ │ ├── 40x40-1.png │ │ ├── 40x40-2.png │ │ ├── 40x40.png │ │ ├── 58x58-1.png │ │ ├── 58x58.png │ │ ├── 60x60.png │ │ ├── 76x76.png │ │ ├── 80x80-1.png │ │ ├── 80x80.png │ │ ├── 87x87.png │ │ └── Contents.json │ └── Contents.json ├── Info.plist ├── MetalImage.h ├── MetalImage │ ├── Blend │ │ ├── Blend.metal │ │ ├── MIAddBlendFilter.h │ │ ├── MIAddBlendFilter.m │ │ ├── MIAlphaBlendFilter.h │ │ ├── MIAlphaBlendFilter.m │ │ ├── MIChromaKeyBlendFilter.h │ │ ├── MIChromaKeyBlendFilter.m │ │ ├── MIColorBlendFilter.h │ │ ├── MIColorBlendFilter.m │ │ ├── MIColorBurnBlendFilter.h │ │ ├── MIColorBurnBlendFilter.m │ │ ├── MIColorDodgeBlendFilter.h │ │ ├── MIColorDodgeBlendFilter.m │ │ ├── MIDarkenBlendFilter.h │ │ ├── MIDarkenBlendFilter.m │ │ ├── MIDifferenceBlendFilter.h │ │ ├── MIDifferenceBlendFilter.m │ │ ├── MIDissolveBlendFilter.h │ │ ├── MIDissolveBlendFilter.m │ │ ├── MIDivideBlendFilter.h │ │ ├── MIDivideBlendFilter.m │ │ ├── MIExclusionBlendFilter.h │ │ ├── MIExclusionBlendFilter.m │ │ ├── MIHardLightBlendFilter.h │ │ ├── MIHardLightBlendFilter.m │ │ ├── MIHueBlendFilter.h │ │ ├── MIHueBlendFilter.m │ │ ├── MILightenBlendFilter.h │ │ ├── MILightenBlendFilter.m │ │ ├── MILinearBurnBlendFilter.h │ │ ├── MILinearBurnBlendFilter.m │ │ ├── MILuminosityBlendFilter.h │ │ ├── MILuminosityBlendFilter.m │ │ ├── MIMaskFilter.h │ │ ├── MIMaskFilter.m │ │ ├── MIMultiplyBlendFilter.h │ │ ├── MIMultiplyBlendFilter.m │ │ ├── MINormalBlendFilter.h │ │ ├── MINormalBlendFilter.m │ │ ├── MIOverlayBlendFilter.h │ │ ├── MIOverlayBlendFilter.m │ │ ├── MISaturationBlendFilter.h │ │ ├── MISaturationBlendFilter.m │ │ ├── MIScreenBlendFilter.h │ │ ├── MIScreenBlendFilter.m │ │ ├── MISoftLightBlendFilter.h │ │ ├── MISoftLightBlendFilter.m │ │ ├── MISourceOverBlendFilter.h │ │ ├── MISourceOverBlendFilter.m │ │ ├── MISubtractBlendFilter.h │ │ └── MISubtractBlendFilter.m │ ├── Color │ │ ├── MIAdaptiveLuminanceFilter.h │ │ ├── MIAdaptiveLuminanceFilter.m │ │ ├── MIAdaptiveLuminanceFilter.metal │ │ ├── MIAdaptiveThresholdFilter.h │ │ ├── MIAdaptiveThresholdFilter.m │ │ ├── MIAdaptiveThresholdFilter.metal │ │ ├── MIAverageLuminanceThresholdFilter.h │ │ ├── MIAverageLuminanceThresholdFilter.m │ │ ├── MIBrightnessFilter.h │ │ ├── MIBrightnessFilter.m │ │ ├── MIBrightnessFilter.metal │ │ ├── MIChromaKeyFilter.h │ │ ├── MIChromaKeyFilter.m │ │ ├── MIChromaKeyFilter.metal │ │ ├── MIColorInvertFilter.h │ │ ├── MIColorInvertFilter.m │ │ ├── MIColorInvertFilter.metal │ │ ├── MIColorMatrixFilter.h │ │ ├── MIColorMatrixFilter.m │ │ ├── MIColorMatrixFilter.metal │ │ ├── MIContrastFilter.h │ │ ├── MIContrastFilter.m │ │ ├── MIContrastFilter.metal │ │ ├── MIExposureFilter.h │ │ ├── MIExposureFilter.m │ │ ├── MIExposureFilter.metal │ │ ├── MIFalseColorFilter.h │ │ ├── MIFalseColorFilter.m │ │ ├── MIFalseColorFilter.metal │ │ ├── MIGammaFilter.h │ │ ├── MIGammaFilter.m │ │ ├── MIGammaFilter.metal │ │ ├── MIGrayscaleFilter.h │ │ ├── MIGrayscaleFilter.m │ │ ├── MIGrayscaleFilter.metal │ │ ├── MIHSBFilter.h │ │ ├── MIHSBFilter.m │ │ ├── MIHSBFilter.metal │ │ ├── MIHazeFilter.h │ │ ├── MIHazeFilter.m │ │ ├── MIHazeFilter.metal │ │ ├── MIHighlightShadowFilter.h │ │ ├── MIHighlightShadowFilter.m │ │ ├── MIHighlightShadowFilter.metal │ │ ├── MIHistogramEqualizationFilter.h │ │ ├── MIHistogramEqualizationFilter.m │ │ ├── MIHistogramFilter.h │ │ ├── MIHistogramFilter.m │ │ ├── MIHistogramGenerator.h │ │ ├── MIHistogramGenerator.m │ │ ├── MIHistogramGenerator.metal │ │ ├── MIHueFilter.h │ │ ├── MIHueFilter.m │ │ ├── MIHueFilter.metal │ │ ├── MILevelsFilter.h │ │ ├── MILevelsFilter.m │ │ ├── MILevelsFilter.metal │ │ ├── MILookupFilter.h │ │ ├── MILookupFilter.m │ │ ├── MILookupFilter.metal │ │ ├── MILuminanceRangeFilter.h │ │ ├── MILuminanceRangeFilter.m │ │ ├── MILuminanceRangeFilter.metal │ │ ├── MILuminanceThresholdFilter.h │ │ ├── MILuminanceThresholdFilter.m │ │ ├── MILuminanceThresholdFilter.metal │ │ ├── MIMonochromeFilter.h │ │ ├── MIMonochromeFilter.m │ │ ├── MIMonochromeFilter.metal │ │ ├── MIOpacityFilter.h │ │ ├── MIOpacityFilter.m │ │ ├── MIOpacityFilter.metal │ │ ├── MIRGBFilter.h │ │ ├── MIRGBFilter.m │ │ ├── MIRGBFilter.metal │ │ ├── MISaturationFilter.h │ │ ├── MISaturationFilter.m │ │ ├── MISaturationFilter.metal │ │ ├── MISepiaFilter.h │ │ ├── MISepiaFilter.m │ │ ├── MISolarizeFilter.h │ │ ├── MISolarizeFilter.m │ │ ├── MISolarizeFilter.metal │ │ ├── MIWhiteBalanceFilter.h │ │ ├── MIWhiteBalanceFilter.m │ │ └── MIWhiteBalanceFilter.metal │ ├── Effects │ │ ├── MIBulgeDistortionFilter.h │ │ ├── MIBulgeDistortionFilter.m │ │ ├── MICGAColorspaceFilter.h │ │ ├── MICGAColorspaceFilter.m │ │ ├── MICGAColorspaceFilter.metal │ │ ├── MICrosshatchFilter.h │ │ ├── MICrosshatchFilter.m │ │ ├── MICrosshatchFilter.metal │ │ ├── MIGlassSphereFilter.h │ │ ├── MIGlassSphereFilter.m │ │ ├── MIHalftoneFilter.h │ │ ├── MIHalftoneFilter.m │ │ ├── MIJFAVoronoiFilter.h │ │ ├── MIJFAVoronoiFilter.m │ │ ├── MIJFAVoronoiFilter.metal │ │ ├── MIKuwaharaFilter.h │ │ ├── MIKuwaharaFilter.m │ │ ├── MIKuwaharaFilter.metal │ │ ├── MIKuwaharaRadius3Filter.h │ │ ├── MIKuwaharaRadius3Filter.m │ │ ├── MIKuwaharaRadius3Filter.metal │ │ ├── MIMosaicFilter.h │ │ ├── MIMosaicFilter.m │ │ ├── MIMosaicFilter.metal │ │ ├── MIPerlinNoiseFilter.h │ │ ├── MIPerlinNoiseFilter.m │ │ ├── MIPerlinNoiseFilter.metal │ │ ├── MIPinchDistortionFilter.h │ │ ├── MIPinchDistortionFilter.m │ │ ├── MIPixellateFilter.h │ │ ├── MIPixellateFilter.m │ │ ├── MIPixellateFilter.metal │ │ ├── MIPolarPixellateFilter.h │ │ ├── MIPolarPixellateFilter.m │ │ ├── MIPolarPixellateFilter.metal │ │ ├── MIPolkaDotFilter.h │ │ ├── MIPolkaDotFilter.m │ │ ├── MIPosterizeFilter.h │ │ ├── MIPosterizeFilter.m │ │ ├── MIPosterizeFilter.metal │ │ ├── MISphereRefractionFilter.h │ │ ├── MISphereRefractionFilter.m │ │ ├── MIStretchDistortionFilter.h │ │ ├── MIStretchDistortionFilter.m │ │ ├── MISwirlFilter.h │ │ ├── MISwirlFilter.m │ │ ├── MISwirlFilter.metal │ │ ├── MIVignetteFilter.h │ │ ├── MIVignetteFilter.m │ │ ├── MIVignetteFilter.metal │ │ ├── MIVoronoiConsumerFilter.h │ │ ├── MIVoronoiConsumerFilter.m │ │ ├── MetalImageDistortionFilter.metal │ │ └── MetalImageSphereFilter.metal │ ├── ImageProcessing │ │ ├── MI3x3ConvolutionFilter.h │ │ ├── MI3x3ConvolutionFilter.m │ │ ├── MI3x3ConvolutionFilter.metal │ │ ├── MIBilateralFilter.h │ │ ├── MIBilateralFilter.m │ │ ├── MIBilateralFilter.metal │ │ ├── MICannyEdgeDetectionFilter.h │ │ ├── MICannyEdgeDetectionFilter.m │ │ ├── MIClosingFilter.h │ │ ├── MIClosingFilter.m │ │ ├── MIColorLocalBinaryPatternFilter.h │ │ ├── MIColorLocalBinaryPatternFilter.m │ │ ├── MIColorLocalBinaryPatternFilter.metal │ │ ├── MIColorPackingFilter.h │ │ ├── MIColorPackingFilter.m │ │ ├── MIColorPackingFilter.metal │ │ ├── MICropFilter.h │ │ ├── MICropFilter.m │ │ ├── MICrosshairGenerator.h │ │ ├── MICrosshairGenerator.m │ │ ├── MIDilationAndErosion.metal │ │ ├── MIDilationFilter.h │ │ ├── MIDilationFilter.m │ │ ├── MIDilationFilter.metal │ │ ├── MIDirectionalNonMaximumSuppressionFilter.h │ │ ├── MIDirectionalNonMaximumSuppressionFilter.m │ │ ├── MIDirectionalNonMaximumSuppressionFilter.metal │ │ ├── MIDirectionalSobelEdgeDetectionFilter.h │ │ ├── MIDirectionalSobelEdgeDetectionFilter.m │ │ ├── MIDirectionalSobelEdgeDetectionFilter.metal │ │ ├── MIErosionFilter.h │ │ ├── MIErosionFilter.m │ │ ├── MIErosionFilter.metal │ │ ├── MIFASTCornerDetectionFilter.h │ │ ├── MIFASTCornerDetectionFilter.m │ │ ├── MIGaussianBlurFilter.h │ │ ├── MIGaussianBlurFilter.m │ │ ├── MIGaussianBlurFilter.metal │ │ ├── MIGuidedFilter.h │ │ ├── MIGuidedFilter.m │ │ ├── MIHighPassFilter.h │ │ ├── MIHighPassFilter.m │ │ ├── MILanczosResamplingFilter.h │ │ ├── MILanczosResamplingFilter.m │ │ ├── MILanczosResamplingFilter.metal │ │ ├── MILaplacianFilter.h │ │ ├── MILaplacianFilter.m │ │ ├── MILocalBinaryPatternFilter.h │ │ ├── MILocalBinaryPatternFilter.m │ │ ├── MILocalBinaryPatternFilter.metal │ │ ├── MILowPassFilter.h │ │ ├── MILowPassFilter.m │ │ ├── MIMaskBilateralFilter.h │ │ ├── MIMaskBilateralFilter.m │ │ ├── MIMaskBilateralFilter.metal │ │ ├── MIMedianFilter.h │ │ ├── MIMedianFilter.m │ │ ├── MIMedianFilter.metal │ │ ├── MINonMaximumSuppressionFilter.h │ │ ├── MINonMaximumSuppressionFilter.m │ │ ├── MINonMaximumSuppressionFilter.metal │ │ ├── MIOpeningFilter.h │ │ ├── MIOpeningFilter.m │ │ ├── MIPrewittEdgeDetectionFilter.h │ │ ├── MIPrewittEdgeDetectionFilter.m │ │ ├── MIPrewittEdgeDetectionFilter.metal │ │ ├── MIRGBClosingFilter.h │ │ ├── MIRGBClosingFilter.m │ │ ├── MIRGBDilationFilter.h │ │ ├── MIRGBDilationFilter.m │ │ ├── MIRGBDilationFilter.metal │ │ ├── MIRGBErosionFilter.h │ │ ├── MIRGBErosionFilter.m │ │ ├── MIRGBErosionFilter.metal │ │ ├── MIRGBOpeningFilter.h │ │ ├── MIRGBOpeningFilter.m │ │ ├── MISharpenFilter.h │ │ ├── MISharpenFilter.m │ │ ├── MISharpenFilter.metal │ │ ├── MISobelEdgeDetectionFilter.h │ │ ├── MISobelEdgeDetectionFilter.m │ │ ├── MISobelEdgeDetectionFilter.metal │ │ ├── MISurfaceBlurFilter.h │ │ ├── MISurfaceBlurFilter.m │ │ ├── MISurfaceBlurFilter.metal │ │ ├── MIThresholdEdgeDetectionFilter.h │ │ ├── MIThresholdEdgeDetectionFilter.m │ │ ├── MITransformFilter.h │ │ ├── MITransformFilter.m │ │ ├── MITransformFilter.metal │ │ ├── MIWeakPixelInclusionFilter.h │ │ ├── MIWeakPixelInclusionFilter.m │ │ ├── MIWeakPixelInclusionFilter.metal │ │ ├── MIXYDerivativeFilter.h │ │ ├── MIXYDerivativeFilter.m │ │ └── MIXYDerivativeFilter.metal │ ├── MI3x3TextureSamplingFilter.h │ ├── MI3x3TextureSamplingFilter.m │ ├── MITwoPassTextureSamplingFilter.h │ ├── MITwoPassTextureSamplingFilter.m │ ├── Matrix │ │ ├── BlasMatrixMult.h │ │ ├── BlasMatrixMult.mm │ │ ├── MetalMatrixBuffers.h │ │ ├── MetalMatrixBuffers.m │ │ ├── MetalMatrixMult.h │ │ ├── MetalMatrixMult.mm │ │ └── MetalMatrixMulti.metal │ ├── Metal │ │ ├── CommonShader.metal │ │ ├── CommonStruct.metal │ │ └── Convolution.metal │ ├── MetalDevice.h │ ├── MetalDevice.m │ ├── MetalImage.h │ ├── MetalImageBuffer.h │ ├── MetalImageBuffer.m │ ├── MetalImageColorConversion.h │ ├── MetalImageColorConversion.m │ ├── MetalImageColorConversion.metal │ ├── MetalImageCommonFilter.h │ ├── MetalImageCommonFilter.m │ ├── MetalImageContext.h │ ├── MetalImageContext.m │ ├── MetalImageDebugView.h │ ├── MetalImageDebugView.m │ ├── MetalImageFilter.h │ ├── MetalImageFilter.m │ ├── MetalImageFilterExtension.h │ ├── MetalImageFilterExtension.m │ ├── MetalImageFilterGroup.h │ ├── MetalImageFilterGroup.m │ ├── MetalImageFunction.h │ ├── MetalImageFunction.m │ ├── MetalImageGlobal.h │ ├── MetalImageInput.h │ ├── MetalImageKernel.h │ ├── MetalImageKernel.m │ ├── MetalImageMath.c │ ├── MetalImageMath.h │ ├── MetalImageOutput.h │ ├── MetalImageOutput.m │ ├── MetalImagePicture.h │ ├── MetalImagePicture.m │ ├── MetalImagePreprocess.h │ ├── MetalImagePreprocess.m │ ├── MetalImageRenderResource.h │ ├── MetalImageRenderResource.m │ ├── MetalImageTexture.h │ ├── MetalImageTexture.m │ ├── MetalImageTextureCache.h │ ├── MetalImageTextureCache.m │ ├── MetalImageTwoInputFilter.h │ ├── MetalImageTwoInputFilter.m │ ├── MetalImageTwoInputKernel.h │ ├── MetalImageTwoInputKernel.m │ ├── MetalImageTwoPassFilter.h │ ├── MetalImageTwoPassFilter.m │ ├── MetalImageTypes.c │ ├── MetalImageTypes.h │ ├── MetalImageVideoCamera.h │ ├── MetalImageVideoCamera.m │ ├── MetalImageView.h │ ├── MetalImageView.m │ ├── UIImage+Texture.h │ └── UIImage+Texture.m ├── Resources │ ├── lookup.png │ ├── lookup_amatorka.png │ ├── lookup_miss_etikate.png │ ├── lookup_soft_elegance_1.png │ └── lookup_soft_elegance_2.png ├── ViewController.h ├── ViewController.m ├── ViewController.xib └── main.m ├── README.md └── privacypolicy.html /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | MetalImage.xcodeproj/project.xcworkspace/xcuserdata/fengstone.xcuserdatad/UserInterfaceState.xcuserstate 3 | MetalImage.xcodeproj/project.xcworkspace/xcuserdata/fengstone.xcuserdatad/UserInterfaceState.xcuserstate 4 | *.xcuserstate 5 | MetalImage.xcodeproj/project.xcworkspace/xcuserdata/fengstone.xcuserdatad/UserInterfaceState.xcuserstate 6 | *.xcuserstate 7 | *.xcuserstate 8 | *.xcuserstate 9 | *.xcuserstate 10 | MetalImage.xcodeproj/project.xcworkspace/xcuserdata/fengstone.xcuserdatad/UserInterfaceState.xcuserstate 11 | *.xcuserstate 12 | *.xcuserstate 13 | MetalImage.xcodeproj/project.xcworkspace/xcuserdata/fengstone.xcuserdatad/UserInterfaceState.xcuserstate 14 | -------------------------------------------------------------------------------- /Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/Default-568h@2x.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Fengshi 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 | -------------------------------------------------------------------------------- /MetalImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MetalImage.xcodeproj/project.xcworkspace/xcuserdata/fengshi.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage.xcodeproj/project.xcworkspace/xcuserdata/fengshi.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MetalImage.xcodeproj/project.xcworkspace/xcuserdata/fengstone.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage.xcodeproj/project.xcworkspace/xcuserdata/fengstone.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MetalImage.xcodeproj/project.xcworkspace/xcuserdata/stonefeng.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage.xcodeproj/project.xcworkspace/xcuserdata/stonefeng.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MetalImage/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/2/7. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | 22 | -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/1024x1024.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/120x120-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/120x120-1.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/120x120.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/152x152.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/167x167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/167x167.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/180x180.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/20x20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/20x20.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/29x29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/29x29.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/40x40-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/40x40-1.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/40x40-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/40x40-2.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/40x40.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/58x58-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/58x58-1.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/58x58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/58x58.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/60x60.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/76x76.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/80x80-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/80x80-1.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/80x80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/80x80.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/AppIcon.appiconset/87x87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Assets.xcassets/AppIcon.appiconset/87x87.png -------------------------------------------------------------------------------- /MetalImage/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /MetalImage/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSCameraUsageDescription 22 | Camera Usage Description 23 | NSPhotoLibraryAddUsageDescription 24 | Photo Library Additions Usage Description 25 | NSPrincipalClass 26 | 27 | UISupportedInterfaceOrientations 28 | 29 | UIInterfaceOrientationPortrait 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIAddBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIAddBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIAddBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIAddBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIAddBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIAddBlendFilter.h" 10 | 11 | @implementation MIAddBlendFilter 12 | 13 | 14 | - (id)init 15 | { 16 | if (!(self = [super initWithFragmentFunctionName:@"fragment_addBlend"])) 17 | { 18 | return nil; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIAlphaBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIAlphaBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIAlphaBlendFilter : MetalImageTwoInputFilter 14 | 15 | // Mix ranges from 0.0 (only image 1) to 1.0 (only image 2), with 1.0 as the normal level 16 | @property(readwrite, nonatomic) CGFloat mix; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIAlphaBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIAlphaBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIAlphaBlendFilter.h" 10 | #import "MetalDevice.h" 11 | 12 | @interface MIAlphaBlendFilter() 13 | 14 | @property (nonatomic, strong) id buffer; 15 | 16 | @end 17 | 18 | @implementation MIAlphaBlendFilter 19 | 20 | - (id)init 21 | { 22 | if (!(self = [super initWithFragmentFunctionName:@"fragment_alphaBlend"])) 23 | { 24 | return nil; 25 | } 26 | 27 | id device = [MetalDevice sharedMTLDevice]; 28 | _buffer = [device newBufferWithLength:sizeof(MTLFloat)*1 options:MTLResourceOptionCPUCacheModeDefault]; 29 | 30 | self.mix = 0.5; 31 | 32 | return self; 33 | } 34 | 35 | - (void)setMix:(CGFloat)mix { 36 | _mix = mix; 37 | [self updateContentBuffer]; 38 | } 39 | 40 | - (void)updateContentBuffer 41 | { 42 | MTLFloat *bufferContents = (MTLFloat *)[_buffer contents]; 43 | bufferContents[0] = _mix; 44 | } 45 | 46 | - (void)assembleRenderEncoder:(id)renderEncoder { 47 | NSParameterAssert(renderEncoder); 48 | 49 | [renderEncoder setDepthStencilState:_depthStencilState]; 50 | [renderEncoder setRenderPipelineState:_pipelineState]; 51 | [renderEncoder setVertexBuffer:_verticsBuffer offset:0 atIndex:0]; 52 | [renderEncoder setVertexBuffer:_coordBuffer offset:0 atIndex:1]; 53 | [renderEncoder setFragmentTexture:[firstInputTexture texture] atIndex:0]; 54 | [renderEncoder setFragmentBuffer:_buffer offset:0 atIndex:0]; 55 | [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:MetalImageDefaultRenderVetexCount instanceCount:1]; 56 | [renderEncoder endEncoding]; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIChromaKeyBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIChromaKeyBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIChromaKeyBlendFilter : MetalImageTwoInputFilter 14 | 15 | /** The threshold sensitivity controls how similar pixels need to be colored to be replaced 16 | 17 | The default value is 0.3 18 | */ 19 | @property(readwrite, nonatomic) MTLFloat thresholdSensitivity; 20 | 21 | /** The degree of smoothing controls how gradually similar colors are replaced in the image 22 | 23 | The default value is 0.1 24 | */ 25 | @property(readwrite, nonatomic) MTLFloat smoothing; 26 | 27 | /** The color to be replaced is specified using individual red, green, and blue components (normalized to 1.0). 28 | 29 | The default is green: (0.0, 1.0, 0.0). 30 | 31 | colorToReplace RGB components of color to be replaced 32 | */ 33 | @property (nonatomic, assign) MTLFloat3 colorToReplace; 34 | 35 | 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIColorBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIColorBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIColorBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIColorBlendFilter.h" 10 | 11 | @implementation MIColorBlendFilter 12 | 13 | 14 | - (id)init 15 | { 16 | if (!(self = [super initWithFragmentFunctionName:@"fragment_colorBlend"])) 17 | { 18 | return nil; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIColorBurnBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorBurnBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | /** Applies a color burn blend of two images 12 | */ 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface MIColorBurnBlendFilter : MetalImageTwoInputFilter 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIColorBurnBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorBurnBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIColorBurnBlendFilter.h" 10 | 11 | @implementation MIColorBurnBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_colorBurnBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIColorDodgeBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorDodgeBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | /** Applies a color dodge blend of two images 12 | */ 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface MIColorDodgeBlendFilter : MetalImageTwoInputFilter 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIColorDodgeBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorDodgeBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIColorDodgeBlendFilter.h" 10 | 11 | @implementation MIColorDodgeBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_colorDodgeBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIDarkenBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIDarkenBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIDarkenBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIDarkenBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIDarkenBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIDarkenBlendFilter.h" 10 | 11 | @implementation MIDarkenBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_darkenBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIDifferenceBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIDifferenceBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIDifferenceBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIDifferenceBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIDifferenceBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIDifferenceBlendFilter.h" 10 | 11 | @implementation MIDifferenceBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_differenceBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIDissolveBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIDissolveBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIDissolveBlendFilter : MetalImageTwoInputFilter 14 | 15 | // Mix ranges from 0.0 (only image 1) to 1.0 (only image 2), with 0.5 (half of either) as the normal level 16 | @property(readwrite, nonatomic) MTLFloat mix; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIDivideBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIDivideBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIDivideBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIDivideBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIDivideBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIDivideBlendFilter.h" 10 | 11 | @implementation MIDivideBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_divideBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIExclusionBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIExclusionBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIExclusionBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIExclusionBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIExclusionBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIExclusionBlendFilter.h" 10 | 11 | @implementation MIExclusionBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_exclusionBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIHardLightBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHardLightBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIHardLightBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIHardLightBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIHardLightBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIHardLightBlendFilter.h" 10 | 11 | @implementation MIHardLightBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_hardlightBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIHueBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHueBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIHueBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIHueBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIHueBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIHueBlendFilter.h" 10 | 11 | @implementation MIHueBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_hueBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MILightenBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILightenBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | /// Blends two images by taking the maximum value of each color component between the images 13 | @interface MILightenBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MILightenBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MILightenBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MILightenBlendFilter.h" 10 | 11 | @implementation MILightenBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_lightenBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MILinearBurnBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILinearBurnBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MILinearBurnBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MILinearBurnBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MILinearBurnBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MILinearBurnBlendFilter.h" 10 | 11 | @implementation MILinearBurnBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_linearBurnBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MILuminosityBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILuminosityBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MILuminosityBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MILuminosityBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MILuminosityBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MILuminosityBlendFilter.h" 10 | 11 | @implementation MILuminosityBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_luminosityBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIMaskFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIMaskFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIMaskFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIMultiplyBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIMultiplyBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIMultiplyBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIMultiplyBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIMultiplyBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIMultiplyBlendFilter.h" 10 | 11 | @implementation MIMultiplyBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_multiplyBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MINormalBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MINormalBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MINormalBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MINormalBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MINormalBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MINormalBlendFilter.h" 10 | 11 | @implementation MINormalBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_normalBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIOverlayBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIOverlayBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIOverlayBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIOverlayBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIOverlayBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIOverlayBlendFilter.h" 10 | 11 | @implementation MIOverlayBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_overlayBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MISaturationBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISaturationBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MISaturationBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MISaturationBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MISaturationBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISaturationBlendFilter.h" 10 | 11 | @implementation MISaturationBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_saturationBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIScreenBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIScreenBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIScreenBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MIScreenBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIScreenBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIScreenBlendFilter.h" 10 | 11 | @implementation MIScreenBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_screenBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MISoftLightBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISoftLightBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MISoftLightBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MISoftLightBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MISoftLightBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISoftLightBlendFilter.h" 10 | 11 | @implementation MISoftLightBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_softlightBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MISourceOverBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISourceOverBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MISourceOverBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MISourceOverBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MISourceOverBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISourceOverBlendFilter.h" 10 | 11 | @implementation MISourceOverBlendFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_sourceOverBlend"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MISubtractBlendFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISubtractBlendFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MISubtractBlendFilter : MetalImageTwoInputFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Blend/MISubtractBlendFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MISubtractBlendFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISubtractBlendFilter.h" 10 | 11 | @implementation MISubtractBlendFilter 12 | 13 | 14 | - (id)init 15 | { 16 | if (!(self = [super initWithFragmentFunctionName:@"fragment_subtractBlend"])) 17 | { 18 | return nil; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIAdaptiveLuminanceFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIAdaptiveLuminanceFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2021/2/19. 6 | // Copyright © 2021 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIAdaptiveLuminanceFilter : MetalImageFilter 14 | 15 | @property (nonatomic, assign) MTLFloat scale; 16 | 17 | @property (nonatomic, assign) MTLFloat offset; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIAdaptiveLuminanceFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIAdaptiveLuminanceFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2021/2/19. 6 | // Copyright © 2021 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | typedef struct { 13 | float k; 14 | float b; 15 | }LineParameters; 16 | 17 | fragment half4 fragment_adaptiveLuminance(VertexIO inFrag [[ stage_in ]], 18 | texture2d tex2D [[ texture(0) ]], 19 | constant LineParameters &linePara [[ buffer(0) ]]) 20 | { 21 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 22 | 23 | const float3 luminanceWeight = float3(0.2627f, 0.6780f, 0.0593f); 24 | 25 | const float3 uWeight = float3(-0.1396f, -0.3604f, 0.5f); 26 | const float3 vWeight = float3(0.5f, -0.4598f, -0.0402f); 27 | float4 source = tex2D.sample(quadSampler, inFrag.textureCoordinate); 28 | float luminance = dot(source.rgb, luminanceWeight); 29 | float u = dot(source.rgb, uWeight); 30 | float v = dot(source.rgb, vWeight); 31 | luminance = clamp(luminance * linePara.k + linePara.b, 0.0f, 1.0f); 32 | 33 | float3 result = float3(luminance, u, v); 34 | 35 | const float3x3 kColorConversion601FullRangeDefault = { 36 | {1.0, 1.0, 1.0}, 37 | {0.0, -0.343, 1.765}, 38 | {1.4, -0.711, 0.0}, 39 | }; 40 | 41 | return half4(half3(kColorConversion601FullRangeDefault * result), 1.0h); 42 | } 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIAdaptiveThresholdFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIAdaptiveThresholdFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilterGroup.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIAdaptiveThresholdFilter : MetalImageFilterGroup 14 | 15 | /** A multiplier for the background averaging blur radius in pixels, with a default of 4 16 | */ 17 | @property(readwrite, nonatomic) CGFloat blurRadiusInPixels; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIAdaptiveThresholdFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIAdaptiveThresholdFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIAdaptiveThresholdFilter.h" 10 | #import "MetalImageContext.h" 11 | #import "MetalDevice.h" 12 | #import "MetalImageFilter.h" 13 | #import "MetalImageTwoInputFilter.h" 14 | #import "MIGrayscaleFilter.h" 15 | //#import "MetalImageBoxBlurFilter.h" 16 | 17 | @interface MIAdaptiveThresholdFilter() { 18 | 19 | } 20 | 21 | @end 22 | 23 | @implementation MIAdaptiveThresholdFilter 24 | 25 | 26 | #pragma mark - 27 | #pragma mark Accessors 28 | 29 | - (void)setBlurRadiusInPixels:(CGFloat)newValue; 30 | { 31 | // boxBlurFilter.blurRadiusInPixels = newValue; 32 | } 33 | 34 | - (CGFloat)blurRadiusInPixels; 35 | { 36 | // return boxBlurFilter.blurRadiusInPixels; 37 | return 0; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIAdaptiveThresholdFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIAdaptiveThresholdFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | 13 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIAverageLuminanceThresholdFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIAverageLuminanceThresholdFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/3. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilterGroup.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIAverageLuminanceThresholdFilter : MetalImageFilterGroup 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIAverageLuminanceThresholdFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIAverageLuminanceThresholdFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/3. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIAverageLuminanceThresholdFilter.h" 10 | 11 | @implementation MIAverageLuminanceThresholdFilter 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIBrightnessFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIBrightnessFilter.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/16. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIBrightnessFilter : MetalImageFilter 14 | 15 | // Brightness ranges from -1.0 to 1.0, with 0.0 as the normal level 16 | @property (nonatomic,assign) MTLFloat brightness; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIBrightnessFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIBrightnessFilter.m 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/16. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIBrightnessFilter.h" 10 | #import "MetalImageContext.h" 11 | #import "MetalDevice.h" 12 | 13 | @interface MIBrightnessFilter () 14 | 15 | @property (nonatomic,strong) id buffer; 16 | 17 | @end 18 | 19 | @implementation MIBrightnessFilter 20 | 21 | - (instancetype)init { 22 | if (self = [super initWithFragmentFunctionName:@"fragment_brightness"]) { 23 | id device = [MetalDevice sharedMTLDevice]; 24 | _buffer = [device newBufferWithLength:sizeof(MTLFloat) options:MTLResourceOptionCPUCacheModeDefault]; 25 | self.brightness = 1.0f; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)dealloc { 31 | _buffer = nil; 32 | } 33 | 34 | - (void)setBrightness:(MTLFloat)brightness { 35 | _brightness = brightness; 36 | MTLFloat *bufferContents = (MTLFloat *)[_buffer contents]; 37 | bufferContents[0] = _brightness; 38 | } 39 | 40 | - (void)assembleRenderEncoder:(id)renderEncoder { 41 | [renderEncoder setDepthStencilState:_depthStencilState]; 42 | [renderEncoder setRenderPipelineState:_pipelineState]; 43 | [renderEncoder setVertexBuffer:_verticsBuffer offset:0 atIndex:0]; 44 | [renderEncoder setVertexBuffer:_coordBuffer offset:0 atIndex:1]; 45 | [renderEncoder setFragmentTexture:[firstInputTexture texture] atIndex:0]; 46 | [renderEncoder setFragmentBuffer:_buffer offset:0 atIndex:0]; 47 | [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:MetalImageDefaultRenderVetexCount instanceCount:1]; 48 | [renderEncoder endEncoding]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIBrightnessFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIBrightnessFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Stone Feng on 2017/8/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_brightness(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float &brightness [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | half4 inColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 18 | return half4((inColor.rgb + half3(brightness)), inColor.a); 19 | } 20 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIChromaKeyFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIChromaKeyFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/8/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIChromaKeyFilter : MetalImageFilter 14 | 15 | /** The threshold sensitivity controls how similar pixels need to be colored to be replaced 16 | 17 | The default value is 0.3 18 | */ 19 | @property(readwrite, nonatomic) MTLFloat thresholdSensitivity; 20 | 21 | /** The degree of smoothing controls how gradually similar colors are replaced in the image 22 | 23 | The default value is 0.1 24 | */ 25 | @property(readwrite, nonatomic) MTLFloat smoothing; 26 | 27 | /** The color to be replaced is specified using individual red, green, and blue components (normalized to 1.0). 28 | 29 | The default is green: (0.0, 1.0, 0.0). 30 | 31 | colorToReplace RGB components of color to be replaced 32 | */ 33 | @property (nonatomic, assign) MTLFloat3 colorToReplace; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIColorInvertFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorInvertFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/8/25. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIColorInvertFilter : MetalImageFilter 14 | 15 | 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIColorInvertFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorInvertFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/8/25. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIColorInvertFilter.h" 10 | 11 | @implementation MIColorInvertFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_colorInvert"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIColorInvertFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorInvertFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/8/25. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_colorInvert(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]]) 14 | { 15 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 16 | 17 | half4 c = tex2D.sample(quadSampler, inFrag.textureCoordinate); 18 | 19 | return half4(half3(1.0h)-c.rgb, c.a); 20 | } 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIColorMatrixFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorMatrixFilter.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | /** Transforms the colors of an image by applying a matrix to them 10 | */ 11 | #import "MetalImageFilter.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface MIColorMatrixFilter : MetalImageFilter 16 | 17 | /** A 4x4 matrix used to transform each color in an image 18 | */ 19 | @property(readwrite, nonatomic) MTLFloat4x4 colorMatrix; 20 | 21 | /** The degree to which the new transformed color replaces the original color for each pixel 22 | */ 23 | @property(readwrite, nonatomic) MTLFloat intensity; 24 | 25 | 26 | @property(nonatomic, strong) id buffer; 27 | 28 | 29 | - (void)updateBufferContents; 30 | 31 | @end 32 | 33 | NS_ASSUME_NONNULL_END 34 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIColorMatrixFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorMatrixFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Stone Feng on 2017/8/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | struct ColorMatrix 13 | { 14 | packed_float4 red; 15 | packed_float4 green; 16 | packed_float4 blue; 17 | packed_float4 alpha; 18 | float intensity; 19 | }; 20 | 21 | fragment half4 fragment_colorMatrix(VertexIO inFrag [[ stage_in ]], 22 | texture2d tex2D [[ texture(0) ]], 23 | constant ColorMatrix &matrixParameter [[ buffer(0) ]]) 24 | { 25 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 26 | half4 inColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 27 | 28 | half4x4 colorMatrix = half4x4(half4(matrixParameter.red), 29 | half4(matrixParameter.green), 30 | half4(matrixParameter.blue), 31 | half4(matrixParameter.alpha)); 32 | half4 outputColor = inColor * colorMatrix; 33 | half intensity = (half)matrixParameter.intensity; 34 | 35 | return mix(inColor, outputColor, intensity); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIContrastFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIContrastFilter.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/15. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIContrastFilter : MetalImageFilter 14 | 15 | /** Contrast ranges from 0.0 to 4.0 (max contrast), with 1.0 as the normal level 16 | */ 17 | @property (nonatomic,assign) MTLFloat contrast; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIContrastFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIContrastFilter.m 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/15. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIContrastFilter.h" 10 | #import "MetalImageContext.h" 11 | #import "MetalDevice.h" 12 | 13 | @interface MIContrastFilter () 14 | 15 | @property (nonatomic,strong) id buffer; 16 | 17 | @end 18 | 19 | @implementation MIContrastFilter 20 | 21 | - (instancetype)init { 22 | if (self = [super initWithFragmentFunctionName:@"fragment_contrast"]) { 23 | id device = [MetalDevice sharedMTLDevice]; 24 | _buffer = [device newBufferWithLength:sizeof(MTLFloat) options:MTLResourceOptionCPUCacheModeDefault]; 25 | self.contrast = 1.0f; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)dealloc { 31 | _buffer = nil; 32 | } 33 | 34 | - (void)setContrast:(MTLFloat)contrast { 35 | _contrast = contrast; 36 | MTLFloat *bufferContents = (MTLFloat *)[_buffer contents]; 37 | bufferContents[0] = _contrast; 38 | } 39 | 40 | - (void)assembleRenderEncoder:(id)renderEncoder { 41 | [renderEncoder setDepthStencilState:_depthStencilState]; 42 | [renderEncoder setRenderPipelineState:_pipelineState]; 43 | [renderEncoder setVertexBuffer:_verticsBuffer offset:0 atIndex:0]; 44 | [renderEncoder setVertexBuffer:_coordBuffer offset:0 atIndex:1]; 45 | [renderEncoder setFragmentTexture:[firstInputTexture texture] atIndex:0]; 46 | [renderEncoder setFragmentBuffer:_buffer offset:0 atIndex:0]; 47 | [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:MetalImageDefaultRenderVetexCount instanceCount:1]; 48 | [renderEncoder endEncoding]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIContrastFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIContrastFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Stone Feng on 2017/8/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_contrast(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float &contrast [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | half4 inColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 18 | return half4((inColor.rgb - half3(0.5h))* contrast + half3(0.5h), inColor.a); 19 | } 20 | 21 | kernel void kernal_contrast(texture2d inTexture [[texture(0)]], 22 | texture2d outTexture [[texture(1)]], 23 | constant float &contrast [[buffer(0)]], 24 | uint2 gid [[thread_position_in_grid]]) 25 | { 26 | const float4 inColor = inTexture.read(gid); 27 | const float4 outColor = float4((inColor.rgb - float3(0.5f))* contrast + float3(0.5f), inColor.a); 28 | outTexture.write(outColor, gid); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIExposureFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIExposureFilter.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIExposureFilter : MetalImageFilter 14 | 15 | // Exposure ranges from -10.0 to 10.0, with 0.0 as the normal level 16 | @property (nonatomic,assign) MTLFloat exposure; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIExposureFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIExposureFilter.m 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIExposureFilter.h" 10 | #import "MetalImageContext.h" 11 | #import "MetalDevice.h" 12 | 13 | @interface MIExposureFilter() 14 | 15 | @property (nonatomic,strong) id buffer; 16 | 17 | @end 18 | 19 | @implementation MIExposureFilter 20 | 21 | 22 | - (instancetype)init { 23 | if (self = [super initWithFragmentFunctionName:@"fragment_exposure"]) { 24 | id device = [MetalDevice sharedMTLDevice]; 25 | _buffer = [device newBufferWithLength:sizeof(MTLFloat) options:MTLResourceOptionCPUCacheModeDefault]; 26 | self.exposure = 0.0f; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)dealloc { 32 | _buffer = nil; 33 | } 34 | 35 | - (void)setExposure:(MTLFloat)exposure { 36 | _exposure = exposure; 37 | MTLFloat *bufferContents = (MTLFloat *)[_buffer contents]; 38 | bufferContents[0] = _exposure; 39 | } 40 | 41 | - (void)assembleRenderEncoder:(id)renderEncoder { 42 | [renderEncoder setDepthStencilState:_depthStencilState]; 43 | [renderEncoder setRenderPipelineState:_pipelineState]; 44 | [renderEncoder setVertexBuffer:_verticsBuffer offset:0 atIndex:0]; 45 | [renderEncoder setVertexBuffer:_coordBuffer offset:0 atIndex:1]; 46 | [renderEncoder setFragmentTexture:[firstInputTexture texture] atIndex:0]; 47 | [renderEncoder setFragmentBuffer:_buffer offset:0 atIndex:0]; 48 | [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:MetalImageDefaultRenderVetexCount instanceCount:1]; 49 | [renderEncoder endEncoding]; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIExposureFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIExposureFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Stone Feng on 2017/8/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_exposure(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float &exposure [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | half4 inColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 18 | return half4(inColor.rgb * pow(2.0, exposure), inColor.a); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIFalseColorFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIFalseColorFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/7/23. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIFalseColorFilter : MetalImageFilter 14 | 15 | // The first and second colors specify what colors replace the dark and light areas of the image, respectively. 16 | // The defaults are (0.0, 0.0, 0.5) amd (1.0, 0.0, 0.0). 17 | @property (readwrite, nonatomic) MTLFloat4 firstColor; 18 | @property (readwrite, nonatomic) MTLFloat4 secondColor; 19 | 20 | @property (nonatomic, strong) id buffer; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIFalseColorFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIFalseColorFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/7/23. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | typedef struct { 13 | packed_float3 firstColor; 14 | packed_float3 secondColor; 15 | }TwoColors; 16 | 17 | fragment half4 fragment_falseColor(VertexIO inFrag [[ stage_in ]], 18 | texture2d tex2D [[ texture(0) ]], 19 | constant TwoColors &twoColors [[ buffer(0) ]]) 20 | { 21 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 22 | 23 | const half3 luminanceWeighting = half3(0.2125h, 0.7154h, 0.0721h); 24 | 25 | half4 textureColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 26 | half luminance = dot(textureColor.rgb, luminanceWeighting); 27 | 28 | half3 firstColor = half3(twoColors.firstColor); 29 | half3 secondColor = half3(twoColors.secondColor); 30 | return half4(mix(firstColor.rgb, secondColor.rgb, luminance), textureColor.a); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIGammaFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIGammaFilter.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIGammaFilter : MetalImageFilter 14 | 15 | // Gamma ranges from 0.0 to 3.0, with 1.0 as the normal level 16 | @property (nonatomic,assign) MTLFloat gamma; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIGammaFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIGammaFilter.m 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIGammaFilter.h" 10 | #import "MetalImageContext.h" 11 | #import "MetalDevice.h" 12 | 13 | @interface MIGammaFilter () 14 | 15 | @property (nonatomic,strong) id buffer; 16 | 17 | @end 18 | 19 | @implementation MIGammaFilter 20 | 21 | - (instancetype)init { 22 | if (self = [super initWithFragmentFunctionName:@"fragment_gamma"]) { 23 | id device = [MetalDevice sharedMTLDevice]; 24 | _buffer = [device newBufferWithLength:sizeof(MTLFloat) options:MTLResourceOptionCPUCacheModeDefault]; 25 | self.gamma = 1.0f; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)dealloc { 31 | _buffer = nil; 32 | } 33 | 34 | - (void)setGamma:(MTLFloat)gamma { 35 | _gamma = gamma; 36 | MTLFloat *bufferContents = (MTLFloat *)[_buffer contents]; 37 | bufferContents[0] = _gamma; 38 | } 39 | 40 | - (void)assembleRenderEncoder:(id)renderEncoder { 41 | [renderEncoder setDepthStencilState:_depthStencilState]; 42 | [renderEncoder setRenderPipelineState:_pipelineState]; 43 | [renderEncoder setVertexBuffer:_verticsBuffer offset:0 atIndex:0]; 44 | [renderEncoder setVertexBuffer:_coordBuffer offset:0 atIndex:1]; 45 | [renderEncoder setFragmentTexture:[firstInputTexture texture] atIndex:0]; 46 | [renderEncoder setFragmentBuffer:_buffer offset:0 atIndex:0]; 47 | [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:MetalImageDefaultRenderVetexCount instanceCount:1]; 48 | [renderEncoder endEncoding]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIGammaFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIGammaFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Stone Feng on 2017/8/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_gamma(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float &gamma [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | half4 inColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 18 | return half4(pow(inColor.rgb, half3(gamma)), inColor.a); 19 | } 20 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIGrayscaleFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIGrayscaleFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/27. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** Converts an image to grayscale (a slightly faster implementation of the saturation filter, 14 | * without the ability to vary the color contribution) 15 | */ 16 | @interface MIGrayscaleFilter : MetalImageFilter 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIGrayscaleFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIGrayscaleFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/27. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIGrayscaleFilter.h" 10 | 11 | @implementation MIGrayscaleFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_luminance"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIGrayscaleFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIGrayscaleFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/27. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_luminance(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]]) 14 | { 15 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 16 | 17 | float4 textureColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 18 | 19 | const float3 W = float3(0.2125h, 0.7154h, 0.0721h); 20 | 21 | float luminance = dot(textureColor.rgb, W); 22 | 23 | return half4(half3(luminance), half(textureColor.a)); 24 | } 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHSBFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHSBFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/7/22. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIColorMatrixFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIHSBFilter : MIColorMatrixFilter 14 | 15 | /** Reset the filter to have no transformations. 16 | */ 17 | - (void)reset; 18 | 19 | /** Add a hue rotation to the filter. 20 | The hue rotation is in the range [-360, 360] with 0 being no-change. 21 | Note that this adjustment is additive, so use the reset method if you need to. 22 | */ 23 | - (void)rotateHue:(float)h; 24 | 25 | /** Add a saturation adjustment to the filter. 26 | The saturation adjustment is in the range [0.0, 2.0] with 1.0 being no-change. 27 | Note that this adjustment is additive, so use the reset method if you need to. 28 | */ 29 | - (void)adjustSaturation:(float)s; 30 | 31 | /** Add a brightness adjustment to the filter. 32 | The brightness adjustment is in the range [0.0, 2.0] with 1.0 being no-change. 33 | Note that this adjustment is additive, so use the reset method if you need to. 34 | */ 35 | - (void)adjustBrightness:(float)b; 36 | 37 | @end 38 | 39 | NS_ASSUME_NONNULL_END 40 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHSBFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIHSBFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/7/22. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | 13 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHazeFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHazeFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/8/23. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | /* 10 | * The haze filter can be used to add or remove haze (similar to a UV filter) 11 | * 12 | * @author Alaric Cole 13 | * @creationDate 03/10/12 14 | * 15 | */ 16 | 17 | /** The haze filter can be used to add or remove haze 18 | 19 | This is similar to a UV filter 20 | */ 21 | 22 | #import "MetalImageFilter.h" 23 | 24 | NS_ASSUME_NONNULL_BEGIN 25 | 26 | @interface MIHazeFilter : MetalImageFilter 27 | 28 | /** Strength of the color applied. Default 0. Values between -.3 and .3 are best 29 | */ 30 | @property (readwrite, nonatomic) CGFloat distance; 31 | 32 | /** Amount of color change. Default 0. Values between -.3 and .3 are best 33 | */ 34 | @property (readwrite, nonatomic) CGFloat slope; 35 | 36 | @property (nonatomic, strong) id buffer; 37 | 38 | @end 39 | 40 | NS_ASSUME_NONNULL_END 41 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHazeFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIHazeFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/8/23. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | typedef struct { 13 | float hazeDistance; 14 | float slope; 15 | }HazeParameters; 16 | 17 | fragment half4 fragment_haze(VertexIO inFrag [[ stage_in ]], 18 | texture2d tex2D [[ texture(0) ]], 19 | constant HazeParameters &hazeParameters [[ buffer(0) ]]) 20 | { 21 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 22 | 23 | half4 color = half4(1.0); 24 | float d = inFrag.textureCoordinate.y * hazeParameters.slope + hazeParameters.hazeDistance; 25 | half4 c = tex2D.sample(quadSampler, inFrag.textureCoordinate); 26 | 27 | c = (c - d * color) / (1.0h - half4(d)); 28 | 29 | return half4(c); 30 | } 31 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHighlightShadowFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHighlightShadowFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/7/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIHighlightShadowFilter : MetalImageFilter 14 | 15 | /** 16 | * 0 - 1, increase to lighten shadows. 17 | * @default 0 18 | */ 19 | @property(readwrite, nonatomic) MTLFloat shadows; 20 | 21 | /** 22 | * 0 - 1, decrease to darken highlights. 23 | * @default 1 24 | */ 25 | @property(readwrite, nonatomic) MTLFloat highlights; 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHighlightShadowFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIHighlightShadowFilter.metal 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/7/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | typedef struct { 13 | float shadows; 14 | float highlights; 15 | }HighlightShadowParameters; 16 | 17 | fragment half4 fragment_highlightShadow(VertexIO inFrag [[ stage_in ]], 18 | texture2d tex2D [[ texture(0) ]], 19 | constant HighlightShadowParameters &highlightShadow [[ buffer(0) ]]) 20 | { 21 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 22 | 23 | const half3 luminanceWeighting = half3(0.3h, 0.3h, 0.3h); 24 | half4 source = tex2D.sample(quadSampler, inFrag.textureCoordinate); 25 | half luminance = dot(source.rgb, luminanceWeighting); 26 | float shadows = highlightShadow.shadows; 27 | float shadow = clamp((pow(float(luminance), 1.0/(shadows+1.0)) + (-0.76)*pow(float(luminance), 2.0/(shadows+1.0))) - luminance, 0.0, 1.0); 28 | float highlights = highlightShadow.highlights; 29 | float highlight = clamp((1.0 - (pow(1.0-luminance, 1.0/(2.0-highlights)) + (-0.8)*pow(1.0-luminance, 2.0/(2.0-highlights)))) - luminance, -1.0, 0.0); 30 | half3 result = half3(0.0) + ((luminance + shadow + highlight) - 0.0) * ((source.rgb - half3(0.0))/(luminance - 0.0)); 31 | 32 | return half4(result, source.a); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHistogramEqualizationFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHistogramEqualizationFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2021/2/19. 6 | // Copyright © 2021 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIHistogramEqualizationFilter : MetalImageFilter 14 | 15 | // Rather than sampling every pixel, this dictates what fraction of the image is sampled. By default, this is 16 with a minimum of 1. 16 | @property (readwrite, nonatomic) NSUInteger downsamplingFactor; 17 | 18 | @property (readwrite, nonatomic) NSTimeInterval duration; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHistogramFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHistogramFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/11/3. 6 | // Copyright © 2017年 tencent. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | typedef enum { 12 | kMetalImageHistogramTypeHist = 0, 13 | kMetalImageHistogramTypeSTD = 1, 14 | kMetalImageHistogramTypeMean = 2, 15 | } MetalImageHistogramType; 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface MIHistogramFilter : MetalImageFilter 20 | { 21 | } 22 | 23 | 24 | // Rather than sampling every pixel, this dictates what fraction of the image is sampled. By default, this is 16 with a minimum of 1. 25 | @property (readwrite, nonatomic) NSUInteger downsamplingFactor; 26 | 27 | // Initialization and teardown 28 | - (id)initWithHistogramType:(MetalImageHistogramType)histogramType; 29 | 30 | @end 31 | 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHistogramGenerator.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHistogramGenerator.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIHistogramGenerator : MetalImageFilter 14 | 15 | @property (nonatomic, assign) MTLFloat4 backgroundColor; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHistogramGenerator.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIHistogramGenerator.metal 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | struct VertexIO 13 | { 14 | float4 position [[position]]; 15 | float2 textureCoordinate [[user(texturecoord)]]; 16 | float height; 17 | }; 18 | 19 | vertex VertexIO vertex_histogramGenerator(constant float4 *pPosition[[ buffer(0) ]], 20 | constant packed_float2 *pTexCoords[[ buffer(1) ]], 21 | uint vid[[ vertex_id ]]) 22 | { 23 | VertexIO outVertices; 24 | 25 | float2 pointTexCoordinate = pTexCoords[vid]; 26 | 27 | outVertices.position = pPosition[vid]; 28 | outVertices.textureCoordinate = float2(pointTexCoordinate.x, 0.5); 29 | outVertices.height = 1.0 - pointTexCoordinate.y; 30 | 31 | return outVertices; 32 | } 33 | 34 | fragment half4 fragment_histogramGenerator(VertexIO inFrag [[ stage_in ]], 35 | texture2d tex2D [[ texture(0) ]], 36 | constant float4 &backgroundColor [[ buffer(0) ]]) 37 | { 38 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 39 | 40 | half4 colorChannels = tex2D.sample(quadSampler, inFrag.textureCoordinate); 41 | half4 heightTest = half4(step(half(inFrag.height), colorChannels.rgb), 1.0h); 42 | 43 | return mix(half4(backgroundColor), heightTest, heightTest.r + heightTest.g + heightTest.b); 44 | } 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHueFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHueFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/7/22. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIHueFilter : MetalImageFilter { 14 | GLint hueAdjustUniform; 15 | } 16 | 17 | @property (nonatomic, readwrite) CGFloat hue; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIHueFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIHueFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/7/22. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIHueFilter.h" 10 | #import "MetalImageContext.h" 11 | #import "MetalDevice.h" 12 | 13 | @interface MIHueFilter() 14 | 15 | @property (nonatomic, strong) id buffer; 16 | 17 | @end 18 | 19 | @implementation MIHueFilter 20 | 21 | - (instancetype)init { 22 | if (self = [super initWithFragmentFunctionName:@"fragment_hue"]) { 23 | id device = [MetalDevice sharedMTLDevice]; 24 | _buffer = [device newBufferWithLength:sizeof(MTLFloat) options:MTLResourceOptionCPUCacheModeDefault]; 25 | self.hue = 90; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)setHue:(CGFloat)newHue 31 | { 32 | // Convert degrees to radians for hue rotation 33 | _hue = fmodf(newHue, 360.0f) * M_PI/180.0f; 34 | MTLFloat *bufferContents = (MTLFloat *)[_buffer contents]; 35 | bufferContents[0] = _hue; 36 | } 37 | 38 | - (void)assembleRenderEncoder:(id)renderEncoder { 39 | [renderEncoder setDepthStencilState:_depthStencilState]; 40 | [renderEncoder setRenderPipelineState:_pipelineState]; 41 | [renderEncoder setVertexBuffer:_verticsBuffer offset:0 atIndex:0]; 42 | [renderEncoder setVertexBuffer:_coordBuffer offset:0 atIndex:1]; 43 | [renderEncoder setFragmentTexture:[firstInputTexture texture] atIndex:0]; 44 | [renderEncoder setFragmentBuffer:_buffer offset:0 atIndex:0]; 45 | [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:MetalImageDefaultRenderVetexCount instanceCount:1]; 46 | [renderEncoder endEncoding]; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MILookupFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILookupFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/8/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MILookupFilter : MetalImageTwoInputFilter 14 | 15 | // How To Use: 16 | // 1) Use your favourite photo editing application to apply a filter to lookup.png from GPUImage/framework/Resources. 17 | // For this to work properly each pixel color must not depend on other pixels (e.g. blur will not work). 18 | // If you need more complex filter you can create as many lookup tables as required. 19 | // E.g. color_balance_lookup_1.png -> GPUImageGaussianBlurFilter -> color_balance_lookup_2.png 20 | // 2) Use you new lookup.png file as a second input for GPUImageLookupFilter. 21 | 22 | // See GPUImageAmatorkaFilter, GPUImageMissEtikateFilter, and GPUImageSoftEleganceFilter for example. 23 | 24 | // Additional Info: 25 | // Lookup texture is organised as 8x8 quads of 64x64 pixels representing all possible RGB colors: 26 | //for (int by = 0; by < 8; by++) { 27 | // for (int bx = 0; bx < 8; bx++) { 28 | // for (int g = 0; g < 64; g++) { 29 | // for (int r = 0; r < 64; r++) { 30 | // image.setPixel(r + bx * 64, g + by * 64, qRgb((int)(r * 255.0 / 63.0 + 0.5), 31 | // (int)(g * 255.0 / 63.0 + 0.5), 32 | // (int)((bx + by * 8.0) * 255.0 / 63.0 + 0.5))); 33 | // } 34 | // } 35 | // } 36 | //} 37 | 38 | // Opacity/intensity of lookup filter ranges from 0.0 to 1.0, with 1.0 as the normal setting 39 | @property(readwrite, nonatomic) MTLFloat intensity; 40 | 41 | 42 | @end 43 | 44 | NS_ASSUME_NONNULL_END 45 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MILookupFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MILookupFilter.metal 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/8/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_lookup(VertexIO inFrag [[ stage_in ]], 13 | texture2d texture1 [[ texture(0) ]], 14 | texture2d texture2 [[ texture(1) ]], 15 | constant float &intensity [[ buffer(0) ]]) 16 | { 17 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 18 | 19 | half4 textureColor = texture1.sample(quadSampler, inFrag.textureCoordinate); 20 | float blueColor = textureColor.b * 63.0; 21 | 22 | float2 quad1; 23 | quad1.y = floor(floor(blueColor) / 8.0); 24 | quad1.x = floor(blueColor) - (quad1.y * 8.0); 25 | 26 | float2 quad2; 27 | quad2.y = floor(ceil(blueColor) / 8.0); 28 | quad2.x = ceil(blueColor) - (quad2.y * 8.0); 29 | 30 | float2 texPos1; 31 | texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 32 | texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 33 | 34 | float2 texPos2; 35 | texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r); 36 | texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g); 37 | 38 | half4 newColor1 = texture2.sample(quadSampler, texPos1); 39 | half4 newColor2 = texture2.sample(quadSampler, texPos2); 40 | 41 | half4 newColor = mix(newColor1, newColor2, half(fract(blueColor))); 42 | 43 | return mix(textureColor, half4(newColor.rgb, textureColor.w), half(intensity)); 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MILuminanceRangeFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILuminanceRangeFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/8/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MILuminanceRangeFilter : MetalImageFilter 14 | 15 | /** The degree to reduce the luminance range, from 0.0 to 1.0. Default is 0.6. 16 | */ 17 | @property(readwrite, nonatomic) CGFloat rangeReductionFactor; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MILuminanceRangeFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MILuminanceRangeFilter.metal 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/8/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_luminanceRange(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float &rangeReduction [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | 18 | half4 textureColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 19 | 20 | // Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham 21 | const half3 luminanceWeighting = half3(0.2125h, 0.7154h, 0.0721h); 22 | 23 | half luminance = dot(textureColor.rgb, luminanceWeighting); 24 | half luminanceRatio = ((0.5h - luminance) * rangeReduction); 25 | 26 | return half4((textureColor.rgb) + (luminanceRatio), textureColor.w); 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MILuminanceThresholdFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILuminanceThresholdFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/27. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** Pixels with a luminance above the threshold will appear white, and those below will be black 14 | */ 15 | @interface MILuminanceThresholdFilter : MetalImageFilter 16 | 17 | /** Anything above this luminance will be white, and anything below black. Ranges from 0.0 to 1.0, with 0.5 as the default 18 | */ 19 | @property(readwrite, nonatomic) MTLFloat threshold; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MILuminanceThresholdFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MILuminanceThresholdFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/27. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_luminanceThreshold(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float &threshold [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | 18 | float4 textureColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 19 | 20 | const float3 W = float3(0.2125, 0.7154, 0.0721); 21 | 22 | float luminance = dot(textureColor.rgb, W); 23 | float thresholdResult = step(threshold, luminance); 24 | 25 | return half4(half3(thresholdResult), half(textureColor.a)); 26 | } 27 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIMonochromeFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIMonochromeFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/7/22. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIMonochromeFilter : MetalImageFilter 14 | 15 | @property (readwrite, nonatomic) CGFloat intensity; 16 | @property (readwrite, nonatomic) MTLFloat4 color; 17 | @property (nonatomic, strong) id buffer; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIMonochromeFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIMonochromeFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/7/22. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_monochrome(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float4 ¶meters [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | 18 | const half3 luminanceWeighting = half3(0.2125h, 0.7154h, 0.0721h); 19 | 20 | //desat, then apply overlay blend 21 | half4 textureColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 22 | half luminance = dot(textureColor.rgb, luminanceWeighting); 23 | 24 | half4 desat = half4(half3(luminance), 1.0h); 25 | 26 | //overlay 27 | half4 outputColor = half4((desat.r < 0.5h ? (2.0h * desat.r * half(parameters[0])) : 28 | (1.0h - 2.0h * (1.0h - desat.r) * (1.0h - half(parameters[0])))), 29 | (desat.g < 0.5h ? (2.0h * desat.g * half(parameters[1])) : 30 | (1.0h - 2.0h * (1.0h - desat.g) * (1.0h - half(parameters[1])))), 31 | (desat.b < 0.5h ? (2.0h * desat.b * half(parameters[2])) : 32 | (1.0h - 2.0h * (1.0h - desat.b) * (1.0h - half(parameters[2])))), 33 | 1.0h 34 | ); 35 | 36 | return half4(mix(textureColor.rgb, outputColor.rgb, half(parameters[3])), textureColor.a); 37 | } 38 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIOpacityFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIOpacityFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/8/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIOpacityFilter : MetalImageFilter 14 | 15 | // Opacity ranges from 0.0 to 1.0, with 1.0 as the normal setting 16 | @property(readwrite, nonatomic) MTLFloat opacity; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIOpacityFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIOpacityFilter.metal 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/8/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_opacity(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float &opacity [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | 18 | half4 source = tex2D.sample(quadSampler, inFrag.textureCoordinate); 19 | 20 | return half4(source.rgb, source.a * half(opacity)); 21 | } 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIRGBFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/8/15. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIRGBFilter : MetalImageFilter 14 | 15 | // Normalized values by which each color channel is multiplied. The range is from 0.0 up, with 1.0 as the default. 16 | @property (readwrite, nonatomic) MTLFloat red; 17 | @property (readwrite, nonatomic) MTLFloat green; 18 | @property (readwrite, nonatomic) MTLFloat blue; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIRGBFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/8/15. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_rgbAdjustment(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant packed_float3 &rgb [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | half4 inColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 18 | 19 | return half4(inColor.x * half(rgb[0]), inColor.y * half(rgb[1]), inColor.z * half(rgb[2]), inColor.a); 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MISaturationFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISaturationFilter.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MISaturationFilter : MetalImageFilter 14 | 15 | /** Saturation ranges from 0.0 (fully desaturated) to 2.0 (max saturation), with 1.0 as the normal level 16 | */ 17 | @property (nonatomic,assign) MTLFloat saturation; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MISaturationFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MISaturationFilter.m 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISaturationFilter.h" 10 | #import "MetalImageContext.h" 11 | #import "MetalDevice.h" 12 | 13 | @interface MISaturationFilter() 14 | 15 | @property (nonatomic,strong) id buffer; 16 | 17 | @end 18 | 19 | @implementation MISaturationFilter 20 | 21 | - (instancetype)init { 22 | if (self = [super initWithFragmentFunctionName:@"fragment_saturation"]) { 23 | id device = [MetalDevice sharedMTLDevice]; 24 | _buffer = [device newBufferWithLength:sizeof(MTLFloat) options:MTLResourceOptionCPUCacheModeDefault]; 25 | self.saturation = 1.0f; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)dealloc { 31 | _buffer = nil; 32 | } 33 | 34 | - (void)setSaturation:(MTLFloat)saturation { 35 | _saturation = saturation; 36 | MTLFloat *bufferContents = (MTLFloat *)[_buffer contents]; 37 | bufferContents[0] = _saturation; 38 | } 39 | 40 | - (void)assembleRenderEncoder:(id)renderEncoder { 41 | [renderEncoder setDepthStencilState:_depthStencilState]; 42 | [renderEncoder setRenderPipelineState:_pipelineState]; 43 | [renderEncoder setVertexBuffer:_verticsBuffer offset:0 atIndex:0]; 44 | [renderEncoder setVertexBuffer:_coordBuffer offset:0 atIndex:1]; 45 | [renderEncoder setFragmentTexture:[firstInputTexture texture] atIndex:0]; 46 | [renderEncoder setFragmentBuffer:_buffer offset:0 atIndex:0]; 47 | [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:MetalImageDefaultRenderVetexCount instanceCount:1]; 48 | [renderEncoder endEncoding]; 49 | } 50 | 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MISaturationFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MISaturationFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Stone Feng on 2017/8/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_saturation(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float &saturation [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | half4 inColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 18 | 19 | // Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham 20 | const half3 luminanceWeighting = half3(0.2125h, 0.7154h, 0.0721h); 21 | half luminance = dot(inColor.rgb, luminanceWeighting); 22 | half3 greyScaleColor = half3(luminance); 23 | return half4(mix(greyScaleColor, inColor.rgb, (half)saturation), inColor.a); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MISepiaFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISepiaFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/8/23. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIColorMatrixFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /// Simple sepia tone filter 14 | @interface MISepiaFilter : MIColorMatrixFilter 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MISepiaFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MISepiaFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/8/23. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISepiaFilter.h" 10 | #import "MetalImageContext.h" 11 | #import "MetalDevice.h" 12 | 13 | @implementation MISepiaFilter 14 | 15 | - (id)init; 16 | { 17 | if (!(self = [super init])) 18 | { 19 | return nil; 20 | } 21 | 22 | self.intensity = 1.0; 23 | self.colorMatrix = (MTLFloat4x4){ 24 | {0.3588, 0.7044, 0.1368, 0.0}, 25 | {0.2990, 0.5870, 0.1140, 0.0}, 26 | {0.2392, 0.4696, 0.0912 ,0.0}, 27 | {0,0,0,1.0}, 28 | }; 29 | 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MISolarizeFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISolarizeFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/2. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** Pixels with a luminance above the threshold will invert their color 14 | */ 15 | @interface MISolarizeFilter : MetalImageFilter 16 | 17 | /** Anything above this luminance will be inverted, and anything below normal. Ranges from 0.0 to 1.0, with 0.5 as the default 18 | */ 19 | @property(readwrite, nonatomic) CGFloat threshold; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MISolarizeFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MISolarizeFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/2. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISolarizeFilter.h" 10 | #import "MetalImageContext.h" 11 | #import "MetalDevice.h" 12 | 13 | @interface MISolarizeFilter() 14 | 15 | @property (nonatomic, strong) id buffer; 16 | 17 | @end 18 | 19 | @implementation MISolarizeFilter 20 | 21 | - (id)init 22 | { 23 | if (!(self = [super initWithFragmentFunctionName:@"fragment_solarize"])) 24 | { 25 | return nil; 26 | } 27 | 28 | id device = [MetalDevice sharedMTLDevice]; 29 | _buffer = [device newBufferWithLength:sizeof(MTLFloat)*2 options:MTLResourceOptionCPUCacheModeDefault]; 30 | 31 | self.threshold = 0.5; 32 | 33 | return self; 34 | } 35 | 36 | - (void)setThreshold:(CGFloat)threshold { 37 | _threshold = threshold; 38 | 39 | MTLFloat *bufferContents = (MTLFloat *)[_buffer contents]; 40 | bufferContents[0] = _threshold; 41 | } 42 | 43 | - (void)assembleRenderEncoder:(id)renderEncoder { 44 | [renderEncoder setDepthStencilState:_depthStencilState]; 45 | [renderEncoder setRenderPipelineState:_pipelineState]; 46 | [renderEncoder setVertexBuffer:_verticsBuffer offset:0 atIndex:0]; 47 | [renderEncoder setVertexBuffer:_coordBuffer offset:0 atIndex:1]; 48 | [renderEncoder setFragmentTexture:[firstInputTexture texture] atIndex:0]; 49 | [renderEncoder setFragmentBuffer:_buffer offset:0 atIndex:0]; 50 | [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:MetalImageDefaultRenderVetexCount instanceCount:1]; 51 | [renderEncoder endEncoding]; 52 | } 53 | 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MISolarizeFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MISolarizeFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/2. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | #include 11 | 12 | using namespace metal; 13 | 14 | fragment half4 fragment_solarize(VertexIO inFrag [[ stage_in ]], 15 | texture2d tex2D [[ texture(0) ]], 16 | constant float &threshold [[ buffer(0) ]]) 17 | { 18 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 19 | 20 | float4 textureColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 21 | const float3 W = float3(0.2125, 0.7154, 0.0721); 22 | float luminance = dot(textureColor.rgb, W); 23 | float thresholdResult = step(luminance, threshold); 24 | float3 finalColor = abs(thresholdResult - textureColor.rgb); 25 | 26 | return half4(half3(finalColor), half(textureColor.a)); 27 | } 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Color/MIWhiteBalanceFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIWhiteBalanceFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/7/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | /** 12 | * Created by Alaric Cole 13 | * Allows adjustment of color temperature in terms of what an image was effectively shot in. 14 | * This means higher Kelvin values will warm the image, while lower values will cool it. 15 | 16 | */ 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | @interface MIWhiteBalanceFilter : MetalImageFilter 21 | 22 | //choose color temperature, in degrees Kelvin 23 | @property(readwrite, nonatomic) CGFloat temperature; 24 | 25 | //adjust tint to compensate 26 | @property(readwrite, nonatomic) CGFloat tint; 27 | 28 | @end 29 | 30 | NS_ASSUME_NONNULL_END 31 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIBulgeDistortionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIBulgeDistortionFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /// Creates a bulge distortion on the image 14 | @interface MIBulgeDistortionFilter : MetalImageFilter 15 | 16 | /// The center about which to apply the distortion, with a default of (0.5, 0.5) 17 | @property(readwrite, nonatomic) MTLFloat2 center; 18 | /// The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25 19 | @property(readwrite, nonatomic) MTLFloat radius; 20 | /// The amount of distortion to apply, from -1.0 to 1.0, with a default of 0.5 21 | @property(readwrite, nonatomic) MTLFloat scale; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MICGAColorspaceFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MICGAColorspaceFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MICGAColorspaceFilter : MetalImageFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MICGAColorspaceFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MICGAColorspaceFilter.m 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MICGAColorspaceFilter.h" 10 | 11 | @implementation MICGAColorspaceFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_cgaColorspace"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MICrosshatchFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MICrosshatchFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MICrosshatchFilter : MetalImageFilter 14 | 15 | // The fractional width of the image to use as the spacing for the crosshatch. The default is 0.03. 16 | @property(readwrite, nonatomic) MTLFloat crossHatchSpacing; 17 | 18 | // A relative width for the crosshatch lines. The default is 0.003. 19 | @property(readwrite, nonatomic) MTLFloat lineWidth; 20 | 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIGlassSphereFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIGlassSphereFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/12. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISphereRefractionFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIGlassSphereFilter : MISphereRefractionFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIGlassSphereFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIGlassSphereFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/12. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIGlassSphereFilter.h" 10 | 11 | @implementation MIGlassSphereFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super initWithFragmentFunctionName:@"fragment_GlassSphereFilter"])) 16 | { 17 | return nil; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIHalftoneFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHalftoneFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/13. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIPixellateFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIHalftoneFilter : MIPixellateFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIHalftoneFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIHalftoneFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/13. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIHalftoneFilter.h" 10 | #import "MetalDevice.h" 11 | 12 | @implementation MIHalftoneFilter 13 | 14 | - (id)init 15 | { 16 | if (!(self = [super initWithFragmentFunctionName:@"fragment_HalftoneFilter"])) 17 | { 18 | return nil; 19 | } 20 | 21 | id device = [MetalDevice sharedMTLDevice]; 22 | self.buffer = [device newBufferWithLength:sizeof(MTLFloat)*2 options:MTLResourceOptionCPUCacheModeDefault]; 23 | 24 | self.fractionalWidthOfAPixel = 0.01; 25 | 26 | return self; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIJFAVoronoiFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIJFAVoronoiFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/12. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIJFAVoronoiFilter : MetalImageFilter 14 | 15 | @property (nonatomic, readwrite) MTLUInt2 sizeInPixels; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIKuwaharaFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIKuwaharaFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/12. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | /** Kuwahara image abstraction, drawn from the work of Kyprianidis, et. al. in their publication "Anisotropic Kuwahara Filtering on the GPU" within the GPU Pro collection. This produces an oil-painting-like image, but it is extremely computationally expensive, so it can take seconds to render a frame on an iPad 2. This might be best used for still images. 13 | */ 14 | @interface MIKuwaharaFilter : MetalImageFilter 15 | 16 | /// The radius to sample from when creating the brush-stroke effect, with a default of 3. The larger the radius, the slower the filter. 17 | @property(readwrite, nonatomic) NSUInteger radius; 18 | 19 | @end 20 | 21 | NS_ASSUME_NONNULL_END 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIKuwaharaRadius3Filter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIKuwaharaRadius3Filter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/12. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIKuwaharaRadius3Filter : MetalImageFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIMosaicFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIMosaicFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/13. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MetalImageTwoInputFilter.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface MIMosaicFilter : MetalImageTwoInputFilter 15 | 16 | // This filter takes an input tileset, the tiles must ascend in luminance 17 | // It looks at the input image and replaces each display tile with an input tile 18 | // according to the luminance of that tile. The idea was to replicate the ASCII 19 | // video filters seen in other apps, but the tileset can be anything. 20 | @property(readwrite, nonatomic) MTLFloat2 inputTileSize; 21 | @property(readwrite, nonatomic) MTLFloat2 displayTileSize; 22 | @property(readwrite, nonatomic) float numTiles; 23 | @property(readwrite, nonatomic) BOOL colorOn; 24 | 25 | - (void)setTileSetImage:(UIImage *)tileSetImage; 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIPerlinNoiseFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIPerlinNoiseFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIPerlinNoiseFilter : MetalImageFilter 14 | 15 | @property (readwrite, nonatomic) MTLFloat4 colorStart; 16 | @property (readwrite, nonatomic) MTLFloat4 colorFinish; 17 | 18 | @property (readwrite, nonatomic) MTLFloat scale; 19 | 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIPinchDistortionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIPinchDistortionFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | /** Creates a pinch distortion of the image 13 | */ 14 | @interface MIPinchDistortionFilter : MetalImageFilter 15 | 16 | /** The center about which to apply the distortion, with a default of (0.5, 0.5) 17 | */ 18 | @property(readwrite, nonatomic) MTLFloat2 center; 19 | /** The radius of the distortion, ranging from 0.0 to 2.0, with a default of 1.0 20 | */ 21 | @property(readwrite, nonatomic) MTLFloat radius; 22 | /** The amount of distortion to apply, from -2.0 to 2.0, with a default of 0.5 23 | */ 24 | @property(readwrite, nonatomic) MTLFloat scale; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIPixellateFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIPixellateFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/13. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIPixellateFilter : MetalImageFilter 14 | 15 | // The fractional width of the image to use as a size for the pixels in the resulting image. 16 | // Values below one pixel width in the source image are ignored. 17 | @property(readwrite, nonatomic) MTLFloat fractionalWidthOfAPixel; 18 | 19 | @property (readwrite, nonatomic) id buffer; 20 | @property (readwrite, nonatomic) MTLFloat aspectRatio; 21 | - (void)adjustAspectRatio; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIPolarPixellateFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIPolarPixellateFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIPolarPixellateFilter : MetalImageFilter 14 | 15 | // The center about which to apply the distortion, with a default of (0.5, 0.5) 16 | @property(readwrite, nonatomic) MTLFloat2 center; 17 | // The amount of distortion to apply, from (-2.0, -2.0) to (2.0, 2.0), with a default of (0.05, 0.05) 18 | @property(readwrite, nonatomic) MTLFloat2 pixelSize; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIPolarPixellateFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIPolarPixellateFilter.metal 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | typedef struct { 13 | float2 pixelSize; 14 | float2 center; 15 | }PolarPixellateParameters; 16 | 17 | // @fattjake based on vid by toneburst 18 | 19 | fragment half4 fragment_polarPixellate(VertexIO inFrag [[ stage_in ]], 20 | texture2d tex2D [[ texture(0) ]], 21 | constant PolarPixellateParameters ¶meters [[ buffer(0) ]]) 22 | { 23 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 24 | 25 | float2 normCoord = 2.0 * inFrag.textureCoordinate - 1.0; 26 | float2 normCenter = 2.0 * parameters.center - 1.0; 27 | 28 | normCoord -= normCenter; 29 | 30 | float r = length(normCoord); // to polar coords 31 | float phi = atan2(normCoord.y, normCoord.x); // to polar coords 32 | 33 | r = r - fmod(r, parameters.pixelSize.x) + 0.03; 34 | phi = phi - fmod(phi, parameters.pixelSize.y); 35 | 36 | normCoord.x = r * cos(phi); 37 | normCoord.y = r * sin(phi); 38 | 39 | normCoord += normCenter; 40 | 41 | float2 textureCoordinateToUse = normCoord / 2.0 + 0.5; 42 | 43 | return tex2D.sample(quadSampler, textureCoordinateToUse); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIPolkaDotFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIPolkaDotFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/13. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIPixellateFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIPolkaDotFilter : MIPixellateFilter 14 | 15 | @property(readwrite, nonatomic) MTLFloat dotScaling; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIPolkaDotFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIPolkaDotFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/13. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIPolkaDotFilter.h" 10 | #import "MetalDevice.h" 11 | 12 | @implementation MIPolkaDotFilter 13 | 14 | - (id)init 15 | { 16 | if (!(self = [super initWithFragmentFunctionName:@"fragment_PolkaDotFilter"])) 17 | { 18 | return nil; 19 | } 20 | 21 | id device = [MetalDevice sharedMTLDevice]; 22 | self.buffer = [device newBufferWithLength:sizeof(MTLFloat)*3 options:MTLResourceOptionCPUCacheModeDefault]; 23 | 24 | self.fractionalWidthOfAPixel = 0.05; 25 | self.dotScaling = 0.90; 26 | 27 | return self; 28 | } 29 | 30 | #pragma mark - 31 | #pragma mark Accessors 32 | 33 | - (void)setDotScaling:(MTLFloat)newValue; 34 | { 35 | _dotScaling = newValue; 36 | 37 | MTLFloat *bufferContents = (MTLFloat *)[self.buffer contents]; 38 | bufferContents[2] = _dotScaling; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIPosterizeFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIPosterizeFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | /** This reduces the color dynamic range into the number of steps specified, leading to a cartoon-like simple shading of the image. 13 | */ 14 | 15 | @interface MIPosterizeFilter : MetalImageFilter 16 | 17 | /** The number of color levels to reduce the image space to. This ranges from 1 to 256, with a default of 10. 18 | */ 19 | @property(readwrite, nonatomic) MTLUInt colorLevels; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIPosterizeFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIPosterizeFilter.metal 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | fragment half4 fragment_posterize(VertexIO inFrag [[ stage_in ]], 13 | texture2d tex2D [[ texture(0) ]], 14 | constant float &colorLevels [[ buffer(0) ]]) 15 | { 16 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 17 | 18 | half4 textureColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 19 | 20 | return floor((textureColor * colorLevels) + half4(0.5)) / colorLevels;; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MISphereRefractionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISphereRefractionFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MISphereRefractionFilter : MetalImageFilter 14 | 15 | /// The center about which to apply the distortion, with a default of (0.5, 0.5) 16 | @property(readwrite, nonatomic) MTLFloat2 center; 17 | /// The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25 18 | @property(readwrite, nonatomic) MTLFloat radius; 19 | /// The index of refraction for the sphere, with a default of 0.71 20 | @property(readwrite, nonatomic) MTLFloat refractiveIndex; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIStretchDistortionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIStretchDistortionFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** Creates a stretch distortion of the image 14 | */ 15 | @interface MIStretchDistortionFilter : MetalImageFilter 16 | 17 | /** The center about which to apply the distortion, with a default of (0.5, 0.5) 18 | */ 19 | @property(readwrite, nonatomic) MTLFloat2 center; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MISwirlFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISwirlFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** Creates a swirl distortion on the image 14 | */ 15 | @interface MISwirlFilter : MetalImageFilter 16 | 17 | /// The center about which to apply the distortion, with a default of (0.5, 0.5) 18 | @property(readwrite, nonatomic) MTLFloat2 center; 19 | /// The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.5 20 | @property(readwrite, nonatomic) MTLFloat radius; 21 | /// The amount of distortion to apply, with a minimum of 0.0 and a default of 1.0 22 | @property(readwrite, nonatomic) MTLFloat angle; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MISwirlFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MISwirlFilter.metal 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | typedef struct { 13 | packed_float2 center; 14 | float radius; 15 | float angle; 16 | }SwirlParameters; 17 | 18 | fragment half4 fragment_swirlFilter(VertexIO inFrag [[ stage_in ]], 19 | texture2d tex2D [[ texture(0) ]], 20 | constant SwirlParameters ¶meters [[ buffer(0) ]]) 21 | { 22 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 23 | 24 | float2 textureCoordinateToUse = inFrag.textureCoordinate; 25 | float dist = distance((float2)parameters.center, textureCoordinateToUse); 26 | 27 | if (dist < parameters.radius) 28 | { 29 | textureCoordinateToUse -= parameters.center; 30 | float percent = (parameters.radius - dist) / parameters.radius; 31 | float theta = percent * percent * parameters.angle * 8.0; 32 | float s = sin(theta); 33 | float c = cos(theta); 34 | textureCoordinateToUse = float2(dot(textureCoordinateToUse, float2(c, -s)), dot(textureCoordinateToUse, float2(s, c))); 35 | textureCoordinateToUse += parameters.center; 36 | } 37 | 38 | return tex2D.sample(quadSampler, textureCoordinateToUse); 39 | } 40 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIVignetteFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIVignetteFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/12. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** Performs a vignetting effect, fading out the image at the edges 14 | */ 15 | @interface MIVignetteFilter : MetalImageFilter 16 | 17 | // the center for the vignette in tex coords (defaults to 0.5, 0.5) 18 | @property (nonatomic, readwrite) MTLFloat2 vignetteCenter; 19 | 20 | // The color to use for the Vignette (defaults to black) 21 | @property (nonatomic, readwrite) MTLFloat3 vignetteColor; 22 | 23 | // The normalized distance from the center where the vignette effect starts. Default of 0.5. 24 | @property (nonatomic, readwrite) MTLFloat vignetteStart; 25 | 26 | // The normalized distance from the center where the vignette effect ends. Default of 0.75. 27 | @property (nonatomic, readwrite) MTLFloat vignetteEnd; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIVignetteFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIVignetteFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/12. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | typedef struct { 13 | packed_float2 vignetteCenter; 14 | packed_float3 vignetteColor; 15 | float vignetteStart; 16 | float vignetteEnd; 17 | }VignetteParameters; 18 | 19 | fragment half4 fragment_VignetteFilter(VertexIO inFrag [[ stage_in ]], 20 | texture2d tex2D [[ texture(0) ]], 21 | constant VignetteParameters ¶meters [[ buffer(0) ]]) 22 | { 23 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 24 | 25 | half4 sourceImageColor = tex2D.sample(quadSampler, inFrag.textureCoordinate); 26 | half d = distance(inFrag.textureCoordinate, float2(parameters.vignetteCenter)); 27 | half percent = smoothstep(half(parameters.vignetteStart), half(parameters.vignetteEnd), d); 28 | return half4(mix(sourceImageColor.rgb, half3(parameters.vignetteColor), percent), sourceImageColor.a); 29 | } 30 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Effects/MIVoronoiConsumerFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIVoronoiConsumerFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/12. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIVoronoiConsumerFilter : MetalImageTwoInputFilter 14 | 15 | @property (nonatomic, readwrite) MTLUInt2 sizeInPixels; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MI3x3ConvolutionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MI3x3ConvolutionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/18. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MI3x3TextureSamplingFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | /** Runs a 3x3 convolution kernel against the image 13 | */ 14 | @interface MI3x3ConvolutionFilter : MI3x3TextureSamplingFilter 15 | 16 | /** Convolution kernel to run against the image 17 | 18 | The convolution kernel is a 3x3 matrix of values to apply to the pixel and its 8 surrounding pixels. 19 | The matrix is specified in row-major order, with the top left pixel being one.one and the bottom right three.three 20 | If the values in the matrix don't add up to 1.0, the image could be brightened or darkened. 21 | */ 22 | @property(readwrite, nonatomic) MTLFloat3x3 convolutionKernel; 23 | 24 | @property (nonatomic, strong) id buffer; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIBilateralFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIBilateralFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2020/6/23. 6 | // Copyright © 2020 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | #import "MITwoPassTextureSamplingFilter.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface MIBilateralFilter : MITwoPassTextureSamplingFilter 15 | 16 | /** A radius in pixels to use for the smoothing, with a default of 2.0, 17 | * The calculation will acting with a gaussian kernel in the size of 18 | * 2 * radius + 1 . 19 | * 20 | * This adjusts the sigma variable in the Gaussian distribution function. 21 | */ 22 | @property (readwrite, nonatomic) unsigned int radius; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIClosingFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIClosingFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilterGroup.h" 10 | 11 | @class MIErosionFilter; 12 | @class MIDilationFilter; 13 | 14 | // A filter that first performs a dilation on the red channel of an image, followed by an erosion of the same radius. 15 | // This helps to filter out smaller dark elements. 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface MIClosingFilter : MetalImageFilterGroup 20 | { 21 | MIErosionFilter *erosionFilter; 22 | MIDilationFilter *dilationFilter; 23 | } 24 | 25 | @property(readwrite, nonatomic) MTLFloat verticalTexelSpacing, horizontalTexelSpacing; 26 | 27 | - (instancetype)initWithRadius:(MTLUInt)radius; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIClosingFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIClosingFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIClosingFilter.h" 10 | #import "MIDilationFilter.h" 11 | #import "MIErosionFilter.h" 12 | 13 | @implementation MIClosingFilter 14 | 15 | - (instancetype)init { 16 | return [self initWithRadius:1]; 17 | } 18 | 19 | - (instancetype)initWithRadius:(MTLUInt)radius { 20 | 21 | if (self = [super init]) { 22 | // First pass: dilation 23 | dilationFilter = [[MIDilationFilter alloc] initWithRadius:radius]; 24 | [self addFilter:dilationFilter]; 25 | 26 | // Second pass: erosion 27 | erosionFilter = [[MIErosionFilter alloc] initWithRadius:radius]; 28 | [self addFilter:erosionFilter]; 29 | 30 | [dilationFilter addTarget:erosionFilter]; 31 | 32 | self.initialFilters = [NSArray arrayWithObjects:dilationFilter, nil]; 33 | self.terminalFilter = erosionFilter; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void)setVerticalTexelSpacing:(MTLFloat)newValue; 40 | { 41 | _verticalTexelSpacing = newValue; 42 | erosionFilter.verticalTexelSpacing = newValue; 43 | dilationFilter.verticalTexelSpacing = newValue; 44 | } 45 | 46 | - (void)setHorizontalTexelSpacing:(MTLFloat)newValue; 47 | { 48 | _horizontalTexelSpacing = newValue; 49 | erosionFilter.horizontalTexelSpacing = newValue; 50 | dilationFilter.horizontalTexelSpacing = newValue; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIColorLocalBinaryPatternFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorLocalBinaryPatternFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/12/5. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MI3x3TextureSamplingFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIColorLocalBinaryPatternFilter : MI3x3TextureSamplingFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIColorLocalBinaryPatternFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorLocalBinaryPatternFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/12/5. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIColorLocalBinaryPatternFilter.h" 10 | 11 | @implementation MIColorLocalBinaryPatternFilter 12 | 13 | - (instancetype)init { 14 | if (self = [super initWithFragmentFunctionName:@"fragment_ColorLocalBinaryPatternFilter"]) { 15 | 16 | } 17 | 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIColorPackingFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIColorPackingFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIColorPackingFilter : MetalImageFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MICropFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MICropFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/13. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MICropFilter : MetalImageFilter { 14 | @protected 15 | MTLFloat2 cropTextureCoordinates[4]; 16 | } 17 | 18 | // The crop region is the rectangle within the image to crop. It is normalized to a coordinate space from 0.0 to 1.0, with 0.0, 0.0 being the upper left corner of the image 19 | @property(readwrite, nonatomic) CGRect cropRegion; 20 | 21 | // Initialization and teardown 22 | - (id)initWithCropRegion:(CGRect)newCropRegion; 23 | 24 | - (void)setTextureCropCoordinates:(MTLFloat2[_Nonnull 4])coordinates; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MICrosshairGenerator.h: -------------------------------------------------------------------------------- 1 | // 2 | // MICrosshairGenerator.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MICrosshairGenerator : MetalImageFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MICrosshairGenerator.m: -------------------------------------------------------------------------------- 1 | // 2 | // MICrosshairGenerator.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MICrosshairGenerator.h" 10 | 11 | @implementation MICrosshairGenerator 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIDilationFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIDilationFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MITwoPassTextureSamplingFilter.h" 10 | 11 | // For each pixel, this sets it to the maximum value of the red channel in a rectangular neighborhood extending out dilationRadius pixels from the center. 12 | // This extends out bright features, and is most commonly used with black-and-white thresholded images. 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface MIDilationFilter : MITwoPassTextureSamplingFilter 17 | 18 | // Acceptable values for dilationRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4. 19 | - (instancetype)initWithRadius:(MTLUInt)dilationRadius; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIDilationFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIDilationFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIDilationFilter.h" 10 | 11 | @implementation MIDilationFilter 12 | 13 | - (instancetype)init { 14 | return [self initWithRadius:1]; 15 | } 16 | 17 | - (instancetype)initWithRadius:(MTLUInt)dilationRadius { 18 | 19 | MTLUInt supportedDilationRadius = MAX(MIN(dilationRadius, 4), 1); 20 | NSString *vertexFunctionName = [NSString stringWithFormat:@"vertex_DilationFilterRadius%d", supportedDilationRadius]; 21 | NSString *fragmentFunctionName = [NSString stringWithFormat:@"fragment_DilationFilterRadius%d", supportedDilationRadius]; 22 | 23 | self = [super initWithFirstStageVertexFunctionName:vertexFunctionName 24 | firstStageFragmentFunctionName:fragmentFunctionName 25 | secondStageVertexFunctionName:vertexFunctionName 26 | secondStageFragmentFunctionName:fragmentFunctionName]; 27 | if (self) 28 | { 29 | } 30 | 31 | return self; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIDirectionalNonMaximumSuppressionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIDirectionalNonMaximumSuppressionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIDirectionalNonMaximumSuppressionFilter : MetalImageFilter 14 | 15 | // The texel width and height determines how far out to sample from this texel. 16 | // By default, this is the normalized width of a pixel, but this can be overridden for different effects. 17 | @property (readwrite, nonatomic) MTLFloat2 texelSize; 18 | 19 | // These thresholds set cutoffs for the intensities that definitely get registered (upper threshold) and those that definitely don't (lower threshold) 20 | @property(readwrite, nonatomic) MTLFloat upperThreshold; 21 | @property(readwrite, nonatomic) MTLFloat lowerThreshold; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIDirectionalSobelEdgeDetectionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIDirectionalSobelEdgeDetectionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MI3x3TextureSamplingFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIDirectionalSobelEdgeDetectionFilter : MI3x3TextureSamplingFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIDirectionalSobelEdgeDetectionFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIDirectionalSobelEdgeDetectionFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIDirectionalSobelEdgeDetectionFilter.h" 10 | 11 | @implementation MIDirectionalSobelEdgeDetectionFilter 12 | 13 | - (instancetype)init { 14 | if (self = [super initWithFragmentFunctionName:@"fragment_DirectionalSobelEdgeDetectionFilter"]) { 15 | 16 | } 17 | 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIErosionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIErosionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MITwoPassTextureSamplingFilter.h" 10 | 11 | // For each pixel, this sets it to the minimum value of the red channel in a rectangular neighborhood extending out dilationRadius pixels from the center. 12 | // This extends out dark features, and is most commonly used with black-and-white thresholded images. 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface MIErosionFilter : MITwoPassTextureSamplingFilter 17 | 18 | // Acceptable values for erosionRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4. 19 | - (id)initWithRadius:(MTLUInt)erosionRadius; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIErosionFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIErosionFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIErosionFilter.h" 10 | 11 | @implementation MIErosionFilter 12 | 13 | - (instancetype)init { 14 | return [self initWithRadius:1]; 15 | } 16 | 17 | - (instancetype)initWithRadius:(MTLUInt)dilationRadius { 18 | 19 | MTLUInt supportedDilationRadius = MAX(MIN(dilationRadius, 4), 1); 20 | NSString *vertexFunctionName = [NSString stringWithFormat:@"vertex_DilationFilterRadius%d", supportedDilationRadius]; 21 | NSString *fragmentFunctionName = [NSString stringWithFormat:@"fragment_ErosionFilterRadius%d", supportedDilationRadius]; 22 | if (self = [super initWithFirstStageVertexFunctionName:vertexFunctionName 23 | firstStageFragmentFunctionName:fragmentFunctionName 24 | secondStageVertexFunctionName:vertexFunctionName 25 | secondStageFragmentFunctionName:fragmentFunctionName]) 26 | { 27 | 28 | } 29 | 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIFASTCornerDetectionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIFASTCornerDetectionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilterGroup.h" 10 | #import "MIGrayscaleFilter.h" 11 | #import "MI3x3TextureSamplingFilter.h" 12 | #import "MINonMaximumSuppressionFilter.h" 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | /* 16 | An implementation of the Features from Accelerated Segment Test (FAST) feature detector as described in the following publications: 17 | 18 | E. Rosten and T. Drummond. Fusing points and lines for high performance tracking. IEEE International Conference on Computer Vision, 2005. 19 | E. Rosten and T. Drummond. Machine learning for high-speed corner detection. European Conference on Computer Vision, 2006. 20 | 21 | For more about the FAST feature detector, see the resources here: 22 | http://www.edwardrosten.com/work/fast.html 23 | */ 24 | 25 | @interface MIFASTCornerDetectionFilter : MetalImageFilterGroup { 26 | MIGrayscaleFilter *luminanceReductionFilter; 27 | MI3x3TextureSamplingFilter *featureDetectionFilter; 28 | MINonMaximumSuppressionFilter *nonMaximumSuppressionFilter; 29 | // Generate a lookup texture based on the bit patterns 30 | 31 | // Step 1: convert to monochrome if necessary 32 | // Step 2: do a lookup at each pixel based on the Bresenham circle, encode comparison in two color components 33 | // Step 3: do non-maximum suppression of close corner points 34 | } 35 | 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIFASTCornerDetectionFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIFASTCornerDetectionFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIFASTCornerDetectionFilter.h" 10 | 11 | @implementation MIFASTCornerDetectionFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super init])) 16 | { 17 | return nil; 18 | } 19 | 20 | // [derivativeFilter addTarget:blurFilter]; 21 | // [blurFilter addTarget:harrisCornerDetectionFilter]; 22 | // [harrisCornerDetectionFilter addTarget:nonMaximumSuppressionFilter]; 23 | // [simpleThresholdFilter addTarget:colorPackingFilter]; 24 | // 25 | // self.initialFilters = [NSArray arrayWithObjects:derivativeFilter, nil]; 26 | // self.terminalFilter = colorPackingFilter; 27 | // self.terminalFilter = nonMaximumSuppressionFilter; 28 | 29 | return self; 30 | } 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIGaussianBlurFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIGaussianBlurFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/2. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MITwoPassTextureSamplingFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** A Gaussian blur filter 14 | * Interpolated optimization based on Daniel Rákos' work at 15 | * http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/ 16 | * 17 | * NOTE: This approaching calculation is separated, for performance, 18 | * to two rendering passes by vertical and horizontal calculation. 19 | * 20 | */ 21 | @interface MIGaussianBlurFilter : MITwoPassTextureSamplingFilter 22 | { 23 | id _gaussianKernelBuffer; 24 | id _radiusBuffer; 25 | } 26 | 27 | /** A radius in pixels to use for the blur, with a default of 2.0, 28 | * The calculation will acting with a gaussian kernel in the size of 29 | * 2 * radius + 1 . 30 | * 31 | * This adjusts the sigma variable in the Gaussian distribution function. 32 | */ 33 | @property (readwrite, nonatomic) unsigned int radius; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIGaussianBlurFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MIGaussianBlurFilter.metal 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2019/11/7. 6 | // Copyright © 2019 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | #include 11 | #include 12 | 13 | using namespace metal; 14 | 15 | fragment half4 fragment_GaussianFilter(VertexIOWithSteps inFrag [[ stage_in ]], 16 | texture2d tex2D [[ texture(0) ]], 17 | constant int &radius [[ buffer(0) ]], 18 | constant float *weights [[ buffer(1) ]]) 19 | { 20 | constexpr sampler quadSampler(coord::normalized, filter::linear, address::clamp_to_edge); 21 | 22 | half3 sum = half3(0.0h); 23 | sum += tex2D.sample(quadSampler, inFrag.textureCoordinate).rgb * weights[0]; 24 | for (int i = 1; i < radius; i++) { 25 | sum += tex2D.sample(quadSampler, inFrag.textureCoordinate - inFrag.texelSteps * i).rgb * weights[i]; 26 | sum += tex2D.sample(quadSampler, inFrag.textureCoordinate + inFrag.texelSteps * i).rgb * weights[i]; 27 | } 28 | 29 | return half4(sum, 1.0h); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIGuidedFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIGuidedFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2019/11/7. 6 | // Copyright © 2019 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIGuidedFilter : MetalImageFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIGuidedFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIGuidedFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2019/11/7. 6 | // Copyright © 2019 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIGuidedFilter.h" 10 | 11 | @implementation MIGuidedFilter 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIHighPassFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIHighPassFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/12/5. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilterGroup.h" 10 | #import "MILowPassFilter.h" 11 | #import "MIDifferenceBlendFilter.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface MIHighPassFilter : MetalImageFilterGroup 16 | { 17 | @protected 18 | MILowPassFilter *lowPassFilter; 19 | MIDifferenceBlendFilter *differenceBlendFilter; 20 | } 21 | 22 | // This controls the degree by which the previous accumulated frames are blended and then subtracted from the current one. This ranges from 0.0 to 1.0, with a default of 0.5. 23 | @property(readwrite, nonatomic) MTLFloat filterStrength; 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIHighPassFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIHighPassFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/12/5. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIHighPassFilter.h" 10 | 11 | @implementation MIHighPassFilter 12 | 13 | - (id)init 14 | { 15 | if (!(self = [super init])) 16 | { 17 | return nil; 18 | } 19 | 20 | // Start with a low pass filter to define the component to be removed 21 | lowPassFilter = [[MILowPassFilter alloc] init]; 22 | [self addFilter:lowPassFilter]; 23 | 24 | // Take the difference of the current frame from the low pass filtered result to get the high pass 25 | differenceBlendFilter = [[MIDifferenceBlendFilter alloc] init]; 26 | [self addFilter:differenceBlendFilter]; 27 | 28 | // Texture location 0 needs to be the original image for the difference blend 29 | [lowPassFilter addTarget:differenceBlendFilter atTextureLocation:1]; 30 | 31 | self.initialFilters = [NSArray arrayWithObjects:lowPassFilter, differenceBlendFilter, nil]; 32 | self.terminalFilter = differenceBlendFilter; 33 | 34 | self.filterStrength = 0.5; 35 | 36 | return self; 37 | } 38 | 39 | #pragma mark - 40 | #pragma mark Accessors 41 | 42 | - (void)setFilterStrength:(MTLFloat)newValue; 43 | { 44 | lowPassFilter.filterStrength = newValue; 45 | } 46 | 47 | - (MTLFloat)filterStrength; 48 | { 49 | return lowPassFilter.filterStrength; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MILanczosResamplingFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILanczosResamplingFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/12/5. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MITwoPassTextureSamplingFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MILanczosResamplingFilter : MITwoPassTextureSamplingFilter { 14 | 15 | @protected 16 | BOOL fixedOriginalImageSize; 17 | } 18 | 19 | @property (nonatomic, assign) MTLUInt2 originalImageSize; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MILaplacianFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILaplacianFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/18. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MI3x3ConvolutionFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MILaplacianFilter : MI3x3ConvolutionFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MILaplacianFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MILaplacianFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/18. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MILaplacianFilter.h" 10 | #import "MetalDevice.h" 11 | 12 | @implementation MILaplacianFilter 13 | 14 | - (id)init 15 | { 16 | if (!(self = [super initWithFragmentFunctionName:@"fragment_LaplacianFilter"])) 17 | { 18 | return nil; 19 | } 20 | 21 | id device = [MetalDevice sharedMTLDevice]; 22 | self.buffer = [device newBufferWithLength:sizeof(MTLFloat)*9 options:MTLResourceOptionCPUCacheModeDefault]; 23 | 24 | MTLFloat3x3 convolutionKernel; 25 | convolutionKernel.v1 = MTLFloat3Make(0.5, 1.0, 0.5); 26 | convolutionKernel.v2 = MTLFloat3Make(1.0, -6.0, 1.0); 27 | convolutionKernel.v3 = MTLFloat3Make(0.5, 1.0, 0.5); 28 | self.convolutionKernel = convolutionKernel; 29 | 30 | return self; 31 | } 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MILocalBinaryPatternFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILocalBinaryPatternFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/12/5. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MI3x3TextureSamplingFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MILocalBinaryPatternFilter : MI3x3TextureSamplingFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MILocalBinaryPatternFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MILocalBinaryPatternFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/12/5. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MILocalBinaryPatternFilter.h" 10 | 11 | @implementation MILocalBinaryPatternFilter 12 | 13 | - (instancetype)init { 14 | if (self = [super initWithFragmentFunctionName:@"fragment_LocalBinaryPatternFilter"]) { 15 | 16 | } 17 | 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MILowPassFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MILowPassFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/12/5. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilterGroup.h" 10 | #import "MetalImageBuffer.h" 11 | #import "MIDissolveBlendFilter.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface MILowPassFilter : MetalImageFilterGroup 16 | { 17 | @protected 18 | MetalImageBuffer *bufferFilter; 19 | MIDissolveBlendFilter *dissolveBlendFilter; 20 | } 21 | 22 | // This controls the degree by which the previous accumulated frames are blended with the current one. 23 | // This ranges from 0.0 to 1.0, with a default of 0.5. 24 | @property(readwrite, nonatomic) MTLFloat filterStrength; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIMaskBilateralFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIMaskBilateralFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2020/6/30. 6 | // Copyright © 2020 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoInputFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIMaskBilateralFilter : MetalImageTwoInputFilter 14 | 15 | /** A radius in pixels to use for the smoothing, with a default of 2.0, 16 | * The calculation will acting with a gaussian kernel in the size of 17 | * 2 * radius + 1 . 18 | * 19 | * This adjusts the sigma variable in the Gaussian distribution function. 20 | */ 21 | @property (readwrite, nonatomic) unsigned int radius; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIMedianFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIMedianFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/18. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MI3x3TextureSamplingFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIMedianFilter : MI3x3TextureSamplingFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIMedianFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIMedianFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/18. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIMedianFilter.h" 10 | 11 | @implementation MIMedianFilter 12 | 13 | - (instancetype)init { 14 | if (self = [super initWithFragmentFunctionName:@"fragment_MedianFilter"]) { 15 | 16 | } 17 | return self; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MINonMaximumSuppressionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MINonMaximumSuppressionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MI3x3TextureSamplingFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MINonMaximumSuppressionFilter : MI3x3TextureSamplingFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MINonMaximumSuppressionFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MINonMaximumSuppressionFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MINonMaximumSuppressionFilter.h" 10 | 11 | @implementation MINonMaximumSuppressionFilter 12 | 13 | - (instancetype)init { 14 | if (self = [super initWithFragmentFunctionName:@"fragment_NonMaximumSuppressionFilter"]) { 15 | 16 | } 17 | 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIOpeningFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIOpeningFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilterGroup.h" 10 | 11 | @class MIErosionFilter; 12 | @class MIDilationFilter; 13 | 14 | // A filter that first performs an erosion on the red channel of an image, followed by a dilation of the same radius. 15 | // This helps to filter out smaller bright elements. 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface MIOpeningFilter : MetalImageFilterGroup 20 | { 21 | MIErosionFilter *erosionFilter; 22 | MIDilationFilter *dilationFilter; 23 | } 24 | 25 | @property(readwrite, nonatomic) MTLFloat verticalTexelSpacing, horizontalTexelSpacing; 26 | 27 | - (instancetype)initWithRadius:(MTLUInt)radius; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIOpeningFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIOpeningFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIOpeningFilter.h" 10 | #import "MIDilationFilter.h" 11 | #import "MIErosionFilter.h" 12 | 13 | @implementation MIOpeningFilter 14 | 15 | - (instancetype)init { 16 | return [self initWithRadius:1]; 17 | } 18 | 19 | - (instancetype)initWithRadius:(MTLUInt)radius { 20 | 21 | if (self = [super init]) { 22 | // First pass: erosion 23 | erosionFilter = [[MIErosionFilter alloc] initWithRadius:radius]; 24 | [self addFilter:erosionFilter]; 25 | 26 | // Second pass: dilation 27 | dilationFilter = [[MIDilationFilter alloc] initWithRadius:radius]; 28 | [self addFilter:dilationFilter]; 29 | 30 | [erosionFilter addTarget:dilationFilter]; 31 | 32 | self.initialFilters = [NSArray arrayWithObjects:erosionFilter, nil]; 33 | self.terminalFilter = dilationFilter; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void)setVerticalTexelSpacing:(MTLFloat)newValue; 40 | { 41 | _verticalTexelSpacing = newValue; 42 | erosionFilter.verticalTexelSpacing = newValue; 43 | dilationFilter.verticalTexelSpacing = newValue; 44 | } 45 | 46 | - (void)setHorizontalTexelSpacing:(MTLFloat)newValue; 47 | { 48 | _horizontalTexelSpacing = newValue; 49 | erosionFilter.horizontalTexelSpacing = newValue; 50 | dilationFilter.horizontalTexelSpacing = newValue; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIPrewittEdgeDetectionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIPrewittEdgeDetectionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISobelEdgeDetectionFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIPrewittEdgeDetectionFilter : MISobelEdgeDetectionFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIPrewittEdgeDetectionFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIPrewittEdgeDetectionFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIPrewittEdgeDetectionFilter.h" 10 | 11 | @implementation MIPrewittEdgeDetectionFilter 12 | 13 | - (instancetype)init { 14 | if (self = [super initWithFragmentFunctionName:@"fragment_PrewittEdgeDetectionFilter"]) { 15 | self.edgeStrength = 1.0; 16 | } 17 | return self; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIRGBClosingFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBClosingFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilterGroup.h" 10 | 11 | @class MIRGBErosionFilter; 12 | @class MIRGBDilationFilter; 13 | 14 | // A filter that first performs a dilation on each color channel of an image, followed by an erosion of the same radius. 15 | // This helps to filter out smaller dark elements. 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface MIRGBClosingFilter : MetalImageFilterGroup 20 | { 21 | MIRGBErosionFilter *erosionFilter; 22 | MIRGBDilationFilter *dilationFilter; 23 | } 24 | 25 | @property(readwrite, nonatomic) MTLFloat verticalTexelSpacing, horizontalTexelSpacing; 26 | 27 | - (instancetype)initWithRadius:(MTLUInt)radius; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIRGBClosingFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBClosingFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIRGBClosingFilter.h" 10 | #import "MIRGBDilationFilter.h" 11 | #import "MIRGBErosionFilter.h" 12 | 13 | @implementation MIRGBClosingFilter 14 | 15 | - (instancetype)init { 16 | return [self initWithRadius:1]; 17 | } 18 | 19 | - (instancetype)initWithRadius:(MTLUInt)radius { 20 | 21 | if (self = [super init]) { 22 | // First pass: dilation 23 | dilationFilter = [[MIRGBDilationFilter alloc] initWithRadius:radius]; 24 | [self addFilter:dilationFilter]; 25 | 26 | // Second pass: erosion 27 | erosionFilter = [[MIRGBErosionFilter alloc] initWithRadius:radius]; 28 | [self addFilter:erosionFilter]; 29 | 30 | [dilationFilter addTarget:erosionFilter]; 31 | 32 | self.initialFilters = [NSArray arrayWithObjects:dilationFilter, nil]; 33 | self.terminalFilter = erosionFilter; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void)setVerticalTexelSpacing:(MTLFloat)newValue; 40 | { 41 | _verticalTexelSpacing = newValue; 42 | erosionFilter.verticalTexelSpacing = newValue; 43 | dilationFilter.verticalTexelSpacing = newValue; 44 | } 45 | 46 | - (void)setHorizontalTexelSpacing:(MTLFloat)newValue; 47 | { 48 | _horizontalTexelSpacing = newValue; 49 | erosionFilter.horizontalTexelSpacing = newValue; 50 | dilationFilter.horizontalTexelSpacing = newValue; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIRGBDilationFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBDilationFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MITwoPassTextureSamplingFilter.h" 10 | 11 | // For each pixel, this sets it to the maximum value of each color channel in a rectangular neighborhood extending out dilationRadius pixels from the center. 12 | // This extends out brighter colors, and can be used for abstraction of color images. 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface MIRGBDilationFilter : MITwoPassTextureSamplingFilter 17 | 18 | // Acceptable values for dilationRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4. 19 | - (instancetype)initWithRadius:(MTLUInt)dilationRadius; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIRGBDilationFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBDilationFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIRGBDilationFilter.h" 10 | 11 | @implementation MIRGBDilationFilter 12 | 13 | - (instancetype)init { 14 | return [self initWithRadius:1]; 15 | } 16 | 17 | - (instancetype)initWithRadius:(MTLUInt)dilationRadius { 18 | 19 | MTLUInt supportedDilationRadius = MAX(MIN(dilationRadius, 4), 1); 20 | NSString *vertexFunctionName = [NSString stringWithFormat:@"vertex_DilationFilterRadius%d", supportedDilationRadius]; 21 | NSString *fragmentFunctionName = [NSString stringWithFormat:@"fragment_RGBDilationFilterRadius%d", supportedDilationRadius]; 22 | if (self = [super initWithFirstStageVertexFunctionName:vertexFunctionName 23 | firstStageFragmentFunctionName:fragmentFunctionName 24 | secondStageVertexFunctionName:vertexFunctionName 25 | secondStageFragmentFunctionName:fragmentFunctionName]) 26 | { 27 | 28 | } 29 | 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIRGBErosionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBErosionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MITwoPassTextureSamplingFilter.h" 10 | 11 | // For each pixel, this sets it to the minimum value of each color channel in a rectangular neighborhood extending out dilationRadius pixels from the center. 12 | // This extends out dark features, and can be used for abstraction of color images. 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface MIRGBErosionFilter : MITwoPassTextureSamplingFilter 17 | 18 | // Acceptable values for erosionRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4. 19 | - (id)initWithRadius:(MTLUInt)erosionRadius; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIRGBErosionFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBErosionFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIRGBErosionFilter.h" 10 | 11 | @implementation MIRGBErosionFilter 12 | 13 | - (instancetype)init { 14 | return [self initWithRadius:1]; 15 | } 16 | 17 | - (instancetype)initWithRadius:(MTLUInt)dilationRadius { 18 | 19 | MTLUInt supportedDilationRadius = MAX(MIN(dilationRadius, 4), 1); 20 | NSString *vertexFunctionName = [NSString stringWithFormat:@"vertex_DilationFilterRadius%d", supportedDilationRadius]; 21 | NSString *fragmentFunctionName = [NSString stringWithFormat:@"fragment_RGBErosionFilterRadius%d", supportedDilationRadius]; 22 | if (self = [super initWithFirstStageVertexFunctionName:vertexFunctionName 23 | firstStageFragmentFunctionName:fragmentFunctionName 24 | secondStageVertexFunctionName:vertexFunctionName 25 | secondStageFragmentFunctionName:fragmentFunctionName]) 26 | { 27 | 28 | } 29 | 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIRGBOpeningFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBOpeningFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilterGroup.h" 10 | 11 | @class MIRGBErosionFilter; 12 | @class MIRGBDilationFilter; 13 | 14 | // A filter that first performs an erosion on each color channel of an image, followed by a dilation of the same radius. 15 | // This helps to filter out smaller bright elements. 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface MIRGBOpeningFilter : MetalImageFilterGroup 20 | { 21 | MIRGBErosionFilter *erosionFilter; 22 | MIRGBDilationFilter *dilationFilter; 23 | } 24 | 25 | @property(readwrite, nonatomic) MTLFloat verticalTexelSpacing, horizontalTexelSpacing; 26 | 27 | - (instancetype)initWithRadius:(MTLUInt)radius; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIRGBOpeningFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIRGBOpeningFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIRGBOpeningFilter.h" 10 | #import "MIRGBDilationFilter.h" 11 | #import "MIRGBErosionFilter.h" 12 | 13 | @implementation MIRGBOpeningFilter 14 | 15 | - (instancetype)init { 16 | return [self initWithRadius:1]; 17 | } 18 | 19 | - (instancetype)initWithRadius:(MTLUInt)radius { 20 | 21 | if (self = [super init]) { 22 | // First pass: erosion 23 | erosionFilter = [[MIRGBErosionFilter alloc] initWithRadius:radius]; 24 | [self addFilter:erosionFilter]; 25 | 26 | // Second pass: dilation 27 | dilationFilter = [[MIRGBDilationFilter alloc] initWithRadius:radius]; 28 | [self addFilter:dilationFilter]; 29 | 30 | [erosionFilter addTarget:dilationFilter]; 31 | 32 | self.initialFilters = [NSArray arrayWithObjects:erosionFilter, nil]; 33 | self.terminalFilter = dilationFilter; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void)setVerticalTexelSpacing:(MTLFloat)newValue; 40 | { 41 | _verticalTexelSpacing = newValue; 42 | erosionFilter.verticalTexelSpacing = newValue; 43 | dilationFilter.verticalTexelSpacing = newValue; 44 | } 45 | 46 | - (void)setHorizontalTexelSpacing:(MTLFloat)newValue; 47 | { 48 | _horizontalTexelSpacing = newValue; 49 | erosionFilter.horizontalTexelSpacing = newValue; 50 | dilationFilter.horizontalTexelSpacing = newValue; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MISharpenFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISharpenFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/16. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MISharpenFilter : MetalImageFilter 14 | 15 | // Sharpness ranges from -4.0 to 4.0, with 0.0 as the normal level 16 | @property(readwrite, nonatomic) MTLFloat sharpness; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MISobelEdgeDetectionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISobelEdgeDetectionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoPassFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MISobelEdgeDetectionFilter : MetalImageTwoPassFilter { 14 | 15 | @protected 16 | BOOL hasOverriddenImageSizeFactor; 17 | MTLUInt2 lastImageSize; 18 | } 19 | 20 | @property (nonatomic, strong) id vertexSlotBuffer; 21 | @property (nonatomic, strong) id fragmentSlotBuffer; 22 | 23 | // The texel width and height factors tweak the appearance of the edges. 24 | // By default, they match the inverse of the filter size in pixels. 25 | @property (nonatomic, assign) MTLFloat2 texelSize; 26 | 27 | // The filter strength property affects the dynamic range of the filter. 28 | // High values can make edges more visible, but can lead to saturation. 29 | // Default of 1.0. 30 | @property (readwrite, nonatomic) MTLFloat edgeStrength; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MISurfaceBlurFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MISurfaceBlurFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2020/6/23. 6 | // Copyright © 2020 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MISurfaceBlurFilter : MetalImageFilter 14 | 15 | // Default is 3 16 | @property (nonatomic, assign) int radius; 17 | 18 | // Default is 15 19 | @property (nonatomic, assign) float gamma; 20 | 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIThresholdEdgeDetectionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIThresholdEdgeDetectionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISobelEdgeDetectionFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIThresholdEdgeDetectionFilter : MISobelEdgeDetectionFilter 14 | 15 | /** Any edge above this threshold will be black, and anything below white. 16 | * Ranges from 0.0 to 1.0, with 0.8 as the default 17 | */ 18 | @property(readwrite, nonatomic) MTLFloat threshold; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIThresholdEdgeDetectionFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIThresholdEdgeDetectionFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIThresholdEdgeDetectionFilter.h" 10 | #import "MetalDevice.h" 11 | 12 | @implementation MIThresholdEdgeDetectionFilter 13 | 14 | - (id)initWithFragmentFunctionName:(NSString *)fragmentFunctionName 15 | { 16 | // Do a luminance pass first to reduce the calculations performed at each fragment in the edge detection phase 17 | 18 | if (self = [super initWithFirstStageVertexFunctionName:@"vertex_common" 19 | firstStageFragmentFunctionName:@"fragment_luminance" 20 | secondStageVertexFunctionName:@"vertex_nearbyTexelSampling" 21 | secondStageFragmentFunctionName:fragmentFunctionName]) { 22 | 23 | id device = [MetalDevice sharedMTLDevice]; 24 | self.vertexSlotBuffer = [device newBufferWithLength:sizeof(MTLFloat2) options:MTLResourceOptionCPUCacheModeDefault]; 25 | self.fragmentSlotBuffer = [device newBufferWithLength:sizeof(MTLFloat)*2 options:MTLResourceOptionCPUCacheModeDefault]; 26 | 27 | self.threshold = 0.25; 28 | self.edgeStrength = 1.0; 29 | 30 | hasOverriddenImageSizeFactor = NO; 31 | } 32 | 33 | return self; 34 | } 35 | 36 | 37 | - (id)init 38 | { 39 | return [self initWithFragmentFunctionName:@"fragment_ThresholdEdgeDetectionFilter"]; 40 | } 41 | 42 | - (void)setThreshold:(MTLFloat)threshold { 43 | _threshold = threshold; 44 | 45 | MTLFloat *contentBuffer = (MTLFloat *)[self.fragmentSlotBuffer contents]; 46 | contentBuffer[1] = _threshold; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MITransformFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MITransformFilter.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/14. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "MetalImageFilter.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface MITransformFilter : MetalImageFilter 16 | 17 | // You can either set the transform to apply to be a 2-D affine transform or a 3-D transform. 18 | // The default is the identity transform (the output image is identical to the input). 19 | @property(readwrite, nonatomic) CGAffineTransform affineTransform; 20 | @property(readwrite, nonatomic) CATransform3D transform3D; 21 | 22 | // This applies the transform to the raw frame data if set to YES, 23 | // the default of NO takes the aspect ratio of the image input into account when rotating 24 | @property(readwrite, nonatomic) BOOL ignoreAspectRatio; 25 | 26 | // sets the anchor point to top left corner, the default is NO. 27 | @property(readwrite, nonatomic) BOOL anchorTopLeft; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MITransformFilter.metal: -------------------------------------------------------------------------------- 1 | // 2 | // MITransformFilter.metal 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/10/14. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include "../Metal/CommonStruct.metal" 10 | using namespace metal; 11 | 12 | typedef struct { 13 | float4x4 transformMatrix; 14 | float4x4 orthographicMatrix; 15 | }TransformParameters; 16 | 17 | vertex VertexIO vertex_transform(constant float4 *pPosition [[ buffer(0) ]], 18 | constant packed_float2 *pTexCoords [[ buffer(1) ]], 19 | constant TransformParameters ¶meters [[ buffer(2) ]], 20 | uint vid [[ vertex_id ]]) 21 | { 22 | VertexIO outVertices; 23 | outVertices.position = parameters.transformMatrix * float4(pPosition[vid].xyz, 1.0) * parameters.orthographicMatrix; 24 | outVertices.textureCoordinate = pTexCoords[vid]; 25 | 26 | return outVertices; 27 | } 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIWeakPixelInclusionFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIWeakPixelInclusionFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MI3x3TextureSamplingFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIWeakPixelInclusionFilter : MI3x3TextureSamplingFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIWeakPixelInclusionFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIWeakPixelInclusionFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIWeakPixelInclusionFilter.h" 10 | 11 | @implementation MIWeakPixelInclusionFilter 12 | 13 | - (instancetype)init { 14 | if (self = [super initWithFragmentFunctionName:@"fragment_WeakPixelInclusionFilter"]) { 15 | 16 | } 17 | 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIXYDerivativeFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIXYDerivativeFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MISobelEdgeDetectionFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MIXYDerivativeFilter : MISobelEdgeDetectionFilter 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageProcessing/MIXYDerivativeFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MIXYDerivativeFilter.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MIXYDerivativeFilter.h" 10 | 11 | @implementation MIXYDerivativeFilter 12 | 13 | - (instancetype)init { 14 | if (self = [super initWithFragmentFunctionName:@"fragment_MIXYDerivativeFilter"]) { 15 | self.edgeStrength = 1.0; 16 | } 17 | return self; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MI3x3TextureSamplingFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MI3x3TextureSamplingFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/17. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MI3x3TextureSamplingFilter : MetalImageFilter { 14 | 15 | @protected 16 | BOOL hasOverriddenImageSizeFactor; 17 | MTLUInt2 lastImageSize; 18 | } 19 | 20 | // The texel width and height determines how far out to sample from this texel. 21 | // By default, this is the normalized width of a pixel, but this can be overridden for different effects. 22 | @property (readwrite, nonatomic) MTLFloat2 texelSize; 23 | @property (nonatomic, strong, readonly) id texelSizeBuffer; 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MITwoPassTextureSamplingFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MITwoPassTextureSamplingFilter.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/9/2. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageTwoPassFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MITwoPassTextureSamplingFilter : MetalImageTwoPassFilter { 14 | 15 | @protected 16 | id verticalBuffer; 17 | id horizontalBuffer; 18 | MTLUInt2 lastImageSize; 19 | MTLFloat _verticalTexelSpacing, _horizontalTexelSpacing; 20 | } 21 | 22 | // This sets the spacing between texels (in pixels) when sampling for the first. By default, this is 1.0 23 | @property (nonatomic, assign) MTLFloat verticalTexelSpacing; 24 | @property (nonatomic, assign) MTLFloat horizontalTexelSpacing; 25 | 26 | - (void)setupFilterForSize:(MTLUInt2)filterFrameSize; 27 | - (MTLUInt2)textureSizeForTexel; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Matrix/MetalMatrixBuffers.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016 Apple Inc. All Rights Reserved. 3 | See LICENSE.txt for this sample’s licensing information 4 | 5 | Abstract: 6 | Utilities for managing metal buffers representing matrices. 7 | */ 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | // A utility class to encapsulate instantiation of Metal matrix buffer. 13 | // By the virtue of this encapsulation, and after the buffers are added 14 | // to a mutable array of buffers, all buffers are kept alive in the 15 | // matrix multiplication object's life-cycle. 16 | @interface MetalMatrixBuffer: NSObject 17 | 18 | @property (nonatomic) BOOL resized; 19 | @property (nonatomic) size_t size; 20 | @property (nonatomic) void* baseAddr; 21 | @property (nonatomic) id buffer; 22 | @property (nonatomic, readonly) id device; 23 | 24 | - (instancetype) initWithDevice:(id)device; 25 | 26 | @end 27 | 28 | // A utility class to encapsulate instantiation of Metal matrix buffer. 29 | // By the virtue of this encapsulation, and after the buffers are added 30 | // to a mutable array of buffers, all buffers are kept alive in the 31 | // matrix multiplication object's life-cycle. 32 | @interface MetalMatrixBuffers: NSObject 33 | 34 | @property (nonatomic) NSMutableArray* array; 35 | @property (nonatomic, readonly) size_t capacity; 36 | 37 | - (instancetype) initWithDevice:(id)device 38 | capacity:(size_t)capacity; 39 | 40 | @end 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Metal/CommonStruct.metal: -------------------------------------------------------------------------------- 1 | // 2 | // CommonStruct.metal 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/15. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace metal; 18 | 19 | struct VertexIO 20 | { 21 | float4 position [[position]]; 22 | float2 textureCoordinate [[user(texturecoord)]]; 23 | }; 24 | 25 | struct VertexIO2 26 | { 27 | float4 position [[position]]; 28 | float2 textureCoordinate [[attribute(0)]]; 29 | float2 textureCoordinate2 [[attribute(1)]]; 30 | }; 31 | 32 | struct VertexIONearbyTexelSampling 33 | { 34 | float4 position [[position]]; 35 | 36 | float2 topLeftTextureCoordinate; 37 | float2 topTextureCoordinate; 38 | float2 topRightTextureCoordinate; 39 | 40 | float2 leftTextureCoordinate; 41 | float2 textureCoordinate [[user(texturecoord)]]; 42 | float2 rightTextureCoordinate; 43 | 44 | float2 bottomLeftTextureCoordinate; 45 | float2 bottomTextureCoordinate; 46 | float2 bottomRightTextureCoordinate; 47 | }; 48 | 49 | struct VertexIOWithSteps 50 | { 51 | float4 position [[position]]; 52 | float2 textureCoordinate [[user(texturecoord)]]; 53 | float2 texelSteps; 54 | }; 55 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalDevice.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalDevice.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/17. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MetalDevice : NSObject 14 | 15 | + (nonnull MetalDevice *)sharedInstance; 16 | + (nullable id)sharedMTLDevice; 17 | + (nullable id)MetalImageLibrary; 18 | + (nullable id)sharedCommandQueue; 19 | 20 | + (nullable id)sharedCommandBuffer; 21 | + (void)commitCommandBuffer; 22 | + (void)commitCommandBufferWithCompletion:(void(^)(id))completion; 23 | + (void)commitCommandBufferWaitUntilScheduled:(BOOL)waitUtilScheduled; 24 | + (void)commitCommandBufferWaitUntilDone:(BOOL)waitUtilDone; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImage.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/2/7. 6 | // Copyright © 2017年 tencent. All rights reserved. 7 | // 8 | 9 | #if TARGET_IPHONE_SIMULATOR 10 | #warning This framework does not support SIMULATOR. 11 | #endif 12 | 13 | #import "MetalDevice.h" 14 | #import "MetalImageTypes.h" 15 | #import "MetalImageGlobal.h" 16 | #import "MetalImageFunction.h" 17 | #import "MetalImageTexture.h" 18 | #import "MetalImageTextureCache.h" 19 | 20 | #import "MetalImageVideoCamera.h" 21 | #import "MetalImageView.h" 22 | #import "MetalImageOutput.h" 23 | #import "MetalImageFilter.h" 24 | #import "MetalImageFilterGroup.h" 25 | #import "MetalImageColorConversion.h" 26 | #import "MetalImageContext.h" 27 | #import "MetalImageKernal.h" 28 | #import "MetalImageDebugView.h" 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageBuffer.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageBuffer.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/20. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MetalImageBuffer : MetalImageFilter 14 | { 15 | NSMutableArray *bufferedFramebuffers; 16 | } 17 | 18 | @property(readwrite, nonatomic) NSUInteger bufferSize; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageColorConversion.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageColorConversion.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/3. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MetalImageTexture.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | typedef NS_ENUM(NSUInteger, ColorConversionKernalFunction) { 15 | ColorConversionKernalFunction601v, 16 | ColorConversionKernalFunction601f, 17 | ColorConversionKernalFunction709v, 18 | }; 19 | 20 | @interface MetalImageColorConversion : NSObject 21 | 22 | @property (nonatomic,assign) ColorConversionKernalFunction function; 23 | 24 | - (void)generateBGROutputTexture:(nonnull id)texture 25 | YPlane:(nonnull id)y_texture 26 | UVPlane:(nonnull id)uv_texture; 27 | 28 | @end 29 | 30 | NS_ASSUME_NONNULL_END 31 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageCommonFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageCommonFilter.h 3 | // MetalImage 4 | // 5 | // Created by keyishen on 2017/7/25. 6 | // Copyright © 2017年 tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MetalImageCommonFilter : MetalImageFilter 12 | 13 | @property (nonatomic, strong) id lutTexture; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageContext.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/2/7. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "MetalImageTextureCache.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface MetalImageContext : NSObject 16 | 17 | @property (nonatomic, readonly) dispatch_queue_t contextQueue; 18 | 19 | - (instancetype)initWithProcessingQueueName:(NSString *)queueName; 20 | 21 | - (NSString *)contextKey; 22 | 23 | - (CVMetalTextureCacheRef)coreVideoTextureCache; 24 | - (MetalImageTextureCache *)textureCache; 25 | 26 | + (MetalImageContext *)sharedImageProcessingContext; 27 | + (MetalImageTextureCache *)sharedTextureCache; 28 | + (dispatch_queue_t)sharedContextQueue; 29 | 30 | @end 31 | 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageDebugView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageDebugView.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MetalImageInput.h" 11 | #import "MetalImageTexture.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface MetalImageDebugView : UIImageView { 16 | 17 | @protected 18 | MetalImageTexture *firstInputTexture; 19 | MetalImageRotationMode inputRotationMode; 20 | } 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageDebugView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageDebugView.m 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/8. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageDebugView.h" 10 | #import "UIImage+Texture.h" 11 | #import "MetalImageFunction.h" 12 | 13 | @implementation MetalImageDebugView 14 | 15 | 16 | #pragma mark - MetalImageInput Protocol 17 | 18 | - (void)setInputRotation:(MetalImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex { 19 | if (inputRotationMode != newInputRotation) { 20 | inputRotationMode = newInputRotation; 21 | // [self updateTextureCoordinates]; 22 | } 23 | } 24 | 25 | - (void)setInputTexture:(MetalImageTexture *)newInputTexture atIndex:(NSInteger)textureIndex { 26 | firstInputTexture = newInputTexture; 27 | [firstInputTexture lock]; 28 | } 29 | 30 | - (void)newTextureReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex { 31 | 32 | runMetalOnMainQueueWithoutDeadlocking(^{ 33 | self.image = [UIImage imageWithMTLTexture:[firstInputTexture texture] orientation:UIImageOrientationUp]; 34 | }); 35 | 36 | [firstInputTexture unlock]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageFilterExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageFilterExtension.h 3 | // MetalImage 4 | // 5 | // Created by fengshi on 2017/9/10. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MetalImageFilter (Extension) 14 | 15 | - (MTLFloat2)rotatedPoint:(MTLFloat2)pointToRotate forRotation:(MetalImageRotationMode)rotation; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageFilterGroup.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageFilterGroup.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/9. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageOutput.h" 10 | #import "MetalImageFilter.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface MetalImageFilterGroup : MetalImageOutput 15 | 16 | @property (nonatomic, strong) MetalImageOutput *terminalFilter; 17 | @property (nonatomic, strong) NSArray *> *initialFilters; 18 | @property (nonatomic, assign) MTLClearColor bgClearColor; 19 | 20 | - (void)addFilter:(MetalImageOutput *)filter; 21 | - (void)removeFilter:(MetalImageOutput *)filter; 22 | - (void)removeAllFilters; 23 | - (MetalImageOutput * _Nullable)filterAtIndex:(NSUInteger)filterIndex; 24 | - (NSUInteger)filterCount; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageFunction.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageFunction.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/2/7. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageContext.h" 10 | #import "MetalImageGlobal.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | extern MTLFloat4 *MetalImageDefaultRenderVetics; 15 | extern NSUInteger MetalImageDefaultRenderVetexCount; 16 | 17 | @interface MetalImageFunction : NSObject 18 | 19 | API_AVAILABLE(ios(9.0)) 20 | extern dispatch_queue_attr_t MetalImageDefaultQueueAttribute(void); 21 | 22 | extern void runMetalOnMainQueueWithoutDeadlocking(void (^block)(void)); 23 | extern void runMetalSynchronouslyOnVideoProcessingQueue(void (^block)(void)); 24 | extern void runMetalAsynchronouslyOnVideoProcessingQueue(void (^block)(void)); 25 | extern void runMetalOnVideoProcessingQueue(BOOL synchronously, void (^block)(void)); 26 | extern void runMetalSynchronouslyOnContextQueue(MetalImageContext *context, void (^block)(void)); 27 | extern void runMetalAsynchronouslyOnContextQueue(MetalImageContext *context, void (^block)(void)); 28 | extern void runMetalOnContextQueue(BOOL synchronously, MetalImageContext *context, void (^block)(void)); 29 | extern void reportAvailableMemoryForMetalImage(NSString *tag); 30 | 31 | extern const MTLFloat2 *TextureCoordinatesForRotation(MetalImageRotationMode rotationMode); 32 | 33 | @end 34 | 35 | NS_ASSUME_NONNULL_END 36 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageGlobal.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageGlobal.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/6. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #ifndef __MetalImageGlobal__ 10 | #define __MetalImageGlobal__ 11 | 12 | #define MetalImageRotationSwapsWidthAndHeight(rotation) (\ 13 | (rotation) == kMetalImageRotateLeft || \ 14 | (rotation) == kMetalImageRotateRight || \ 15 | (rotation) == kMetalImageRotateRightFlipVertical || \ 16 | (rotation) == kMetalImageRotateRightFlipHorizontal) 17 | 18 | typedef NS_ENUM(NSUInteger, MetalImageRotationMode) { 19 | kMetalImageNoRotation,//0 20 | kMetalImageRotateLeft,//1 21 | kMetalImageRotateRight,//2 22 | kMetalImageFlipVertical,//3 23 | kMetalImageFlipHorizonal,//4 24 | kMetalImageRotateRightFlipVertical,//5 25 | kMetalImageRotateRightFlipHorizontal,//6 26 | kMetalImageRotate180//7 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageInput.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageInput.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/2/11. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "MetalImageGlobal.h" 12 | #import "MetalImageTexture.h" 13 | 14 | typedef struct { 15 | CMTime frameTime; 16 | MetalImageRotationMode rotationMode; 17 | BOOL frameCheckDisabled; 18 | BOOL hasReceivedFrame; 19 | BOOL hasSetTarget; 20 | }MetalImageInputParameter; 21 | 22 | NS_ASSUME_NONNULL_BEGIN 23 | 24 | @protocol MetalImageInput 25 | 26 | @required 27 | - (void)newTextureReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex; 28 | - (void)setInputTexture:(MetalImageTexture *)newInputTexture atIndex:(NSInteger)textureIndex; 29 | - (void)setInputRotation:(MetalImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex; 30 | 31 | @optional 32 | - (NSInteger)nextAvailableTextureIndex; 33 | - (void)reserveTextureIndex:(NSInteger)textureIndex; 34 | - (void)releaseTextureIndex:(NSInteger)textureIndex; 35 | 36 | - (CGSize)maximumOutputSize; 37 | - (void)endProcessing; 38 | - (BOOL)shouldIgnoreUpdatesToThisTarget; 39 | - (BOOL)enabled; 40 | - (BOOL)wantsMonochromeInput; 41 | - (void)setCurrentlyReceivingMonochromeInput:(BOOL)newValue; 42 | 43 | 44 | @end 45 | 46 | NS_ASSUME_NONNULL_END 47 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageKernel.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageKernel.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/14. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageOutput.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MetalImageKernel : MetalImageOutput { 14 | 15 | @protected 16 | MetalImageTexture *firstInputTexture; 17 | MetalImageInputParameter firstInputParameter; 18 | 19 | dispatch_semaphore_t m_InflightSemaphore; 20 | id k_fuction; 21 | id k_computePipelineState; 22 | } 23 | 24 | @property (nonatomic,readonly) NSString *functionName; 25 | 26 | - (instancetype)initWithFunctionName:(NSString *)fuctionName; 27 | - (instancetype)initWithFunction:(id)function; 28 | 29 | - (void)computeTexture; 30 | - (void)assembleComputeEncoder:(id)computeEncoder; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageMath.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageMath.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2020/6/23. 6 | // Copyright © 2020 fengshi. All rights reserved. 7 | // 8 | 9 | #ifndef MetalImageMath_h 10 | #define MetalImageMath_h 11 | 12 | #include 13 | #include 14 | 15 | void make_gaussian_distribution(const unsigned int radius, const float sigma, const bool normalize, float *buffer); 16 | void make_gaussian_distribution_2d(const unsigned int radius, const float sigma, const bool normalize, float *buffer); 17 | 18 | #endif /* MetalImageMath_h */ 19 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImagePicture.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImagePicture.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/12. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MetalImageOutput.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface MetalImagePicture : MetalImageOutput { 15 | 16 | CGSize pixelSizeOfImage; 17 | BOOL hasProcessedImage; 18 | BOOL shouldSmoothlyScaleOutput; 19 | 20 | dispatch_semaphore_t imageUpdateSemaphore; 21 | } 22 | 23 | - (instancetype)initWithImage:(UIImage *)newImageSource; 24 | - (instancetype)initWithImage:(UIImage *)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput removePremultiplication:(BOOL)removePremultiplication; 25 | 26 | - (void)processImage; 27 | - (BOOL)processImageWithCompletionHandler:(void (^ _Nullable)(void))completion; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImagePreprocess.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImagePreprocess.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/6. 6 | // Copyright © 2017年 tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MetalImageTexture.h" 11 | #import "MetalImageOutput.h" 12 | 13 | @interface MetalImagePreprocess : MetalImageOutput 14 | 15 | @property (nonatomic,assign) uint32_t borderSize; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageRenderResource.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageRenderResource.h 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface MetalImageRenderBuffer : NSObject 15 | 16 | @property (nonatomic,strong) id buffer; 17 | @property (nonatomic,assign) NSUInteger offset; 18 | @property (nonatomic,assign) NSUInteger index; 19 | 20 | @end 21 | 22 | @interface MetalImageVertexBuffer : MetalImageRenderBuffer 23 | @end 24 | 25 | @interface MetalImageFragmentBuffer : MetalImageRenderBuffer 26 | @end 27 | 28 | @interface MetalImageRenderTexture : NSObject 29 | 30 | @property (nonatomic,strong) id texture; 31 | @property (nonatomic,assign) NSUInteger index; 32 | 33 | @end 34 | 35 | @interface MetalImageVertexTexture : MetalImageRenderTexture 36 | @end 37 | 38 | @interface MetalImageFragmentTexture : MetalImageRenderTexture 39 | @end 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageRenderResource.m: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageRenderResource.m 3 | // MetalImage 4 | // 5 | // Created by Feng Stone on 2017/10/21. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageRenderResource.h" 10 | 11 | @implementation MetalImageRenderBuffer 12 | 13 | @end 14 | 15 | @implementation MetalImageVertexBuffer 16 | 17 | @end 18 | 19 | @implementation MetalImageFragmentBuffer 20 | 21 | @end 22 | 23 | 24 | @implementation MetalImageRenderTexture 25 | 26 | @end 27 | 28 | @implementation MetalImageVertexTexture 29 | 30 | @end 31 | 32 | @implementation MetalImageFragmentTexture 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageTexture.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageTexture.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/2/7. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import "MetalImageTypes.h" 14 | 15 | @class UIImage; 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface MetalImageTexture : NSObject 20 | 21 | @property (nonatomic,strong,nullable) NSString *label; 22 | @property (nonatomic,strong,readonly) id texture; 23 | @property (nonatomic,readonly) MTLUInt2 size; 24 | @property (nonatomic,readonly) int pixelFormat; 25 | 26 | - (instancetype)initWithTextureSize:(MTLUInt2)size; 27 | - (instancetype)initWithTextureSize:(MTLUInt2)size pixelFormat:(int)pixelFormat; 28 | - (instancetype)initWithTextureSize:(MTLUInt2)size textureUsage:(MTLTextureUsage)usage; 29 | 30 | + (BOOL)supportsFastTextureUpload; 31 | + (CGSize)sizeThatFitsWithinATextureForSize:(CGSize)inputSize; 32 | + (int)defaultPixelFormat; 33 | 34 | // Reference counting 35 | - (MetalImageTexture *)lock; 36 | - (void)unlock; 37 | - (void)clearAllLocks; 38 | - (void)disableReferenceCounting; 39 | - (void)enableReferenceCounting; 40 | - (BOOL)isReferenceCountingEnable; 41 | - (NSUInteger)referenceCounting; 42 | 43 | // Raw data bytes 44 | - (void)lockForReading; 45 | - (void)unlockAfterReading; 46 | - (NSUInteger)bytesPerRow; 47 | - (Byte *)byteBuffer; 48 | 49 | // debug 50 | - (UIImage *)imageFromTexture; 51 | 52 | @end 53 | 54 | NS_ASSUME_NONNULL_END 55 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageTextureCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageTextureCache.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/2/7. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MetalImageTexture.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface MetalImageTextureCache : NSObject 15 | 16 | // texture management 17 | - (MetalImageTexture *)fetchTextureWithSize:(MTLUInt2)size; 18 | - (MetalImageTexture *)fetchTextureWithSize:(MTLUInt2)size pixelFormat:(int)pixelFormat; 19 | 20 | - (void)cacheTexture:(MetalImageTexture *)texture; 21 | - (void)purgeAllUnassignedTextures; 22 | 23 | - (void)addFramebufferToActiveImageCaptureList:(MetalImageTexture *)framebuffer; 24 | - (void)removeFramebufferFromActiveImageCaptureList:(MetalImageTexture *)framebuffer; 25 | 26 | @end 27 | 28 | @interface MTLTextureDescriptor (reuseIdentifier) 29 | 30 | - (NSString *)reuseIdentifier; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageTwoInputFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageTwoInputFilter.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/29. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageFilter.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MetalImageTwoInputFilter : MetalImageFilter { 14 | 15 | @protected 16 | MetalImageTexture *secondInputTexture; 17 | MetalImageInputParameter secondInputParameter; 18 | 19 | id _coordBuffer2; 20 | } 21 | 22 | - (void)disableFirstFrameCheck; 23 | - (void)disableSecondFrameCheck; 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageTwoInputKernel.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageTwoInputKernel.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/4/7. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import "MetalImageKernel.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface MetalImageTwoInputKernel : MetalImageKernel { 14 | 15 | @protected 16 | MetalImageTexture *secondInputTexture; 17 | MetalImageInputParameter secondInputParameter; 18 | } 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MetalImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalImageView.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/3. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MetalImageInput.h" 11 | #import "MetalImageTexture.h" 12 | 13 | typedef NS_ENUM(NSUInteger, MetalImageFillModeType) { 14 | kMetalImageFillModeStretch, // Stretch to fill the full view, which may distort the image outside of its normal aspect ratio 15 | kMetalImageFillModePreserveAspectRatio, // Maintains the aspect ratio of the source image, adding bars of the specified background color 16 | kMetalImageFillModePreserveAspectRatioAndFill // Maintains the aspect ratio of the source image, zooming in on its center to fill the view 17 | }; 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | @interface MetalImageView : UIView { 22 | 23 | @protected 24 | MetalImageTexture *firstInputTexture; 25 | MetalImageRotationMode inputRotationMode; 26 | } 27 | 28 | 29 | /** The fill mode dictates how images are fit in the view, with the default being kGPUImageFillModePreserveAspectRatio 30 | */ 31 | @property (nonatomic,assign) MetalImageFillModeType fillMode; 32 | 33 | 34 | @property (nonatomic,assign) MTLClearColor bgClearColor; 35 | 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/UIImage+Texture.h: -------------------------------------------------------------------------------- 1 | @import UIKit; 2 | 3 | @protocol MTLTexture; 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface UIImage (MTLTexture) 8 | 9 | + (UIImage *)imageWithMTLTexture:(id)texture orientation:(UIImageOrientation)orientation; 10 | 11 | @end 12 | 13 | NS_ASSUME_NONNULL_END 14 | 15 | bool CGRectIsValid(CGRect rect); 16 | -------------------------------------------------------------------------------- /MetalImage/Resources/lookup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Resources/lookup.png -------------------------------------------------------------------------------- /MetalImage/Resources/lookup_amatorka.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Resources/lookup_amatorka.png -------------------------------------------------------------------------------- /MetalImage/Resources/lookup_miss_etikate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Resources/lookup_miss_etikate.png -------------------------------------------------------------------------------- /MetalImage/Resources/lookup_soft_elegance_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Resources/lookup_soft_elegance_1.png -------------------------------------------------------------------------------- /MetalImage/Resources/lookup_soft_elegance_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feng1919/MetalImage/91bcbc4750bef4af3883755e3f397f4e280f5cc0/MetalImage/Resources/lookup_soft_elegance_2.png -------------------------------------------------------------------------------- /MetalImage/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/2/7. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ViewController : UIViewController 14 | 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /MetalImage/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MetalImage 4 | // 5 | // Created by stonefeng on 2017/3/25. 6 | // Copyright © 2017年 fengshi. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MetalImage 2 | 3 | A GPU-Accelerated Framework for Images, Videos in iOS.This framework is based on BradLarson's GPUImage, and using the Apple Metal to accelerate, different from GPUImage by OpenGL ES. 4 | 5 | Author: Feng Shi 6 | 7 | Email : redpark@qq.com 8 | 9 | # Technical requirements 10 | Metal Framework: Applications using this will run on arm64 iOS devices only. 11 | iOS 9.0 SDK to build. 12 | Devices must have a camera to use camera-related functionality (obviously). 13 | 14 | # License 15 | MIT License 16 | 17 | Copyright (c) 2017 Fengshi 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in all 27 | copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. 36 | -------------------------------------------------------------------------------- /privacypolicy.html: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | PRIVACY POLICY 10 | 11 | 12 |

PRIVACY POLICY

13 |

14 | Effective Date: March 6, 2020 15 |

16 |

17 | Welcome to HuiGram Labs, Inc ("Company", "we", "us" or "our"), a mobile technology company specializing in computer vision and deep learning related products. 18 |

19 |

20 | HuiGram, this app, runs on devices, and will never cast an internet connection. We will never collect your any information. 21 |

22 |

23 | Contact: Feng Shi, +086-18621699994 24 |

25 |

26 | Address: Room 27-402, No.88 Wanyuan Rd., Dianshanhu Twon, The city of Kunshan, Jiangsu province, China. 27 |

28 |

29 | Email: redpark@qq.com 30 |

31 | 32 | 33 | --------------------------------------------------------------------------------