Skip to content

Commit

Permalink
NUKE IT FROM ORBIT. Set the keyword on ALL versions we can find for e…
Browse files Browse the repository at this point in the history
…ach master.
  • Loading branch information
schwa committed Aug 21, 2011
1 parent b322edb commit 94b004b
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 61 deletions.
105 changes: 51 additions & 54 deletions ApertureDuplicateFinder/ApertureLibraryProcessor.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ @interface ApertureLibraryProcessor ()
@property (readwrite, nonatomic, assign) CFAbsoluteTime finish;
@property (readwrite, nonatomic, assign) CFAbsoluteTime estimatedTimeRemaining;

@property (readwrite, nonatomic, strong) CSqliteDatabase *database;
@property (readwrite, nonatomic, assign) CGColorSpaceRef colorSpace;
@property (readwrite, nonatomic, strong) NSMutableDictionary *imagesByUUID;

Expand All @@ -44,6 +45,7 @@ @implementation ApertureLibraryProcessor
@synthesize finish;
@synthesize estimatedTimeRemaining;

@synthesize database;
@synthesize colorSpace;
@synthesize imagesByUUID;

Expand All @@ -54,7 +56,15 @@ - (id)initWithLibraryURL:(NSURL *)inLibraryURL
libraryURL = inLibraryURL;
imagesByUUID = [[NSMutableDictionary alloc] init];


NSURL *theDatabaseURL = [self.libraryURL URLByAppendingPathComponent:@"Database/Library.apdb"];

// Open the aperture library
NSError *theError = NULL;
database = [[CSqliteDatabase alloc] initWithURL:theDatabaseURL flags:SQLITE_OPEN_READONLY error:&theError];

colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);

}
return self;
}
Expand Down Expand Up @@ -87,21 +97,8 @@ - (BOOL)main:(NSError **)outError

self.processing = YES;

NSURL *theDatabaseURL = [self.libraryURL URLByAppendingPathComponent:@"Database/Library.apdb"];
NSURL *theMastersURL = [self.libraryURL URLByAppendingPathComponent:@"Masters"];

// Open the aperture library
NSError *theError = NULL;
CSqliteDatabase *theDatabase = [[CSqliteDatabase alloc] initWithURL:theDatabaseURL flags:SQLITE_OPEN_READONLY error:&theError];
if (theDatabase == NULL)
{
if (outError)
{
*outError = theError;
}
return(NO);
}

dispatch_group_t theGroup = dispatch_group_create();
dispatch_queue_t theSerialQueue = dispatch_queue_create("com.toxicsoftware.some_queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t theGlobalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
Expand All @@ -111,7 +108,7 @@ - (BOOL)main:(NSError **)outError
// Get all images from the Aperture Library
NSString *theStatementString = @"SELECT * FROM RKMaster";
// NSString *theStatementString = @"SELECT * FROM RKMaster LIMIT 100";
CSqliteStatement *theStatement = [theDatabase statementWithString:theStatementString];
CSqliteStatement *theStatement = [self.database statementWithString:theStatementString];
[theStatement enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(CSqliteRow *row, NSUInteger idx, BOOL *stop) {

NSString *thePath = [row objectForKey:@"imagePath"];
Expand All @@ -137,10 +134,11 @@ - (BOOL)main:(NSError **)outError
if (theApertureImage == NULL)
{
theApertureImage = [[CApertureImage alloc] init];
theApertureImage.modelID = [row objectForKey:@"modelId"];
theApertureImage.UUID = theUUID;
theApertureImage.path = thePath;
theApertureImage.type = theType;
theApertureImage.originalVersionUUID = [row objectForKey:@"originalVersionUuid"];
// theApertureImage.originalVersionUUID = [row objectForKey:@"originalVersionUuid"];
[self.imagesByUUID setObject:theApertureImage forKey:theUUID];
}
});
Expand Down Expand Up @@ -288,61 +286,60 @@ - (BOOL)searchForDuplicates:(NSError **)outError
[theImages addObject:theImage];
}

ApertureApplication *theApplication = [SBApplication applicationWithBundleIdentifier:@"com.apple.Aperture"];
if (theApplication.isRunning == NO)
{
[theApplication activate];
}



NSMutableSet *theDuplicateDigests = [NSMutableSet set];

[theImagesByDigest enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj count] > 1)
{
[theDuplicateDigests addObject:key];
for (CApertureImage *theImage in obj)
{
ApertureImageVersion *theVersion = [theApplication.imageVersions objectWithID:theImage.originalVersionUUID];
theVersion = [theVersion get];
NSLog(@"%@ -> %@", theImage.UUID, theVersion.name);

NSLog(@"%@", [theVersion.keywords valueForKey:@"name"]);

NSDictionary *theProperties = [NSDictionary dictionaryWithObjectsAndKeys:
@"x-duplicate", @"name",
NULL];
ApertureKeyword *theKeyword = [[[theApplication classForScriptingClass:@"keyword"] alloc] initWithProperties:theProperties];
// [theVersion.keywords get];
[theVersion.keywords addObject:theKeyword];
CSqliteStatement *theStatement = [self.database statementWithFormat:@"SELECT * FROM RKVersion WHERE masterId == '%@' ORDER BY 'versionNumber'", theImage.modelID];
NSError *theError = NULL;
NSArray *theRows = [theStatement rows:&theError];

NSLog(@"%@", [theVersion.keywords valueForKey:@"name"]);
theImage.versionUUIDs = [theRows valueForKey:@"uuid"];
}

}
}];
NSLog(@"%lu", [theDuplicateDigests count]);

// NSLog(@"%@", [theKeyword lastError]);
// NSLog(@"%@", [theVersion lastError]);
//
// NSLog(@"%@", [theVersion.keywords get]);
//
// theProperties = [NSDictionary dictionaryWithObjectsAndKeys:
// @"MD5", @"name",
// @"something", @"value",
// NULL];
//
//// ApertureCustomTag *theTag = [[[theApplication classForScriptingClass:@"custom tag"] alloc] initWithProperties:theProperties];
//// [theVersion.customTags addObject:theTag];
//
// NSLog(@"%@", [theVersion.customTags get]);
self.database = NULL;

ApertureApplication *theApplication = [SBApplication applicationWithBundleIdentifier:@"com.apple.Aperture"];
if (theApplication.isRunning == NO)
{
[theApplication activate];
}

[theImagesByDigest enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj count] > 1)
{
for (CApertureImage *theImage in obj)
{
for (NSString *theVersionUUID in theImage.versionUUIDs)
{
ApertureImageVersion *theVersion = [theApplication.imageVersions objectWithID:theVersionUUID];
NSLog(@"SETTING");
theVersion = [theVersion get];
NSDictionary *theProperties = [NSDictionary dictionaryWithObjectsAndKeys:
@"x-duplicate", @"name",
NULL];
ApertureKeyword *theKeyword = [[[theApplication classForScriptingClass:@"keyword"] alloc] initWithProperties:theProperties];
[theVersion.keywords addObject:theKeyword];
}
}

// NSLog(@"%@", obj);
}
}];
NSLog(@"%lu", [theDuplicateDigests count]);







//



return(YES);
Expand Down
3 changes: 2 additions & 1 deletion ApertureDuplicateFinder/CApertureImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@

@interface CApertureImage : NSObject

@property (readwrite, nonatomic, copy) NSString *modelID;
@property (readwrite, nonatomic, copy) NSString *UUID;
@property (readwrite, nonatomic, copy) NSString *path;
@property (readwrite, nonatomic, copy) NSData *digest;
@property (readwrite, nonatomic, copy) NSString *type;
@property (readwrite, nonatomic, copy) NSString *originalVersionUUID;
@property (readwrite, nonatomic, copy) NSArray *versionUUIDs;


@end
3 changes: 2 additions & 1 deletion ApertureDuplicateFinder/CApertureImage.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@

@implementation CApertureImage

@synthesize modelID;
@synthesize UUID;
@synthesize path;
@synthesize digest;
@synthesize type;
@synthesize originalVersionUUID;
@synthesize versionUUIDs;

- (NSString *)description
{
Expand Down
2 changes: 1 addition & 1 deletion Externals/TouchSQL
Submodule TouchSQL updated from 6a4f09 to 74fc9b
5 changes: 1 addition & 4 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The file finds all master images by reading the private and not-to-be-accessed-b

It then enumerates over each image file, loading it into memory into a known image format (8-bit RGBA) and produces a MD5 hash for the pixel data. The hashes are then used to find duplicate images.

Each image that is a duplicate is then tagged as such with the keyword "x-duplicate" (currently broken).
Each image that is a duplicate is then tagged as such with the keyword "x-duplicate".

## Performance

Expand All @@ -54,6 +54,3 @@ Much of the code has been made multiprocessor happy with the use of GCD. While r

Don't run this on your full Aperture library. That's nuts. Find an album or project that you know contains duplicates and then export that into a new library.

## Bugs

Setting the keyword seems to work, but the keyword is not visible inside Aperture itself. What the hell?

0 comments on commit 94b004b

Please sign in to comment.