Last active
November 16, 2017 21:32
-
-
Save sushihangover/e94ab75592e21d990df7466f95bfd8e1 to your computer and use it in GitHub Desktop.
Xamarin iOS CIFilter / CIColorKernel Replace one color with another color (with threshold parameter to catch those stray variants)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ColorReplaceFilter : CIFilter | |
{ | |
const string filterName = "colorReplace"; | |
const int numArgs = 4; | |
const string coreIageShaderProgram = | |
@" | |
kernel vec4 main(__sample s, __color o, __color r, float threshold) { | |
vec4 diff = s.rgba - o; | |
float distance = length( diff ); | |
float alpha = compare( distance - threshold, 0.0, 1.0 ); | |
if (alpha == 0.0) | |
return r; | |
return s; | |
} | |
"; | |
NSObject[] arguments; | |
CIColorKernel colorKernel; | |
public ColorReplaceFilter() { Initializer(); } | |
public ColorReplaceFilter(NSCoder coder) : base(coder) { Initializer(); } | |
public ColorReplaceFilter(NSObjectFlag t) : base(t) { Initializer(); } | |
public ColorReplaceFilter(IntPtr handle) : base(handle) { Initializer(); } | |
public CIImage InputImage { get; set; } | |
public CIColor MatchColor { get; set; } | |
public CIColor ReplaceWithColor { get; set; } | |
NSNumber _threshold; | |
public nfloat Threshold | |
{ | |
get { return _threshold.NFloatValue; } | |
set { _threshold = NSNumber.FromNFloat(value); } | |
} | |
void Initializer() | |
{ | |
arguments = new NSObject[numArgs]; | |
colorKernel = CIColorKernel.FromProgramSingle(coreIageShaderProgram); | |
MatchColor = CIColor.BlackColor; | |
ReplaceWithColor = CIColor.WhiteColor; | |
_threshold = new NSNumber(0.0f); | |
} | |
public override string Name | |
{ | |
get => filterName; | |
} | |
public override CIImage OutputImage | |
{ | |
get => CreateOutputImage(); | |
} | |
CIImage CreateOutputImage() | |
{ | |
if (InputImage != null) // Avoid object creation to allow fast filter chaining | |
{ | |
arguments[0] = InputImage as NSObject; | |
arguments[1] = MatchColor as NSObject; | |
arguments[2] = ReplaceWithColor as NSObject; | |
arguments[3] = _threshold as NSObject; | |
var ciImage = colorKernel.ApplyWithExtent(InputImage.Extent, arguments); | |
return ciImage; | |
} | |
return null; | |
} | |
protected override void Dispose(bool disposing) | |
{ | |
base.Dispose(disposing); | |
arguments = null; | |
InputImage = null; | |
MatchColor = null; | |
ReplaceWithColor = null; | |
colorKernel.Dispose(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var inputImage = inputVIew.Image; // Some UIImage as input; | |
var replaceFilter = new ColorReplaceFilter | |
{ | |
InputImage = new CIImage(inputImage) | |
}; | |
replaceFilter.MatchColor = CIColor.FromRgba(red: 0.019f, green: 0.235f, blue: 0.458f, alpha: 1); | |
replaceFilter.ReplaceWithColor = CIColor.FromRgb(255, 0, 0); | |
thresholdSlider.ValueChanged += (sender, e) => | |
{ | |
replaceFilter.Threshold = thresholdSlider.Value; | |
var image = replaceFilter.OutputImage; | |
outputView.Image = UIImage.FromImage(image); | |
}; |
Author
sushihangover
commented
Nov 16, 2017
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment