Skip to content

Commit

Permalink
add nullability annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
YuAo committed Jan 27, 2016
1 parent aeba047 commit f6dc668
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 61 deletions.
4 changes: 4 additions & 0 deletions Sources/YUCIFilterConstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#import <Foundation/Foundation.h>
#import <CoreImage/CoreImage.h>

NS_ASSUME_NONNULL_BEGIN
/*
Using class with name `filterName` to construct a filter object.
*/
Expand All @@ -19,3 +21,5 @@
- (instancetype)init NS_UNAVAILABLE;

@end

NS_ASSUME_NONNULL_END
4 changes: 2 additions & 2 deletions Sources/YUCIHighPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

@interface YUCIHighPass : CIFilter

@property (nonatomic,strong) CIImage *inputImage;
@property (nonatomic, strong, nullable) CIImage *inputImage;

@property (nonatomic,copy) NSNumber *inputRadius; //default 1.0
@property (nonatomic, copy, null_resettable) NSNumber *inputRadius; //default 1.0

@end
8 changes: 4 additions & 4 deletions Sources/YUCIHighPassSkinSmoothing.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@

@interface YUCIHighPassSkinSmoothing : CIFilter

@property (nonatomic,strong) CIImage *inputImage;
@property (nonatomic, strong, nullable) CIImage *inputImage;

@property (nonatomic,copy) NSNumber *inputAmount; //default: 0.75
@property (nonatomic, copy, null_resettable) NSNumber *inputAmount; //default: 0.75

@property (nonatomic,copy) NSNumber *inputRadius; //default: 8.0
@property (nonatomic, copy, null_resettable) NSNumber *inputRadius; //default: 8.0

@property (nonatomic,copy) NSArray<CIVector *> *inputToneCurveControlPoints; //default: (0,0) (120/255.0,146/255.0) (1,1)
@property (nonatomic, copy, null_resettable) NSArray<CIVector *> *inputToneCurveControlPoints; //default: (0,0) (120/255.0,146/255.0) (1,1)

@end
19 changes: 13 additions & 6 deletions Sources/YUCIHighPassSkinSmoothing.m
Original file line number Diff line number Diff line change
Expand Up @@ -134,25 +134,32 @@ - (NSNumber *)inputRadius {
- (YUCIRGBToneCurve *)skinToneCurveFilter {
if (!_skinToneCurveFilter) {
_skinToneCurveFilter = [[YUCIRGBToneCurve alloc] init];
_skinToneCurveFilter.rgbCompositeControlPoints = @[[CIVector vectorWithX:0 Y:0],
[CIVector vectorWithX:120/255.0 Y:146/255.0],
[CIVector vectorWithX:1.0 Y:1.0]];
_skinToneCurveFilter.inputRGBCompositeControlPoints = self.defaultInputRGBCompositeControlPoints;
}
return _skinToneCurveFilter;
}

- (NSArray<CIVector *> *)defaultInputRGBCompositeControlPoints {
return @[[CIVector vectorWithX:0 Y:0],
[CIVector vectorWithX:120/255.0 Y:146/255.0],
[CIVector vectorWithX:1.0 Y:1.0]];
}

- (void)setInputToneCurveControlPoints:(NSArray<CIVector *> *)inputToneCurveControlPoints {
self.skinToneCurveFilter.rgbCompositeControlPoints = inputToneCurveControlPoints;
if (inputToneCurveControlPoints.count == 0) {
inputToneCurveControlPoints = self.defaultInputRGBCompositeControlPoints;
}
self.skinToneCurveFilter.inputRGBCompositeControlPoints = inputToneCurveControlPoints;
}

- (NSArray<CIVector *> *)inputToneCurveControlPoints {
return self.skinToneCurveFilter.rgbCompositeControlPoints;
return self.skinToneCurveFilter.inputRGBCompositeControlPoints;
}

- (void)setDefaults {
self.inputAmount = nil;
self.inputRadius = nil;
self.skinToneCurveFilter = nil;
self.inputToneCurveControlPoints = nil;
}

- (CIImage *)outputImage {
Expand Down
4 changes: 4 additions & 0 deletions Sources/YUCIMetalUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>

NS_ASSUME_NONNULL_BEGIN

@interface YUCIMetalUtilities : NSObject

+ (id<MTLTexture>)textureFromCGImage:(CGImageRef)imageRef device:(id<MTLDevice>)device;

@end

NS_ASSUME_NONNULL_END

#endif
12 changes: 6 additions & 6 deletions Sources/YUCIRGBToneCurve.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@

@interface YUCIRGBToneCurve : CIFilter

@property (nonatomic,strong) CIImage *inputImage;
@property (nonatomic, strong, nullable) CIImage *inputImage;

@property(nonatomic, copy) NSArray<CIVector *> *redControlPoints;
@property(nonatomic, copy) NSArray<CIVector *> *greenControlPoints;
@property(nonatomic, copy) NSArray<CIVector *> *blueControlPoints;
@property(nonatomic, copy) NSArray<CIVector *> *rgbCompositeControlPoints;
@property (nonatomic, copy, null_resettable) NSArray<CIVector *> *inputRedControlPoints;
@property (nonatomic, copy, null_resettable) NSArray<CIVector *> *inputGreenControlPoints;
@property (nonatomic, copy, null_resettable) NSArray<CIVector *> *inputBlueControlPoints;
@property (nonatomic, copy, null_resettable) NSArray<CIVector *> *inputRGBCompositeControlPoints;

@property (nonatomic,copy) NSNumber *inputIntensity; //default 1.0
@property (nonatomic, copy, null_resettable) NSNumber *inputIntensity; //default 1.0

@end
138 changes: 96 additions & 42 deletions Sources/YUCIRGBToneCurve.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@

@interface YUCIRGBToneCurve ()

@property (nonatomic,copy) NSArray *redCurve, *greenCurve, *blueCurve, *rgbCompositeCurve;
@property (nonatomic,copy) NSArray<NSNumber *> *redCurve, *greenCurve, *blueCurve, *rgbCompositeCurve;

@property (nonatomic,strong) CIImage *toneCurveTexture;

@end

@implementation YUCIRGBToneCurve

@synthesize inputRGBCompositeControlPoints = _inputRGBCompositeControlPoints;
@synthesize inputRedControlPoints = _inputRedControlPoints;
@synthesize inputGreenControlPoints = _inputGreenControlPoints;
@synthesize inputBlueControlPoints = _inputBlueControlPoints;

+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Expand Down Expand Up @@ -55,28 +60,17 @@ - (NSNumber *)inputIntensity {

- (void)setDefaults {
self.inputIntensity = nil;
self.redControlPoints = self.defaultCurveControlPoints;
self.greenControlPoints = self.defaultCurveControlPoints;
self.blueControlPoints = self.defaultCurveControlPoints;
self.rgbCompositeControlPoints = self.defaultCurveControlPoints;
self.inputRedControlPoints = self.defaultCurveControlPoints;
self.inputGreenControlPoints = self.defaultCurveControlPoints;
self.inputBlueControlPoints = self.defaultCurveControlPoints;
self.inputRGBCompositeControlPoints = self.defaultCurveControlPoints;
}

- (CIImage *)outputImage {
NSArray *defaultCurve = self.defaultCurveControlPoints;
if (self.redControlPoints.count == 0) {
self.redControlPoints = defaultCurve;
}
if (self.greenControlPoints.count == 0) {
self.greenControlPoints = defaultCurve;
}
if (self.blueControlPoints.count == 0) {
self.blueControlPoints = defaultCurve;
}
if (self.rgbCompositeControlPoints.count == 0) {
self.rgbCompositeControlPoints = defaultCurve;
if (!self.toneCurveTexture) {
[self validateInputs];
[self updateToneCurveTexture];
}
[self updateToneCurveTexture];

return [[YUCIRGBToneCurve filterKernel] applyWithExtent:self.inputImage.extent
roiCallback:^CGRect(int index, CGRect destRect) {
if (index == 0) {
Expand All @@ -91,49 +85,109 @@ - (CIImage *)outputImage {
}

- (void)updateToneCurveTexture {
if (self.redCurve.count == 256 && self.greenCurve.count == 256 && self.blueCurve.count == 256 && self.rgbCompositeCurve.count == 256) {
if (self.redCurve.count == 256 &&
self.greenCurve.count == 256 &&
self.blueCurve.count == 256 &&
self.rgbCompositeCurve.count == 256)
{
uint8_t *toneCurveByteArray = calloc(256 * 4, sizeof(uint8_t));
for (unsigned int currentCurveIndex = 0; currentCurveIndex < 256; currentCurveIndex++)
{
// BGRA for upload to texture
uint8_t b = fmin(fmax(currentCurveIndex + [[self.blueCurve objectAtIndex:currentCurveIndex] floatValue], 0), 255);
toneCurveByteArray[currentCurveIndex * 4] = fmin(fmax(b + [[self.rgbCompositeCurve objectAtIndex:b] floatValue], 0), 255);
uint8_t g = fmin(fmax(currentCurveIndex + [[self.greenCurve objectAtIndex:currentCurveIndex] floatValue], 0), 255);
toneCurveByteArray[currentCurveIndex * 4 + 1] = fmin(fmax(g + [[self.rgbCompositeCurve objectAtIndex:g] floatValue], 0), 255);
uint8_t r = fmin(fmax(currentCurveIndex + [[self.redCurve objectAtIndex:currentCurveIndex] floatValue], 0), 255);
toneCurveByteArray[currentCurveIndex * 4 + 2] = fmin(fmax(r + [[self.rgbCompositeCurve objectAtIndex:r] floatValue], 0), 255);
uint8_t b = fmin(fmax(currentCurveIndex + self.blueCurve[currentCurveIndex].floatValue, 0), 255);
toneCurveByteArray[currentCurveIndex * 4] = fmin(fmax(b + self.rgbCompositeCurve[b].floatValue, 0), 255);
uint8_t g = fmin(fmax(currentCurveIndex + self.greenCurve[currentCurveIndex].floatValue, 0), 255);
toneCurveByteArray[currentCurveIndex * 4 + 1] = fmin(fmax(g + self.rgbCompositeCurve[g].floatValue, 0), 255);
uint8_t r = fmin(fmax(currentCurveIndex + self.redCurve[currentCurveIndex].floatValue, 0), 255);
toneCurveByteArray[currentCurveIndex * 4 + 2] = fmin(fmax(r + self.rgbCompositeCurve[r].floatValue, 0), 255);
toneCurveByteArray[currentCurveIndex * 4 + 3] = 255;
}
CIImage *toneCurveTexture = [CIImage imageWithBitmapData:[NSData dataWithBytesNoCopy:toneCurveByteArray length:256 * 4 * sizeof(uint8_t) freeWhenDone:YES] bytesPerRow:256 * 4 * sizeof(uint8_t) size:CGSizeMake(256, 1) format:kCIFormatBGRA8 colorSpace:nil];
self.toneCurveTexture = toneCurveTexture;
}
}

- (void)setRgbCompositeControlPoints:(NSArray *)newValue
{
_rgbCompositeControlPoints = [newValue copy];
_rgbCompositeCurve = [self getPreparedSplineCurve:_rgbCompositeControlPoints];
- (void)validateInputs {
if (_inputRGBCompositeControlPoints.count == 0 ||
_inputRedControlPoints.count == 0 ||
_inputGreenControlPoints.count == 0 ||
_inputBlueControlPoints.count == 0)
{
NSArray *defaultControlPoints = self.defaultCurveControlPoints;
NSArray *defaultCurve = [self getPreparedSplineCurve:defaultControlPoints];
if (_inputRGBCompositeControlPoints.count == 0) {
_inputRGBCompositeControlPoints = defaultControlPoints.copy;
_rgbCompositeCurve = defaultCurve.copy;
}
if (_inputRedControlPoints.count == 0) {
_inputRedControlPoints = defaultControlPoints.copy;
_redCurve = defaultCurve.copy;
}
if (_inputGreenControlPoints.count == 0) {
_inputGreenControlPoints = defaultControlPoints.copy;
_greenCurve = defaultCurve.copy;
}
if (_inputBlueControlPoints.count == 0) {
_inputBlueControlPoints = defaultControlPoints.copy;
_blueCurve = defaultCurve.copy;
}
}
}

- (NSArray<CIVector *> *)inputRGBCompositeControlPoints {
[self validateInputs];
return _inputRGBCompositeControlPoints;
}

- (void)setRedControlPoints:(NSArray *)newValue;
{
_redControlPoints = [newValue copy];
_redCurve = [self getPreparedSplineCurve:_redControlPoints];
- (NSArray<CIVector *> *)inputRedControlPoints {
[self validateInputs];
return _inputRedControlPoints;
}

- (NSArray<CIVector *> *)inputGreenControlPoints {
[self validateInputs];
return _inputGreenControlPoints;
}

- (void)setGreenControlPoints:(NSArray *)newValue
{
_greenControlPoints = [newValue copy];
_greenCurve = [self getPreparedSplineCurve:_greenControlPoints];
- (NSArray<CIVector *> *)inputBlueControlPoints {
[self validateInputs];
return _inputBlueControlPoints;
}

- (void)setInputRGBCompositeControlPoints:(NSArray<CIVector *> *)inputRGBCompositeControlPoints {
if (![_inputRGBCompositeControlPoints isEqualToArray:inputRGBCompositeControlPoints]) {
_inputRGBCompositeControlPoints = inputRGBCompositeControlPoints.copy;
_rgbCompositeCurve = [self getPreparedSplineCurve:_inputRGBCompositeControlPoints];
[self validateInputs];
[self updateToneCurveTexture];
}
}

- (void)setBlueControlPoints:(NSArray *)newValue
{
_blueControlPoints = [newValue copy];
_blueCurve = [self getPreparedSplineCurve:_blueControlPoints];
- (void)setInputRedControlPoints:(NSArray<CIVector *> *)inputRedControlPoints {
if (![_inputRedControlPoints isEqualToArray:inputRedControlPoints]) {
_inputRedControlPoints = inputRedControlPoints.copy;
_redCurve = [self getPreparedSplineCurve:_inputRedControlPoints];
[self validateInputs];
[self updateToneCurveTexture];
}
}

- (void)setInputGreenControlPoints:(NSArray<CIVector *> *)inputGreenControlPoints {
if (![_inputGreenControlPoints isEqualToArray:inputGreenControlPoints]) {
_inputGreenControlPoints = inputGreenControlPoints.copy;
_greenCurve = [self getPreparedSplineCurve:_inputGreenControlPoints];
[self validateInputs];
[self updateToneCurveTexture];
}
}

- (void)setInputBlueControlPoints:(NSArray<CIVector *> *)inputBlueControlPoints {
if (![_inputBlueControlPoints isEqualToArray:inputBlueControlPoints]) {
_inputBlueControlPoints = inputBlueControlPoints.copy;
_blueCurve = [self getPreparedSplineCurve:_inputBlueControlPoints];
[self validateInputs];
[self updateToneCurveTexture];
}
}

#pragma mark - Curve calculation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class MetalRenderContextViewController: UIViewController, MTKViewDelegate {
func drawInMTKView(view: MTKView) {
let commandBuffer = self.commandQueue.commandBuffer()

let texture = YUCIMetalUtilities.textureFromCGImage(UIImage(named: "SampleImage")!.CGImage!, device: self.metalView.device)
let texture = YUCIMetalUtilities.textureFromCGImage(UIImage(named: "SampleImage")!.CGImage!, device: self.metalView.device!)
let inputCIImage = CIImage(MTLTexture: texture, options: nil)
let filter = CIFilter(name: "YUCIHighPassSkinSmoothing")!
filter.setValue(inputCIImage, forKey: kCIInputImageKey)
Expand Down

0 comments on commit f6dc668

Please sign in to comment.