Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Saving optimal JPEGs
//
// 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