I noticed you release the fileProps but didn’t release the image, but I don’t 
know if that’s one of those details you left out for clarity.  Also, depending 
on some factors like mutability, while the initWithString call with a 
CFStringRef might essentially be a no-op, you can just do the typecast on the 
dateref and pass it directly into dateFromString.

One thing I’d suggest is to do the work for each image asynchronously on a 
background queue and have that block (essentially all of your for-loop code) 
report its completion by some asynchronous way like posting a notification on 
the original queue along with the result you care about, the parsed date 
associated with the particular file.  Let the original queue handle how to 
store each parsed date; it would probably be best to use a dictionary where the 
key was the filename and value is the date.  To prevent memory pressure, 
allocate your background queue so that it’s concurrent and autorelease 
frequency is set to be workItem.  If you want to be sure to know when 
everything’s done, you could use a DispatchGroup to track those and you could 
choose to pass back NSNull or nil for the parsed result if the date could not 
be parsed.

Of course, this will depend on if your file system is non-network-based and 
whether it’s SSD vs HD as well as other physical system factors.
--
Gary

> On Aug 14, 2022, at 2:22 PM, Gabriel Zachmann via Cocoa-dev 
> <cocoa-dev@lists.apple.com> wrote:
> 
> I would like to collect the date/time stored in an EXIF tag in a bunch of 
> images.
> 
> I thought I could do so with the following procedure
> (some details and error checking omitted for sake of clarity):
> 
> 
>    NSMutableArray * dates_and_times = [NSMutableArray arrayWithCapacity: 
> [imagefiles count]];
>    CFDictionaryRef exif_dict;
>    CFStringRef dateref = NULL;
>    for ( NSString* filename in imagefiles )
>    {
>        NSURL * imgurl = [NSURL fileURLWithPath: filename isDirectory: NO];    
> // escapes any chars that are not allowed in URLs (space, &, etc.)
>        CGImageSourceRef image = CGImageSourceCreateWithURL( (__bridge 
> CFURLRef) imgurl, NULL );
>        CFDictionaryRef fileProps = CGImageSourceCopyPropertiesAtIndex( image, 
> 0, NULL );
>        bool success = CFDictionaryGetValueIfPresent( fileProps, 
> kCGImagePropertyExifDictionary, (const void **) & exif_dict );
>        success = CFDictionaryGetValueIfPresent( exif_dict, 
> kCGImagePropertyExifDateTimeDigitized, (const void **) & dateref );
>        NSString * date_str = [[NSString alloc] initWithString: (__bridge 
> NSString * _Nonnull)( dateref ) ];
>        NSDate * iso_date = [isoDateFormatter_ dateFromString: date_str];
>        if ( iso_date )
>             [dates_and_times addObject: iso_date ];
>        CFRelease( fileProps );
>    }
> 
> 
> But, I get the impression, this code actually loads each and every image.
> On my Macbook, it takes 3m30s for 250k images (130GB).
> 
> So, the big question is: can it be done faster?
> 
> I know the EXIF tags are part of the image file, but I was hoping it might be 
> possible to load only those EXIF dictionaries.
> Or are the CGImage functions above already clever enough to implement this 
> idea?
> 
> 
> Best regards, Gab.
> 

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to