How to get panoramas from ALAsset objects

We have about 2k objects that are an instance of the ALAsset class, and we need to know which files are panoramic images. We tried to get a CGImageRef from an ALAsset instance and check the width to height ratio.

ALAsset *alasset = ...
CFImageRef = alasset.thumbnail; // return square thumbnail and not suitable for me
CFImageRef = alasset.aspectRationThumbnail; //return aspect ration thumbnail, but very slowly

It is not suitable for us because it is slow for many files.

We also tried to get metadata from defaultRepresentation and check the EXIF ​​image, but it works slowly.

NSDictionary *dictionary = [alasset defaultRepresentation] metadata]; //very slowly to

Is there any way to make this better?

thank

+4
source share
1 answer

Finally, I found this solution for ALAsset:

ALAssetsLibrary *assetsLibrary = ...;
NSOperation *queue = [NSoperationQueue alloc] init];
static NSString * const kAssetQueueName = ...;
static NSUInteger const kAssetConcurrentOperationCount = ...; //I use 5 
queue.maxConcurrentOperationCount = kAssetConcurrentOperationCount;
queue.name = kAssetQueueName;
dispatch_async(dispatch_get_main_queue(), ^{
  [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
    /*You must check the group is not nil */
    if (!group)
      return;
    /*Then you need to select group where you will search panoramas: for iPhone-Simulator it @"Saved Photos" and "Camera Roll" for  iPhone. It actuality only for iOS 7 or early. */
    static NSString * const kAssetGroupName = ...;
    if ([[group valueForProperty:ALAssetsGroupPropertyName] kAssetGroupName]) {
      [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) {
        if (!asset)
          return;
        [queue addOperationWithBlock:^{
         //I use @autoreleasepool for instant memory release, after I find panoramas asset url
          @autoreleasepool {
            ALAssetRepresentation *defaultRepresentation = asset.defaultRepresentation;
            if ([defaultRepresentation.UTI isEqualToString:@"public.jpeg"]) {
              NSDictionary *metadata = defaultRepresentation.metadata;
              if (!metadata) 
                return;
              if (metadata[@"PixelWidth"] && metadata[@"PixelHeight"]) {
                NSInteger pixelWidth = [metadata[@"PixelWidth"] integerValue];
                NSInteger pixelHeight = [metadata[@"PixelHeight"] integerValue];
                static NSUInteger const kSidesRelationshipConstant = ...; //I use 2
                static NSUInteger const kMinimalPanoramaHeight = ...; //I use 600

                if (pixelHeight >= kMinimalPanoramaHeight && pixelWidth/pixelHeight >= kSidesRelationshipConstant) {/*So, that is panorama.*/}
             }

        }];

      }];
    }
  } failureBlock:^(NSError *error) {
      //Some failing action, you know.
  }];
};

I.e. Therefore, I believe that this is not the best solution. However, to date, I have not found the best.

+1

Source: https://habr.com/ru/post/1546685/


All Articles