|
|
@@ -0,0 +1,173 @@ |
|
|
// |
|
|
// main.m |
|
|
// creategif |
|
|
// |
|
|
// Created by Kevin Meaney on 21/10/2013. |
|
|
// Copyright (c) 2013 Kevin Meaney. All rights reserved. |
|
|
// |
|
|
|
|
|
#import <Foundation/Foundation.h> |
|
|
@import ImageIO; |
|
|
|
|
|
void PrintUsage() |
|
|
{ |
|
|
printf("creategif - usage:\n"); |
|
|
printf(" ./creategif [-parameter <value> ...], filename1, filename2, ...\n"); |
|
|
printf(" Parameters are preceded by a -<parameterName>. The order of the parameters is unimportant.\n"); |
|
|
printf(" All the input image filenames follow the parameters.\n"); |
|
|
printf(" You probably need to escape or quote paths especially if the paths includes spaces etc..\n"); |
|
|
printf(" Only one of -delaytime or -unclampeddelaytime needs to be specified, both can be.\n"); |
|
|
printf(" If the output file already exists then it will be deleted prior to saving the new file if allowed.\n"); |
|
|
printf(" Available parameters are:\n"); |
|
|
printf(" -outputfile <output file path which should finish with a gif extension>\n"); |
|
|
printf(" -delaytime <should be a floating point number above 0.1>\n"); |
|
|
// printf(" -unclampeddelaytime <should be a floating point number above 0.1>\n"); |
|
|
printf(" Sample export lines:\n"); |
|
|
printf(" ./creategif -outputfile blahblah.gif -delaytime 0.4 -unclampeddelaytime 0.4 image1.png image2.png image3.png image4.png\n"); |
|
|
printf(" ./creategif -outputfile \"Users/ktam/gifs/blahblah.gif\" -delaytime 1.0 image1.png image2.png image3.png image4.png\n"); |
|
|
} |
|
|
|
|
|
BOOL GetFloatFromString(NSString *string, CGFloat *value) |
|
|
{ |
|
|
NSScanner *scanner = [[NSScanner alloc] initWithString:string]; |
|
|
CGFloat floatVal; |
|
|
BOOL gotValue = [scanner scanDouble:&floatVal]; |
|
|
if (gotValue) |
|
|
{ |
|
|
*value = floatVal; |
|
|
} |
|
|
return gotValue; |
|
|
} |
|
|
|
|
|
NSMutableArray *inputImageList; |
|
|
NSString *outFilePath; |
|
|
CGFloat delayTime; |
|
|
CGFloat unclampedDelayTime; |
|
|
BOOL gotDelayTime = NO; |
|
|
BOOL gotUnclampedDelayTime = NO; |
|
|
|
|
|
bool GetArgs(int argc, const char **argv) // returns true if successful. |
|
|
{ |
|
|
bool success = true; |
|
|
|
|
|
argv++; |
|
|
argc--; |
|
|
const char *args; |
|
|
// Get the parameters |
|
|
while (argc > 0 && **argv == '-') |
|
|
{ |
|
|
args = *argv; |
|
|
argv++; |
|
|
argc--; |
|
|
|
|
|
if ( ! strcmp ( args, "-outputfile" ) ) |
|
|
{ |
|
|
outFilePath = @(*argv++); |
|
|
argc--; |
|
|
} |
|
|
else if ( ! strcmp( args, "-delaytime" )) |
|
|
{ |
|
|
gotDelayTime = GetFloatFromString(@(*argv++), &delayTime); |
|
|
argc--; |
|
|
} |
|
|
/* else if ( ! strcmp( args, "-unclampeddelaytime")) |
|
|
{ |
|
|
gotUnclampedDelayTime = GetFloatFromString(@(*argv++), &unclampedDelayTime); |
|
|
argc--; |
|
|
} |
|
|
*/ |
|
|
} |
|
|
|
|
|
if (!(gotDelayTime || gotUnclampedDelayTime)) |
|
|
success = false; |
|
|
|
|
|
if (!outFilePath) |
|
|
success = false; |
|
|
|
|
|
// If we've got to the end of arguments and there are no input files then bail. |
|
|
if (!success) |
|
|
return success; |
|
|
|
|
|
inputImageList = [[NSMutableArray alloc] initWithCapacity:0]; |
|
|
// [inputImageList addObject:@(args)]; |
|
|
// Finished getting parameters. Now get list of source files. 1 image per file. |
|
|
while (argc > 0) |
|
|
{ |
|
|
args = *argv; |
|
|
argv++; |
|
|
argc--; |
|
|
[inputImageList addObject:@(args)]; |
|
|
} |
|
|
if (!inputImageList || [inputImageList count] == 0) |
|
|
success = false; |
|
|
|
|
|
return success; |
|
|
} |
|
|
|
|
|
int main(int argc, const char * argv[]) |
|
|
{ |
|
|
@autoreleasepool |
|
|
{ |
|
|
if (!GetArgs(argc, argv)) |
|
|
{ |
|
|
PrintUsage(); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
NSDictionary *gifFileProps = @{ @"{GIF}" : @{ @"HasGlobalColorMap" : @YES, |
|
|
@"LoopCount" : @(0) } }; |
|
|
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outFilePath isDirectory:NO]; |
|
|
CGImageDestinationRef imageDest; |
|
|
imageDest = CGImageDestinationCreateWithURL((__bridge CFURLRef)outputURL, |
|
|
CFSTR("com.compuserve.gif"), |
|
|
[inputImageList count], |
|
|
(__bridge CFDictionaryRef)gifFileProps); |
|
|
if (!imageDest) |
|
|
{ |
|
|
printf("Couldn't create image destination"); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
CGImageDestinationSetProperties(imageDest, |
|
|
(__bridge CFDictionaryRef)gifFileProps); |
|
|
|
|
|
for (NSString *inputFile in inputImageList) |
|
|
{ |
|
|
NSString *expandedString = [inputFile stringByExpandingTildeInPath]; |
|
|
NSURL *sourceFile = [[NSURL alloc] initFileURLWithPath:expandedString |
|
|
isDirectory:NO]; |
|
|
CGImageSourceRef imageSource; |
|
|
imageSource = CGImageSourceCreateWithURL((__bridge CFURLRef)sourceFile, |
|
|
NULL); |
|
|
if (!imageSource) |
|
|
{ |
|
|
printf("Invalid source file path\n"); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
if (CGImageSourceGetCount(imageSource)) |
|
|
{ |
|
|
CGImageRef theImage; |
|
|
theImage = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); |
|
|
if (theImage) |
|
|
{ |
|
|
NSMutableDictionary *gifFrameProps; |
|
|
gifFrameProps = [[NSMutableDictionary alloc] initWithCapacity:0]; |
|
|
if (gotDelayTime) |
|
|
[gifFrameProps setObject:@(delayTime) forKey:@"DelayTime"]; |
|
|
// if (gotUnclampedDelayTime) |
|
|
// [gifFrameProps setObject:@(unclampedDelayTime) |
|
|
// forKey:@"UnclampedDelayTime"]; |
|
|
NSDictionary *frameProps = @{ @"{GIF}" : gifFrameProps }; |
|
|
CGImageDestinationAddImage(imageDest, theImage, |
|
|
(__bridge CFDictionaryRef)frameProps); |
|
|
CFRelease(theImage); |
|
|
} |
|
|
} |
|
|
CFRelease(imageSource); |
|
|
} |
|
|
CGImageDestinationFinalize(imageDest); |
|
|
CFRelease(imageDest); |
|
|
} |
|
|
return 0; |
|
|
} |