Skip to content

Commit

Permalink
Move DFImageUtilities to DFImageProcessor; remove excessive functions
Browse files Browse the repository at this point in the history
  • Loading branch information
kean committed Mar 19, 2015
1 parent 0e09fd1 commit 7aa6330
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 266 deletions.
10 changes: 0 additions & 10 deletions DFImageManager/DFImageManager.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@
0CEEEC8A1AABC5FC00C212A4 /* DFImageProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CEEEC821AABC5FC00C212A4 /* DFImageProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
0CEEEC8B1AABC5FC00C212A4 /* DFImageProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CEEEC831AABC5FC00C212A4 /* DFImageProcessor.m */; };
0CEEEC8C1AABC5FC00C212A4 /* DFImageProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CEEEC831AABC5FC00C212A4 /* DFImageProcessor.m */; };
0CEEEC8D1AABC5FC00C212A4 /* DFImageUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CEEEC841AABC5FC00C212A4 /* DFImageUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; };
0CEEEC8E1AABC5FC00C212A4 /* DFImageUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CEEEC851AABC5FC00C212A4 /* DFImageUtilities.m */; };
0CEEEC8F1AABC5FC00C212A4 /* DFImageUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CEEEC851AABC5FC00C212A4 /* DFImageUtilities.m */; };
0CEEEC9D1AABC84F00C212A4 /* DFCachedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CEEEC971AABC84F00C212A4 /* DFCachedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
0CEEEC9E1AABC84F00C212A4 /* DFCachedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CEEEC981AABC84F00C212A4 /* DFCachedImage.m */; };
0CEEEC9F1AABC84F00C212A4 /* DFCachedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CEEEC981AABC84F00C212A4 /* DFCachedImage.m */; };
Expand Down Expand Up @@ -241,8 +238,6 @@
0CE578531AA4067D00E934FB /* TDFCompositeImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TDFCompositeImageManager.m; sourceTree = "<group>"; };
0CEEEC821AABC5FC00C212A4 /* DFImageProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFImageProcessor.h; sourceTree = "<group>"; };
0CEEEC831AABC5FC00C212A4 /* DFImageProcessor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DFImageProcessor.m; sourceTree = "<group>"; };
0CEEEC841AABC5FC00C212A4 /* DFImageUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFImageUtilities.h; sourceTree = "<group>"; };
0CEEEC851AABC5FC00C212A4 /* DFImageUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DFImageUtilities.m; sourceTree = "<group>"; };
0CEEEC971AABC84F00C212A4 /* DFCachedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFCachedImage.h; sourceTree = "<group>"; };
0CEEEC981AABC84F00C212A4 /* DFCachedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DFCachedImage.m; sourceTree = "<group>"; };
0CEEEC991AABC84F00C212A4 /* DFImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFImageCache.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -525,8 +520,6 @@
children = (
0CEEEC821AABC5FC00C212A4 /* DFImageProcessor.h */,
0CEEEC831AABC5FC00C212A4 /* DFImageProcessor.m */,
0CEEEC841AABC5FC00C212A4 /* DFImageUtilities.h */,
0CEEEC851AABC5FC00C212A4 /* DFImageUtilities.m */,
);
path = Processing;
sourceTree = "<group>";
Expand Down Expand Up @@ -639,7 +632,6 @@
0C44A81F1AAB2AD900900C6A /* ALAssetsLibrary+DFImageManager.h in Headers */,
0CEEED011AABD9DB00C212A4 /* DFCompositeImageManager.h in Headers */,
0CEEECD41AABD70400C212A4 /* DFImageRequestOptions.h in Headers */,
0CEEEC8D1AABC5FC00C212A4 /* DFImageUtilities.h in Headers */,
0CEEED331AABE4BC00C212A4 /* DFURLResponseDeserializing.h in Headers */,
0CEEED2A1AABE4BC00C212A4 /* DFURLImageDeserializer.h in Headers */,
0C44A8281AAB2AD900900C6A /* DFAssetsLibraryImageFetchOperation.h in Headers */,
Expand Down Expand Up @@ -953,7 +945,6 @@
0C44A8231AAB2AD900900C6A /* DFALAsset.m in Sources */,
0CEEECA41AABC84F00C212A4 /* NSCache+DFImageManager.m in Sources */,
0CEEED171AABE36100C212A4 /* DFImageManagerConfiguration.m in Sources */,
0CEEEC8E1AABC5FC00C212A4 /* DFImageUtilities.m in Sources */,
0C6550B31AA738EB00B4805C /* DFAnimatedImage.m in Sources */,
0C44A8201AAB2AD900900C6A /* ALAssetsLibrary+DFImageManager.m in Sources */,
0C44A86A1AAB3CE800900C6A /* DFCollectionViewPreheatingController.m in Sources */,
Expand Down Expand Up @@ -999,7 +990,6 @@
0CEEECE81AABD75F00C212A4 /* DFImageRequestID.m in Sources */,
0C44A73C1AAB235800900C6A /* DFPhotosKitImageFetcher.m in Sources */,
0C6550B61AA82C0000B4805C /* DFAnimatedImage.m in Sources */,
0CEEEC8F1AABC5FC00C212A4 /* DFImageUtilities.m in Sources */,
0CEEED151AABE36100C212A4 /* DFImageManager+DefaultManager.m in Sources */,
0CEEED131AABE36100C212A4 /* DFImageManager.m in Sources */,
0C44A8211AAB2AD900900C6A /* ALAssetsLibrary+DFImageManager.m in Sources */,
Expand Down
1 change: 0 additions & 1 deletion DFImageManager/Source/Core/DFImageManagerKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@

// Processing
#import "DFImageProcessor.h"
#import "DFImageUtilities.h"

// Utilities
#import "DFCompositeImageManager.h"
Expand Down
23 changes: 23 additions & 0 deletions DFImageManager/Source/Core/Processing/DFImageProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// THE SOFTWARE.

#import "DFImageProcessing.h"
#import "DFImageRequestOptions.h"
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

Expand All @@ -32,4 +33,26 @@ extern NSString *DFImageProcessingCornerRadiusKey;
*/
@interface DFImageProcessor : NSObject <DFImageProcessing>

/*! Returns decompressed image with a given image.
*/
+ (UIImage *)decompressedWithImage:(UIImage *)image;

/*! Returns decompressed image with a given image.
@param targetSize Image target size in pixels.
*/
+ (UIImage *)decompressedImageWithImage:(UIImage *)image targetSize:(CGSize)targetSize contentMode:(DFImageContentMode)contentMode;

/*! Returns scaled decompressed image with a given image.
*/
+ (UIImage *)decompressedWithImage:(UIImage *)image scale:(CGFloat)scale;

/*! Returns image cropped to a given normalized crop rect.
*/
+ (UIImage *)croppedImageWithImage:(UIImage *)image normalizedCropRect:(CGRect)cropRect;

/*! Returns image by drawing rounded corners.
@param cornerRadius corner radius in points.
*/
+ (UIImage *)imageWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius;

@end
164 changes: 149 additions & 15 deletions DFImageManager/Source/Core/Processing/DFImageProcessor.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@
#import "DFImageProcessor.h"
#import "DFImageRequest.h"
#import "DFImageRequestOptions.h"
#import "DFImageUtilities.h"

NSString *DFImageProcessingCornerRadiusKey = @"DFImageProcessingCornerRadiusKey";

@implementation DFImageProcessor

#pragma mark <DFImageProcessing>

- (BOOL)isProcessingForRequestEquivalent:(DFImageRequest *)request1 toRequest:(DFImageRequest *)request2 {
if (request1 == request2) {
return YES;
Expand All @@ -44,26 +45,159 @@ - (BOOL)isProcessingForRequestEquivalent:(DFImageRequest *)request1 toRequest:(D
}

- (UIImage *)processedImage:(UIImage *)image forRequest:(DFImageRequest *)request {
switch (request.contentMode) {
case DFImageContentModeAspectFit:
image = [DFImageUtilities decompressedImageWithImage:image aspectFitPixelSize:request.targetSize];
break;
case DFImageContentModeAspectFill: {
if (request.options.allowsClipping) {
image = [DFImageUtilities croppedImageWithImage:image aspectFillPixelSize:request.targetSize];
}
image = [DFImageUtilities decompressedImageWithImage:image aspectFillPixelSize:request.targetSize];
}
break;
default:
break;
if (request.contentMode == DFImageContentModeAspectFill && request.options.allowsClipping) {
image = [DFImageProcessor croppedImageWithImage:image aspectFillPixelSize:request.targetSize];
}
image = [DFImageProcessor decompressedImageWithImage:image targetSize:request.targetSize contentMode:request.contentMode];
NSNumber *normalizedCornerRadius = request.options.userInfo[DFImageProcessingCornerRadiusKey];
if (normalizedCornerRadius) {
CGFloat cornerRadius = [normalizedCornerRadius floatValue] * MIN(image.size.width, image.size.height);
image = [DFImageUtilities imageWithImage:image cornerRadius:cornerRadius];
image = [DFImageProcessor imageWithImage:image cornerRadius:cornerRadius];
}
return image;
}

#pragma mark Utilities

+ (UIImage *)decompressedWithImage:(UIImage *)image {
return [self decompressedWithImage:image scale:1.f];
}

+ (UIImage *)decompressedImageWithImage:(UIImage *)image targetSize:(CGSize)targetSize contentMode:(DFImageContentMode)contentMode {
CGSize bitmapSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage));
CGFloat scaleWidth = targetSize.width / bitmapSize.width;
CGFloat scaleHeight = targetSize.height / bitmapSize.height;
CGFloat scale = contentMode == DFImageContentModeAspectFill ? MAX(scaleWidth, scaleHeight) : MIN(scaleWidth, scaleHeight);
return [self decompressedWithImage:image scale:scale];
}

+ (UIImage *)decompressedWithImage:(UIImage *)image scale:(CGFloat)scale {
if (!image) {
return nil;
}
if (image.images) {
return image;
}
CGImageRef imageRef = image.CGImage;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
if (scale < 1.f) {
imageSize = CGSizeMake(imageSize.width * scale, imageSize.height * scale);
}

CGRect imageRect = (CGRect){.origin = CGPointZero, .size = imageSize};

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);

int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask);
BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone ||
infoMask == kCGImageAlphaNoneSkipFirst ||
infoMask == kCGImageAlphaNoneSkipLast);

// CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB.
// https://developer.apple.com/library/mac/#qa/qa1037/_index.html
if (infoMask == kCGImageAlphaNone && CGColorSpaceGetNumberOfComponents(colorSpace) > 1) {
// Unset the old alpha info.
bitmapInfo &= ~kCGBitmapAlphaInfoMask;

// Set noneSkipFirst.
bitmapInfo |= kCGImageAlphaNoneSkipFirst;
}
// Some PNGs tell us they have alpha but only 3 components. Odd.
else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace) == 3) {
// Unset the old alpha info.
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
bitmapInfo |= kCGImageAlphaPremultipliedFirst;
}

// It calculates the bytes-per-row based on the bitsPerComponent and width arguments.
CGContextRef context = CGBitmapContextCreate(NULL,
(size_t)imageSize.width,
(size_t)imageSize.height,
CGImageGetBitsPerComponent(imageRef),
0,
colorSpace,
bitmapInfo);
CGColorSpaceRelease(colorSpace);

// If failed, return original image
if (!context) {
return image;
}

CGContextDrawImage(context, imageRect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);

CGContextRelease(context);

UIImage *decompressedImage = [UIImage imageWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(decompressedImageRef);
return decompressedImage;
}

+ (UIImage *)croppedImageWithImage:(UIImage *)image aspectFillPixelSize:(CGSize)targetSize {
CGSize imageSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage));
CGFloat scale = ({
CGFloat scaleWidth = targetSize.width / imageSize.width;
CGFloat scaleHeight = targetSize.height / imageSize.height;
MAX(scaleWidth, scaleHeight);
});
CGSize sizeScaled = CGSizeMake(imageSize.width * scale, imageSize.height * scale);
CGRect cropRect = CGRectMake((sizeScaled.width - targetSize.width) / 2.f, (sizeScaled.height - targetSize.height) / 2.f, targetSize.width, targetSize.height);
CGRect normalizedCropRect = CGRectMake(cropRect.origin.x / sizeScaled.width, cropRect.origin.y / sizeScaled.height, cropRect.size.width / sizeScaled.width, cropRect.size.height / sizeScaled.height);
return [self croppedImageWithImage:image normalizedCropRect:normalizedCropRect];
}

+ (UIImage *)croppedImageWithImage:(UIImage *)image normalizedCropRect:(CGRect)inputCropRect {
CGRect cropRect = inputCropRect;

switch (image.imageOrientation) {
case UIImageOrientationUp:
case UIImageOrientationUpMirrored:
// do nothing
break;
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
cropRect.origin.y = inputCropRect.origin.x;
cropRect.origin.x = 1.f - inputCropRect.origin.y - inputCropRect.size.height;
cropRect.size.width = inputCropRect.size.height;
cropRect.size.height = inputCropRect.size.width;
break;
case UIImageOrientationDown:
case UIImageOrientationDownMirrored:
cropRect.origin.x = 1.f - inputCropRect.origin.x - inputCropRect.size.width;
cropRect.origin.y = 1.f - inputCropRect.origin.y - inputCropRect.size.height;
break;
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
cropRect.origin.x = inputCropRect.origin.y;
cropRect.origin.y = 1.f - inputCropRect.origin.x - inputCropRect.size.width;
cropRect.size.width = inputCropRect.size.height;
cropRect.size.height = inputCropRect.size.width;
break;
default:
break;
}

CGSize imagePixelSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage));
CGRect imageCropRect = CGRectMake((CGFloat)floor(cropRect.origin.x * imagePixelSize.width),
(CGFloat)floor(cropRect.origin.y * imagePixelSize.height),
(CGFloat)floor(cropRect.size.width * imagePixelSize.width),
(CGFloat)floor(cropRect.size.height * imagePixelSize.height));

CGImageRef croppedImageRef = CGImageCreateWithImageInRect(image.CGImage, imageCropRect);
UIImage *croppedImage = [UIImage imageWithCGImage:croppedImageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(croppedImageRef);
return croppedImage;
}

+ (UIImage *)imageWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius {
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
[[UIBezierPath bezierPathWithRoundedRect:(CGRect){CGPointZero, image.size} cornerRadius:cornerRadius] addClip];
[image drawInRect:(CGRect){CGPointZero, image.size}];
UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return processedImage;
}

@end
67 changes: 0 additions & 67 deletions DFImageManager/Source/Core/Processing/DFImageUtilities.h

This file was deleted.

Loading

0 comments on commit 7aa6330

Please sign in to comment.