Created
June 3, 2015 14:53
-
-
Save zacwest/a21e3d548ca9bb793d47 to your computer and use it in GitHub Desktop.
Saving optimal JPEGs
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
// | |
// ZSWFileTester.m | |
// Image Size Test | |
// | |
// Created by Zachary West on 3/4/14. | |
// Copyright (c) 2014 Zachary West. All rights reserved. | |
// | |
#import "ZSWFileTester.h" | |
@import MobileCoreServices; | |
@import ImageIO; | |
@implementation ZSWFileTester | |
+ (NSUInteger)fileSizeForImageIOVersionOfImage:(UIImage *)image { | |
NSURL *destinationURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"test.jpg"]]; | |
CGImageDestinationRef destinationRef = CGImageDestinationCreateWithURL((__bridge CFURLRef)destinationURL, | |
kUTTypeJPEG, | |
/* number of images */ 1, | |
/* reserved */ NULL); | |
CGImageDestinationSetProperties(destinationRef, | |
(__bridge CFDictionaryRef)@{ | |
(__bridge NSString *)kCGImageDestinationLossyCompressionQuality: @(0.94) | |
}); | |
CGImageDestinationAddImage(destinationRef, image.CGImage, NULL); | |
CGImageDestinationFinalize(destinationRef); | |
CFRelease(destinationRef); | |
NSNumber *fileSize; | |
if ([destinationURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:NULL]) { | |
return [fileSize unsignedIntegerValue]; | |
} else { | |
NSAssert(NO, @"Booboo"); | |
return 0; | |
} | |
} | |
+ (NSUInteger)fileSizeForUIImageVersionOfImage:(UIImage *)image { | |
NSURL *destinationURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"test.jpg"]]; | |
[UIImageJPEGRepresentation(image, 0.94) writeToFile:destinationURL.path atomically:NO]; | |
NSNumber *fileSize; | |
if ([destinationURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:NULL]) { | |
return [fileSize unsignedIntegerValue]; | |
} else { | |
NSAssert(NO, @"Booboo"); | |
return 0; | |
} | |
} | |
+ (void)test { | |
NSLog(@"Starting test... this will take a little bit."); | |
NSURL *folderURL = [[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:@"images"]; | |
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:folderURL | |
includingPropertiesForKeys:@[ ] | |
options:0 | |
errorHandler:NULL]; | |
NSUInteger runningSizeCount = 0; | |
CGFloat runningSizeDifference = 0; | |
NSUInteger runningTimeCount = 0; | |
NSTimeInterval runningTimeDifference = 0; | |
for (NSURL *imageURL in enumerator) { | |
NSTimeInterval imageIoTime, uiImageTime; | |
NSUInteger imageIoSize, uiImageSize; | |
@autoreleasepool { | |
UIImage *image = [[UIImage alloc] initWithContentsOfFile:imageURL.path]; | |
NSDate *imageIoStart = [NSDate date]; | |
imageIoSize = [self fileSizeForImageIOVersionOfImage:image]; | |
imageIoTime = [[NSDate date] timeIntervalSinceDate:imageIoStart]; | |
NSDate *uiImageStart = [NSDate date]; | |
uiImageSize = [self fileSizeForUIImageVersionOfImage:image]; | |
uiImageTime = [[NSDate date] timeIntervalSinceDate:uiImageStart]; | |
} | |
#define UPDATE_RUNNING_AVG(result, count, new_value) \ | |
do { \ | |
result = ((result * count) + new_value)/(count+1); \ | |
count++; \ | |
} while (0) | |
NSTimeInterval timeDifference = (imageIoTime - uiImageTime)/imageIoTime; | |
UPDATE_RUNNING_AVG(runningTimeDifference, runningTimeCount, timeDifference); | |
CGFloat sizeDifference = ((CGFloat)(uiImageSize - imageIoSize))/((CGFloat)uiImageSize); | |
UPDATE_RUNNING_AVG(runningSizeDifference, runningSizeCount, sizeDifference); | |
printf("."); | |
} | |
printf("\n"); | |
NSLog(@"Image IO creates files %.02f%% smaller than UIImage", runningSizeDifference*100); | |
NSLog(@"Image IO takes %.02fx longer than UIImage", (1.0/runningTimeDifference)); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment