Merge pull request #2918 from dreampiggy/feature_transformer_CIImage
Support all transformer method on CIImage based UIImage/NSImage
This commit is contained in:
commit
fafed705d0
|
@ -19,6 +19,10 @@
|
||||||
The underlying Core Graphics image object. This will actually use `CGImageForProposedRect` with the image size.
|
The underlying Core Graphics image object. This will actually use `CGImageForProposedRect` with the image size.
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, readonly, nullable) CGImageRef CGImage;
|
@property (nonatomic, readonly, nullable) CGImageRef CGImage;
|
||||||
|
/**
|
||||||
|
The underlying Core Image data. This will actually use `bestRepresentationForRect` with the image size to find the `NSCIImageRep`.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, nullable) CIImage *CIImage;
|
||||||
/**
|
/**
|
||||||
The scale factor of the image. This wil actually use `bestRepresentationForRect` with image size and pixel size to calculate the scale factor. If failed, use the default value 1.0. Should be greater than or equal to 1.0.
|
The scale factor of the image. This wil actually use `bestRepresentationForRect` with image size and pixel size to calculate the scale factor. If failed, use the default value 1.0. Should be greater than or equal to 1.0.
|
||||||
*/
|
*/
|
||||||
|
@ -38,6 +42,16 @@ The underlying Core Graphics image object. This will actually use `CGImageForPro
|
||||||
*/
|
*/
|
||||||
- (nonnull instancetype)initWithCGImage:(nonnull CGImageRef)cgImage scale:(CGFloat)scale orientation:(CGImagePropertyOrientation)orientation;
|
- (nonnull instancetype)initWithCGImage:(nonnull CGImageRef)cgImage scale:(CGFloat)scale orientation:(CGImagePropertyOrientation)orientation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes and returns an image object with the specified Core Image object. The representation is `NSCIImageRep`.
|
||||||
|
|
||||||
|
@param ciImage A Core Image image object
|
||||||
|
@param scale The image scale factor
|
||||||
|
@param orientation The orientation of the image data
|
||||||
|
@return The image object
|
||||||
|
*/
|
||||||
|
- (nonnull instancetype)initWithCIImage:(nonnull CIImage *)ciImage scale:(CGFloat)scale orientation:(CGImagePropertyOrientation)orientation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns an image object with the scale factor. The representation is created from the image data.
|
Returns an image object with the scale factor. The representation is created from the image data.
|
||||||
@note The difference between these this and `initWithData:` is that `initWithData:` will always use `backingScaleFactor` as scale factor.
|
@note The difference between these this and `initWithData:` is that `initWithData:` will always use `backingScaleFactor` as scale factor.
|
||||||
|
|
|
@ -20,6 +20,15 @@
|
||||||
return cgImage;
|
return cgImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (nullable CIImage *)CIImage {
|
||||||
|
NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height);
|
||||||
|
NSImageRep *imageRep = [self bestRepresentationForRect:imageRect context:nil hints:nil];
|
||||||
|
if (![imageRep isKindOfClass:NSCIImageRep.class]) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return ((NSCIImageRep *)imageRep).CIImage;
|
||||||
|
}
|
||||||
|
|
||||||
- (CGFloat)scale {
|
- (CGFloat)scale {
|
||||||
CGFloat scale = 1;
|
CGFloat scale = 1;
|
||||||
NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height);
|
NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height);
|
||||||
|
@ -65,6 +74,28 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithCIImage:(nonnull CIImage *)ciImage scale:(CGFloat)scale orientation:(CGImagePropertyOrientation)orientation {
|
||||||
|
NSCIImageRep *imageRep;
|
||||||
|
if (orientation != kCGImagePropertyOrientationUp) {
|
||||||
|
CIImage *rotatedCIImage = [ciImage imageByApplyingOrientation:orientation];
|
||||||
|
imageRep = [[NSCIImageRep alloc] initWithCIImage:rotatedCIImage];
|
||||||
|
} else {
|
||||||
|
imageRep = [[NSCIImageRep alloc] initWithCIImage:ciImage];
|
||||||
|
}
|
||||||
|
if (scale < 1) {
|
||||||
|
scale = 1;
|
||||||
|
}
|
||||||
|
CGFloat pixelWidth = imageRep.pixelsWide;
|
||||||
|
CGFloat pixelHeight = imageRep.pixelsHigh;
|
||||||
|
NSSize size = NSMakeSize(pixelWidth / scale, pixelHeight / scale);
|
||||||
|
self = [self initWithSize:size];
|
||||||
|
if (self) {
|
||||||
|
imageRep.size = size;
|
||||||
|
[self addRepresentation:imageRep];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
- (instancetype)initWithData:(nonnull NSData *)data scale:(CGFloat)scale {
|
- (instancetype)initWithData:(nonnull NSData *)data scale:(CGFloat)scale {
|
||||||
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:data];
|
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:data];
|
||||||
if (!imageRep) {
|
if (!imageRep) {
|
||||||
|
|
|
@ -164,6 +164,21 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
return [UIColor colorWithRed:r green:g blue:b alpha:a];
|
return [UIColor colorWithRed:r green:g blue:b alpha:a];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SD_UIKIT || SD_MAC
|
||||||
|
// Core Image Support
|
||||||
|
static inline CGImageRef _Nullable SDCGImageFromCIImage(CIImage * _Nonnull ciImage) {
|
||||||
|
CGImageRef imageRef = NULL;
|
||||||
|
if (@available(iOS 10, macOS 10.12, tvOS 10, *)) {
|
||||||
|
imageRef = ciImage.CGImage;
|
||||||
|
}
|
||||||
|
if (!imageRef) {
|
||||||
|
CIContext *context = [CIContext context];
|
||||||
|
imageRef = [context createCGImage:ciImage fromRect:ciImage.extent];
|
||||||
|
}
|
||||||
|
return imageRef;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
@implementation UIImage (Transform)
|
@implementation UIImage (Transform)
|
||||||
|
|
||||||
- (void)sd_drawInRect:(CGRect)rect context:(CGContextRef)context scaleMode:(SDImageScaleMode)scaleMode clipsToBounds:(BOOL)clips {
|
- (void)sd_drawInRect:(CGRect)rect context:(CGContextRef)context scaleMode:(SDImageScaleMode)scaleMode clipsToBounds:(BOOL)clips {
|
||||||
|
@ -194,27 +209,45 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable UIImage *)sd_croppedImageWithRect:(CGRect)rect {
|
- (nullable UIImage *)sd_croppedImageWithRect:(CGRect)rect {
|
||||||
if (!self.CGImage) return nil;
|
|
||||||
rect.origin.x *= self.scale;
|
rect.origin.x *= self.scale;
|
||||||
rect.origin.y *= self.scale;
|
rect.origin.y *= self.scale;
|
||||||
rect.size.width *= self.scale;
|
rect.size.width *= self.scale;
|
||||||
rect.size.height *= self.scale;
|
rect.size.height *= self.scale;
|
||||||
if (rect.size.width <= 0 || rect.size.height <= 0) return nil;
|
if (rect.size.width <= 0 || rect.size.height <= 0) return nil;
|
||||||
CGImageRef imageRef = CGImageCreateWithImageInRect(self.CGImage, rect);
|
|
||||||
|
#if SD_UIKIT || SD_MAC
|
||||||
|
// CIImage shortcut
|
||||||
|
if (self.CIImage) {
|
||||||
|
CGRect croppingRect = CGRectMake(rect.origin.x, self.size.height - CGRectGetMaxY(rect), rect.size.width, rect.size.height);
|
||||||
|
CIImage *ciImage = [self.CIImage imageByCroppingToRect:croppingRect];
|
||||||
|
#if SD_UIKIT
|
||||||
|
UIImage *image = [UIImage imageWithCIImage:ciImage scale:self.scale orientation:self.imageOrientation];
|
||||||
|
#else
|
||||||
|
UIImage *image = [[UIImage alloc] initWithCIImage:ciImage scale:self.scale orientation:kCGImagePropertyOrientationUp];
|
||||||
|
#endif
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CGImageRef imageRef = self.CGImage;
|
||||||
if (!imageRef) {
|
if (!imageRef) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGImageRef croppedImageRef = CGImageCreateWithImageInRect(imageRef, rect);
|
||||||
|
if (!croppedImageRef) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
#if SD_UIKIT || SD_WATCH
|
#if SD_UIKIT || SD_WATCH
|
||||||
UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
|
UIImage *image = [UIImage imageWithCGImage:croppedImageRef scale:self.scale orientation:self.imageOrientation];
|
||||||
#else
|
#else
|
||||||
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:self.scale orientation:kCGImagePropertyOrientationUp];
|
UIImage *image = [[UIImage alloc] initWithCGImage:croppedImageRef scale:self.scale orientation:kCGImagePropertyOrientationUp];
|
||||||
#endif
|
#endif
|
||||||
CGImageRelease(imageRef);
|
CGImageRelease(croppedImageRef);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable UIImage *)sd_roundedCornerImageWithRadius:(CGFloat)cornerRadius corners:(SDRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(nullable UIColor *)borderColor {
|
- (nullable UIImage *)sd_roundedCornerImageWithRadius:(CGFloat)cornerRadius corners:(SDRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(nullable UIColor *)borderColor {
|
||||||
if (!self.CGImage) return nil;
|
|
||||||
SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] init];
|
SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] init];
|
||||||
format.scale = self.scale;
|
format.scale = self.scale;
|
||||||
SDGraphicsImageRenderer *renderer = [[SDGraphicsImageRenderer alloc] initWithSize:self.size format:format];
|
SDGraphicsImageRenderer *renderer = [[SDGraphicsImageRenderer alloc] initWithSize:self.size format:format];
|
||||||
|
@ -256,11 +289,32 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable UIImage *)sd_rotatedImageWithAngle:(CGFloat)angle fitSize:(BOOL)fitSize {
|
- (nullable UIImage *)sd_rotatedImageWithAngle:(CGFloat)angle fitSize:(BOOL)fitSize {
|
||||||
if (!self.CGImage) return nil;
|
|
||||||
size_t width = self.size.width;
|
size_t width = self.size.width;
|
||||||
size_t height = self.size.height;
|
size_t height = self.size.height;
|
||||||
CGRect newRect = CGRectApplyAffineTransform(CGRectMake(0, 0, width, height),
|
CGRect newRect = CGRectApplyAffineTransform(CGRectMake(0, 0, width, height),
|
||||||
fitSize ? CGAffineTransformMakeRotation(angle) : CGAffineTransformIdentity);
|
fitSize ? CGAffineTransformMakeRotation(angle) : CGAffineTransformIdentity);
|
||||||
|
|
||||||
|
#if SD_UIKIT || SD_MAC
|
||||||
|
// CIImage shortcut
|
||||||
|
if (self.CIImage) {
|
||||||
|
CIImage *ciImage = self.CIImage;
|
||||||
|
if (fitSize) {
|
||||||
|
CGAffineTransform transform = CGAffineTransformMakeRotation(angle);
|
||||||
|
ciImage = [ciImage imageByApplyingTransform:transform];
|
||||||
|
} else {
|
||||||
|
CIFilter *filter = [CIFilter filterWithName:@"CIStraightenFilter"];
|
||||||
|
[filter setValue:ciImage forKey:kCIInputImageKey];
|
||||||
|
[filter setValue:@(angle) forKey:kCIInputAngleKey];
|
||||||
|
ciImage = filter.outputImage;
|
||||||
|
}
|
||||||
|
#if SD_UIKIT || SD_WATCH
|
||||||
|
UIImage *image = [UIImage imageWithCIImage:ciImage scale:self.scale orientation:self.imageOrientation];
|
||||||
|
#else
|
||||||
|
UIImage *image = [[UIImage alloc] initWithCIImage:ciImage scale:self.scale orientation:kCGImagePropertyOrientationUp];
|
||||||
|
#endif
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] init];
|
SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] init];
|
||||||
format.scale = self.scale;
|
format.scale = self.scale;
|
||||||
|
@ -283,9 +337,31 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable UIImage *)sd_flippedImageWithHorizontal:(BOOL)horizontal vertical:(BOOL)vertical {
|
- (nullable UIImage *)sd_flippedImageWithHorizontal:(BOOL)horizontal vertical:(BOOL)vertical {
|
||||||
if (!self.CGImage) return nil;
|
|
||||||
size_t width = self.size.width;
|
size_t width = self.size.width;
|
||||||
size_t height = self.size.height;
|
size_t height = self.size.height;
|
||||||
|
|
||||||
|
#if SD_UIKIT || SD_MAC
|
||||||
|
// CIImage shortcut
|
||||||
|
if (self.CIImage) {
|
||||||
|
CGAffineTransform transform = CGAffineTransformIdentity;
|
||||||
|
// Use UIKit coordinate system
|
||||||
|
if (horizontal) {
|
||||||
|
CGAffineTransform flipHorizontal = CGAffineTransformMake(-1, 0, 0, 1, width, 0);
|
||||||
|
transform = CGAffineTransformConcat(transform, flipHorizontal);
|
||||||
|
}
|
||||||
|
if (vertical) {
|
||||||
|
CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, height);
|
||||||
|
transform = CGAffineTransformConcat(transform, flipVertical);
|
||||||
|
}
|
||||||
|
CIImage *ciImage = [self.CIImage imageByApplyingTransform:transform];
|
||||||
|
#if SD_UIKIT
|
||||||
|
UIImage *image = [UIImage imageWithCIImage:ciImage scale:self.scale orientation:self.imageOrientation];
|
||||||
|
#else
|
||||||
|
UIImage *image = [[UIImage alloc] initWithCIImage:ciImage scale:self.scale orientation:kCGImagePropertyOrientationUp];
|
||||||
|
#endif
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] init];
|
SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] init];
|
||||||
format.scale = self.scale;
|
format.scale = self.scale;
|
||||||
|
@ -308,18 +384,30 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
#pragma mark - Image Blending
|
#pragma mark - Image Blending
|
||||||
|
|
||||||
- (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor {
|
- (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor {
|
||||||
if (!self.CGImage) return nil;
|
|
||||||
if (!tintColor.CGColor) return nil;
|
|
||||||
|
|
||||||
BOOL hasTint = CGColorGetAlpha(tintColor.CGColor) > __FLT_EPSILON__;
|
BOOL hasTint = CGColorGetAlpha(tintColor.CGColor) > __FLT_EPSILON__;
|
||||||
if (!hasTint) {
|
if (!hasTint) {
|
||||||
#if SD_UIKIT || SD_WATCH
|
return self;
|
||||||
return [UIImage imageWithCGImage:self.CGImage scale:self.scale orientation:self.imageOrientation];
|
|
||||||
#else
|
|
||||||
return [[UIImage alloc] initWithCGImage:self.CGImage scale:self.scale orientation:kCGImagePropertyOrientationUp];
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SD_UIKIT || SD_MAC
|
||||||
|
// CIImage shortcut
|
||||||
|
if (self.CIImage) {
|
||||||
|
CIImage *ciImage = self.CIImage;
|
||||||
|
CIImage *colorImage = [CIImage imageWithColor:[[CIColor alloc] initWithColor:tintColor]];
|
||||||
|
colorImage = [colorImage imageByCroppingToRect:ciImage.extent];
|
||||||
|
CIFilter *filter = [CIFilter filterWithName:@"CISourceAtopCompositing"];
|
||||||
|
[filter setValue:colorImage forKey:kCIInputImageKey];
|
||||||
|
[filter setValue:ciImage forKey:kCIInputBackgroundImageKey];
|
||||||
|
ciImage = filter.outputImage;
|
||||||
|
#if SD_UIKIT
|
||||||
|
UIImage *image = [UIImage imageWithCIImage:ciImage scale:self.scale orientation:self.imageOrientation];
|
||||||
|
#else
|
||||||
|
UIImage *image = [[UIImage alloc] initWithCIImage:ciImage scale:self.scale orientation:kCGImagePropertyOrientationUp];
|
||||||
|
#endif
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CGSize size = self.size;
|
CGSize size = self.size;
|
||||||
CGRect rect = { CGPointZero, size };
|
CGRect rect = { CGPointZero, size };
|
||||||
CGFloat scale = self.scale;
|
CGFloat scale = self.scale;
|
||||||
|
@ -340,10 +428,16 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable UIColor *)sd_colorAtPoint:(CGPoint)point {
|
- (nullable UIColor *)sd_colorAtPoint:(CGPoint)point {
|
||||||
if (!self) {
|
CGImageRef imageRef = NULL;
|
||||||
return nil;
|
// CIImage compatible
|
||||||
|
#if SD_UIKIT || SD_MAC
|
||||||
|
if (self.CIImage) {
|
||||||
|
imageRef = SDCGImageFromCIImage(self.CIImage);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!imageRef) {
|
||||||
|
imageRef = self.CGImage;
|
||||||
}
|
}
|
||||||
CGImageRef imageRef = self.CGImage;
|
|
||||||
if (!imageRef) {
|
if (!imageRef) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -384,10 +478,16 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable NSArray<UIColor *> *)sd_colorsWithRect:(CGRect)rect {
|
- (nullable NSArray<UIColor *> *)sd_colorsWithRect:(CGRect)rect {
|
||||||
if (!self) {
|
CGImageRef imageRef = NULL;
|
||||||
return nil;
|
// CIImage compatible
|
||||||
|
#if SD_UIKIT || SD_MAC
|
||||||
|
if (self.CIImage) {
|
||||||
|
imageRef = SDCGImageFromCIImage(self.CIImage);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!imageRef) {
|
||||||
|
imageRef = self.CGImage;
|
||||||
}
|
}
|
||||||
CGImageRef imageRef = self.CGImage;
|
|
||||||
if (!imageRef) {
|
if (!imageRef) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -451,18 +551,41 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
if (self.size.width < 1 || self.size.height < 1) {
|
if (self.size.width < 1 || self.size.height < 1) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
if (!self.CGImage) {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL hasBlur = blurRadius > __FLT_EPSILON__;
|
BOOL hasBlur = blurRadius > __FLT_EPSILON__;
|
||||||
if (!hasBlur) {
|
if (!hasBlur) {
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SD_UIKIT || SD_MAC
|
||||||
|
if (self.CIImage) {
|
||||||
|
CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
|
||||||
|
[filter setValue:self.CIImage forKey:kCIInputImageKey];
|
||||||
|
// Blur Radius use pixel count
|
||||||
|
[filter setValue:@(blurRadius / 2) forKey:kCIInputRadiusKey];
|
||||||
|
CIImage *ciImage = filter.outputImage;
|
||||||
|
ciImage = [ciImage imageByCroppingToRect:CGRectMake(0, 0, self.size.width, self.size.height)];
|
||||||
|
#if SD_UIKIT
|
||||||
|
UIImage *image = [UIImage imageWithCIImage:ciImage scale:self.scale orientation:self.imageOrientation];
|
||||||
|
#else
|
||||||
|
UIImage *image = [[UIImage alloc] initWithCIImage:ciImage scale:self.scale orientation:kCGImagePropertyOrientationUp];
|
||||||
|
#endif
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CGFloat scale = self.scale;
|
CGFloat scale = self.scale;
|
||||||
CGImageRef imageRef = self.CGImage;
|
CGImageRef imageRef = self.CGImage;
|
||||||
|
|
||||||
|
//convert to BGRA if it isn't
|
||||||
|
if (CGImageGetBitsPerPixel(imageRef) != 32 ||
|
||||||
|
CGImageGetBitsPerComponent(imageRef) != 8 ||
|
||||||
|
!((CGImageGetBitmapInfo(imageRef) & kCGBitmapAlphaInfoMask))) {
|
||||||
|
SDGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
|
||||||
|
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
|
||||||
|
imageRef = SDGraphicsGetImageFromCurrentImageContext().CGImage;
|
||||||
|
SDGraphicsEndImageContext();
|
||||||
|
}
|
||||||
|
|
||||||
vImage_Buffer effect = {}, scratch = {};
|
vImage_Buffer effect = {}, scratch = {};
|
||||||
vImage_Buffer *input = NULL, *output = NULL;
|
vImage_Buffer *input = NULL, *output = NULL;
|
||||||
|
|
||||||
|
@ -477,7 +600,7 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
};
|
};
|
||||||
|
|
||||||
vImage_Error err;
|
vImage_Error err;
|
||||||
err = vImageBuffer_InitWithCGImage(&effect, &format, NULL, imageRef, kvImagePrintDiagnosticsToConsole);
|
err = vImageBuffer_InitWithCGImage(&effect, &format, NULL, imageRef, kvImageNoFlags);
|
||||||
if (err != kvImageNoError) {
|
if (err != kvImageNoError) {
|
||||||
NSLog(@"UIImage+Transform error: vImageBuffer_InitWithCGImage returned error code %zi for inputImage: %@", err, self);
|
NSLog(@"UIImage+Transform error: vImageBuffer_InitWithCGImage returned error code %zi for inputImage: %@", err, self);
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -542,12 +665,19 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
|
||||||
|
|
||||||
#if SD_UIKIT || SD_MAC
|
#if SD_UIKIT || SD_MAC
|
||||||
- (nullable UIImage *)sd_filteredImageWithFilter:(nonnull CIFilter *)filter {
|
- (nullable UIImage *)sd_filteredImageWithFilter:(nonnull CIFilter *)filter {
|
||||||
if (!self.CGImage) return nil;
|
CIImage *inputImage;
|
||||||
|
if (self.CIImage) {
|
||||||
CIContext *context = [CIContext context];
|
inputImage = self.CIImage;
|
||||||
CIImage *inputImage = [CIImage imageWithCGImage:self.CGImage];
|
} else {
|
||||||
|
CGImageRef imageRef = self.CGImage;
|
||||||
|
if (!imageRef) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
inputImage = [CIImage imageWithCGImage:imageRef];
|
||||||
|
}
|
||||||
if (!inputImage) return nil;
|
if (!inputImage) return nil;
|
||||||
|
|
||||||
|
CIContext *context = [CIContext context];
|
||||||
[filter setValue:inputImage forKey:kCIInputImageKey];
|
[filter setValue:inputImage forKey:kCIInputImageKey];
|
||||||
CIImage *outputImage = filter.outputImage;
|
CIImage *outputImage = filter.outputImage;
|
||||||
if (!outputImage) return nil;
|
if (!outputImage) return nil;
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
|
|
||||||
@interface SDImageTransformerTests : SDTestCase
|
@interface SDImageTransformerTests : SDTestCase
|
||||||
|
|
||||||
@property (nonatomic, strong) UIImage *testImage;
|
@property (nonatomic, strong) UIImage *testImageCG;
|
||||||
|
@property (nonatomic, strong) UIImage *testImageCI;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -22,21 +23,37 @@
|
||||||
#pragma mark - UIImage+Transform
|
#pragma mark - UIImage+Transform
|
||||||
|
|
||||||
// UIImage+Transform test is hard to write because it's more about visual effect. Current it's tied to the `TestImage.png`, please keep that image or write new test with new image
|
// UIImage+Transform test is hard to write because it's more about visual effect. Current it's tied to the `TestImage.png`, please keep that image or write new test with new image
|
||||||
- (void)test01UIImageTransformResize {
|
- (void)test01UIImageTransformResizeCG {
|
||||||
|
[self test01UIImageTransformResizeWithImage:self.testImageCG];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test01UIImageTransformResizeCI {
|
||||||
|
[self test01UIImageTransformResizeWithImage:self.testImageCI];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test01UIImageTransformResizeWithImage:(UIImage *)testImage {
|
||||||
CGSize scaleDownSize = CGSizeMake(200, 100);
|
CGSize scaleDownSize = CGSizeMake(200, 100);
|
||||||
UIImage *scaledDownImage = [self.testImage sd_resizedImageWithSize:scaleDownSize scaleMode:SDImageScaleModeFill];
|
UIImage *scaledDownImage = [testImage sd_resizedImageWithSize:scaleDownSize scaleMode:SDImageScaleModeFill];
|
||||||
expect(CGSizeEqualToSize(scaledDownImage.size, scaleDownSize)).beTruthy();
|
expect(CGSizeEqualToSize(scaledDownImage.size, scaleDownSize)).beTruthy();
|
||||||
CGSize scaleUpSize = CGSizeMake(2000, 1000);
|
CGSize scaleUpSize = CGSizeMake(2000, 1000);
|
||||||
UIImage *scaledUpImage = [self.testImage sd_resizedImageWithSize:scaleUpSize scaleMode:SDImageScaleModeAspectFit];
|
UIImage *scaledUpImage = [testImage sd_resizedImageWithSize:scaleUpSize scaleMode:SDImageScaleModeAspectFit];
|
||||||
expect(CGSizeEqualToSize(scaledUpImage.size, scaleUpSize)).beTruthy();
|
expect(CGSizeEqualToSize(scaledUpImage.size, scaleUpSize)).beTruthy();
|
||||||
// Check image not inversion
|
// Check image not inversion
|
||||||
UIColor *topCenterColor = [scaledUpImage sd_colorAtPoint:CGPointMake(1000, 50)];
|
UIColor *topCenterColor = [scaledUpImage sd_colorAtPoint:CGPointMake(1000, 50)];
|
||||||
expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)test02UIImageTransformCrop {
|
- (void)test02UIImageTransformCropCG {
|
||||||
|
[self test02UIImageTransformCropWithImage:self.testImageCG];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test02UIImageTransformCropCI {
|
||||||
|
[self test02UIImageTransformCropWithImage:self.testImageCI];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test02UIImageTransformCropWithImage:(UIImage *)testImage {
|
||||||
CGRect rect = CGRectMake(50, 10, 200, 200);
|
CGRect rect = CGRectMake(50, 10, 200, 200);
|
||||||
UIImage *croppedImage = [self.testImage sd_croppedImageWithRect:rect];
|
UIImage *croppedImage = [testImage sd_croppedImageWithRect:rect];
|
||||||
expect(CGSizeEqualToSize(croppedImage.size, CGSizeMake(200, 200))).beTruthy();
|
expect(CGSizeEqualToSize(croppedImage.size, CGSizeMake(200, 200))).beTruthy();
|
||||||
UIColor *startColor = [croppedImage sd_colorAtPoint:CGPointZero];
|
UIColor *startColor = [croppedImage sd_colorAtPoint:CGPointZero];
|
||||||
expect([startColor.sd_hexString isEqualToString:[UIColor clearColor].sd_hexString]).beTruthy();
|
expect([startColor.sd_hexString isEqualToString:[UIColor clearColor].sd_hexString]).beTruthy();
|
||||||
|
@ -45,7 +62,15 @@
|
||||||
expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)test03UIImageTransformRoundedCorner {
|
- (void)test03UIImageTransformRoundedCornerCG {
|
||||||
|
[self test03UIImageTransformRoundedCornerWithImage:self.testImageCG];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test03UIImageTransformRoundedCornerCI {
|
||||||
|
[self test03UIImageTransformRoundedCornerWithImage:self.testImageCI];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test03UIImageTransformRoundedCornerWithImage:(UIImage *)testImage {
|
||||||
CGFloat radius = 50;
|
CGFloat radius = 50;
|
||||||
#if SD_UIKIT
|
#if SD_UIKIT
|
||||||
SDRectCorner corners = UIRectCornerAllCorners;
|
SDRectCorner corners = UIRectCornerAllCorners;
|
||||||
|
@ -54,7 +79,7 @@
|
||||||
#endif
|
#endif
|
||||||
CGFloat borderWidth = 1;
|
CGFloat borderWidth = 1;
|
||||||
UIColor *borderColor = [UIColor blackColor];
|
UIColor *borderColor = [UIColor blackColor];
|
||||||
UIImage *roundedCornerImage = [self.testImage sd_roundedCornerImageWithRadius:radius corners:corners borderWidth:borderWidth borderColor:borderColor];
|
UIImage *roundedCornerImage = [testImage sd_roundedCornerImageWithRadius:radius corners:corners borderWidth:borderWidth borderColor:borderColor];
|
||||||
expect(CGSizeEqualToSize(roundedCornerImage.size, CGSizeMake(300, 300))).beTruthy();
|
expect(CGSizeEqualToSize(roundedCornerImage.size, CGSizeMake(300, 300))).beTruthy();
|
||||||
UIColor *startColor = [roundedCornerImage sd_colorAtPoint:CGPointZero];
|
UIColor *startColor = [roundedCornerImage sd_colorAtPoint:CGPointZero];
|
||||||
expect([startColor.sd_hexString isEqualToString:[UIColor clearColor].sd_hexString]).beTruthy();
|
expect([startColor.sd_hexString isEqualToString:[UIColor clearColor].sd_hexString]).beTruthy();
|
||||||
|
@ -66,25 +91,42 @@
|
||||||
expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)test04UIImageTransformRotate {
|
- (void)test04UIImageTransformRotateCG {
|
||||||
|
[self test04UIImageTransformRotateWithImage:self.testImageCG];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test04UIImageTransformRotateCI {
|
||||||
|
[self test04UIImageTransformRotateWithImage:self.testImageCI];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test04UIImageTransformRotateWithImage:(UIImage *)testImage {
|
||||||
CGFloat angle = M_PI_4;
|
CGFloat angle = M_PI_4;
|
||||||
UIImage *rotatedImage = [self.testImage sd_rotatedImageWithAngle:angle fitSize:NO];
|
UIImage *rotatedImage = [testImage sd_rotatedImageWithAngle:angle fitSize:NO];
|
||||||
// Not fit size and no change
|
// Not fit size and no change
|
||||||
expect(CGSizeEqualToSize(rotatedImage.size, self.testImage.size)).beTruthy();
|
expect(CGSizeEqualToSize(rotatedImage.size, testImage.size)).beTruthy();
|
||||||
// Fit size, may change size
|
// Fit size, may change size
|
||||||
rotatedImage = [self.testImage sd_rotatedImageWithAngle:angle fitSize:YES];
|
rotatedImage = [testImage sd_rotatedImageWithAngle:angle fitSize:YES];
|
||||||
CGSize rotatedSize = CGSizeMake(ceil(300 * 1.414), ceil(300 * 1.414)); // 45º, square length * sqrt(2)
|
CGSize rotatedSize = CGSizeMake(ceil(300 * 1.414), ceil(300 * 1.414)); // 45º, square length * sqrt(2)
|
||||||
expect(CGSizeEqualToSize(rotatedImage.size, rotatedSize)).beTruthy();
|
expect(rotatedImage.size.width - rotatedSize.width <= 1).beTruthy();
|
||||||
|
expect(rotatedImage.size.height - rotatedSize.height <= 1).beTruthy();
|
||||||
// Check image not inversion
|
// Check image not inversion
|
||||||
UIColor *leftCenterColor = [rotatedImage sd_colorAtPoint:CGPointMake(60, 175)];
|
UIColor *leftCenterColor = [rotatedImage sd_colorAtPoint:CGPointMake(60, 175)];
|
||||||
expect([leftCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
expect([leftCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)test05UIImageTransformFlip {
|
- (void)test05UIImageTransformFlipCG {
|
||||||
|
[self test05UIImageTransformFlipWithImage:self.testImageCG];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test05UIImageTransformFlipCI {
|
||||||
|
[self test05UIImageTransformFlipWithImage:self.testImageCI];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test05UIImageTransformFlipWithImage:(UIImage *)testImage {
|
||||||
BOOL horizontal = YES;
|
BOOL horizontal = YES;
|
||||||
BOOL vertical = YES;
|
BOOL vertical = YES;
|
||||||
UIImage *flippedImage = [self.testImage sd_flippedImageWithHorizontal:horizontal vertical:vertical];
|
UIImage *flippedImage = [testImage sd_flippedImageWithHorizontal:horizontal vertical:vertical];
|
||||||
expect(CGSizeEqualToSize(flippedImage.size, self.testImage.size)).beTruthy();
|
expect(CGSizeEqualToSize(flippedImage.size, testImage.size)).beTruthy();
|
||||||
// Test pixel colors method here
|
// Test pixel colors method here
|
||||||
UIColor *checkColor = [flippedImage sd_colorAtPoint:CGPointMake(75, 75)];
|
UIColor *checkColor = [flippedImage sd_colorAtPoint:CGPointMake(75, 75)];
|
||||||
expect(checkColor);
|
expect(checkColor);
|
||||||
|
@ -98,10 +140,18 @@
|
||||||
expect([bottomCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
expect([bottomCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)test06UIImageTransformTint {
|
- (void)test06UIImageTransformTintCG {
|
||||||
|
[self test06UIImageTransformTintWithImage:self.testImageCG];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test06UIImageTransformTintCI {
|
||||||
|
[self test06UIImageTransformTintWithImage:self.testImageCI];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test06UIImageTransformTintWithImage:(UIImage *)testImage {
|
||||||
UIColor *tintColor = [UIColor blackColor];
|
UIColor *tintColor = [UIColor blackColor];
|
||||||
UIImage *tintedImage = [self.testImage sd_tintedImageWithColor:tintColor];
|
UIImage *tintedImage = [testImage sd_tintedImageWithColor:tintColor];
|
||||||
expect(CGSizeEqualToSize(tintedImage.size, self.testImage.size)).beTruthy();
|
expect(CGSizeEqualToSize(tintedImage.size, testImage.size)).beTruthy();
|
||||||
// Check center color, should keep clear
|
// Check center color, should keep clear
|
||||||
UIColor *centerColor = [tintedImage sd_colorAtPoint:CGPointMake(150, 150)];
|
UIColor *centerColor = [tintedImage sd_colorAtPoint:CGPointMake(150, 150)];
|
||||||
expect([centerColor.sd_hexString isEqualToString:[UIColor clearColor].sd_hexString]);
|
expect([centerColor.sd_hexString isEqualToString:[UIColor clearColor].sd_hexString]);
|
||||||
|
@ -113,10 +163,18 @@
|
||||||
expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
expect([topCenterColor.sd_hexString isEqualToString:[UIColor blackColor].sd_hexString]).beTruthy();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)test07UIImageTransformBlur {
|
- (void)test07UIImageTransformBlurCG {
|
||||||
|
[self test07UIImageTransformBlurWithImage:self.testImageCG];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test07UIImageTransformBlurCI {
|
||||||
|
[self test07UIImageTransformBlurWithImage:self.testImageCI];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test07UIImageTransformBlurWithImage:(UIImage *)testImage {
|
||||||
CGFloat radius = 50;
|
CGFloat radius = 50;
|
||||||
UIImage *blurredImage = [self.testImage sd_blurredImageWithRadius:radius];
|
UIImage *blurredImage = [testImage sd_blurredImageWithRadius:radius];
|
||||||
expect(CGSizeEqualToSize(blurredImage.size, self.testImage.size)).beTruthy();
|
expect(CGSizeEqualToSize(blurredImage.size, testImage.size)).beTruthy();
|
||||||
// Check left color, should be blurred
|
// Check left color, should be blurred
|
||||||
UIColor *leftColor = [blurredImage sd_colorAtPoint:CGPointMake(80, 150)];
|
UIColor *leftColor = [blurredImage sd_colorAtPoint:CGPointMake(80, 150)];
|
||||||
// Hard-code from the output
|
// Hard-code from the output
|
||||||
|
@ -124,14 +182,23 @@
|
||||||
expect([leftColor.sd_hexString isEqualToString:expectedColor.sd_hexString]);
|
expect([leftColor.sd_hexString isEqualToString:expectedColor.sd_hexString]);
|
||||||
// Check rounded corner operation not inversion the image
|
// Check rounded corner operation not inversion the image
|
||||||
UIColor *topCenterColor = [blurredImage sd_colorAtPoint:CGPointMake(150, 20)];
|
UIColor *topCenterColor = [blurredImage sd_colorAtPoint:CGPointMake(150, 20)];
|
||||||
expect([topCenterColor.sd_hexString isEqualToString:@"#9a430d06"]).beTruthy();
|
UIColor *bottomCenterColor = [blurredImage sd_colorAtPoint:CGPointMake(150, 280)];
|
||||||
|
expect([topCenterColor.sd_hexString isEqualToString:bottomCenterColor.sd_hexString]).beFalsy();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)test08UIImageTransformFilter {
|
- (void)test08UIImageTransformFilterCG {
|
||||||
|
[self test08UIImageTransformFilterWithImage:self.testImageCG];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test08UIImageTransformFilterCI {
|
||||||
|
[self test08UIImageTransformFilterWithImage:self.testImageCI];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)test08UIImageTransformFilterWithImage:(UIImage *)testImage {
|
||||||
// Invert color filter
|
// Invert color filter
|
||||||
CIFilter *filter = [CIFilter filterWithName:@"CIColorInvert"];
|
CIFilter *filter = [CIFilter filterWithName:@"CIColorInvert"];
|
||||||
UIImage *filteredImage = [self.testImage sd_filteredImageWithFilter:filter];
|
UIImage *filteredImage = [testImage sd_filteredImageWithFilter:filter];
|
||||||
expect(CGSizeEqualToSize(filteredImage.size, self.testImage.size)).beTruthy();
|
expect(CGSizeEqualToSize(filteredImage.size, testImage.size)).beTruthy();
|
||||||
// Check left color, should be inverted
|
// Check left color, should be inverted
|
||||||
UIColor *leftColor = [filteredImage sd_colorAtPoint:CGPointMake(80, 150)];
|
UIColor *leftColor = [filteredImage sd_colorAtPoint:CGPointMake(80, 150)];
|
||||||
// Hard-code from the output
|
// Hard-code from the output
|
||||||
|
@ -198,7 +265,7 @@
|
||||||
NSString *transformerKey = [transformerKeys componentsJoinedByString:@"-"]; // SDImageTransformerKeySeparator
|
NSString *transformerKey = [transformerKeys componentsJoinedByString:@"-"]; // SDImageTransformerKeySeparator
|
||||||
expect([pipelineTransformer.transformerKey isEqualToString:transformerKey]).beTruthy();
|
expect([pipelineTransformer.transformerKey isEqualToString:transformerKey]).beTruthy();
|
||||||
|
|
||||||
UIImage *transformedImage = [pipelineTransformer transformedImageWithImage:self.testImage forKey:@"Test"];
|
UIImage *transformedImage = [pipelineTransformer transformedImageWithImage:self.testImageCG forKey:@"Test"];
|
||||||
expect(transformedImage).notTo.beNil();
|
expect(transformedImage).notTo.beNil();
|
||||||
expect(CGSizeEqualToSize(transformedImage.size, cropRect.size)).beTruthy();
|
expect(CGSizeEqualToSize(transformedImage.size, cropRect.size)).beTruthy();
|
||||||
}
|
}
|
||||||
|
@ -239,6 +306,8 @@
|
||||||
expect(SDTransformedKeyForKey(key, transformerKey)).equal(@"ftp://root:password@foo.com/image-SDImageFlippingTransformer(1,0).png");
|
expect(SDTransformedKeyForKey(key, transformerKey)).equal(@"ftp://root:password@foo.com/image-SDImageFlippingTransformer(1,0).png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Coder Helper
|
||||||
|
|
||||||
- (void)test20CGImageCreateDecodedWithOrientation {
|
- (void)test20CGImageCreateDecodedWithOrientation {
|
||||||
// Test EXIF orientation tag, you can open this image with `Preview.app`, open inspector (Command+I) and rotate (Command+L/R) to check
|
// Test EXIF orientation tag, you can open this image with `Preview.app`, open inspector (Command+I) and rotate (Command+L/R) to check
|
||||||
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[self testPNGPathForName:@"TestEXIF"]];
|
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[self testPNGPathForName:@"TestEXIF"]];
|
||||||
|
@ -331,11 +400,23 @@
|
||||||
|
|
||||||
#pragma mark - Helper
|
#pragma mark - Helper
|
||||||
|
|
||||||
- (UIImage *)testImage {
|
- (UIImage *)testImageCG {
|
||||||
if (!_testImage) {
|
if (!_testImageCG) {
|
||||||
_testImage = [[UIImage alloc] initWithContentsOfFile:[self testPNGPathForName:@"TestImage"]];
|
_testImageCG = [[UIImage alloc] initWithContentsOfFile:[self testPNGPathForName:@"TestImage"]];
|
||||||
}
|
}
|
||||||
return _testImage;
|
return _testImageCG;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImage *)testImageCI {
|
||||||
|
if (!_testImageCI) {
|
||||||
|
CIImage *ciImage = [[CIImage alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[self testPNGPathForName:@"TestImage"]]];
|
||||||
|
#if SD_UIKIT
|
||||||
|
_testImageCI = [[UIImage alloc] initWithCIImage:ciImage scale:1 orientation:UIImageOrientationUp];
|
||||||
|
#else
|
||||||
|
_testImageCI = [[UIImage alloc] initWithCIImage:ciImage scale:1 orientation:kCGImagePropertyOrientationUp];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return _testImageCI;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)testPNGPathForName:(NSString *)name {
|
- (NSString *)testPNGPathForName:(NSString *)name {
|
||||||
|
|
Loading…
Reference in New Issue