priore

Thumbnail image from ALAsset with a category

Apr 23rd, 2015
866
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #import <AssetsLibrary/AssetsLibrary.h>
  2. #import <AVFoundation/AVFoundation.h>
  3. #import <ImageIO/ImageIO.h>
  4.  
  5. @interface ALAsset (Thumbnail)
  6. - (UIImage*)thumbnailImageSize:(int)size;
  7. @end
  8.  
  9. @implementation ALAsset (Thumbnail)
  10.  
  11. typedef struct {
  12.     void *assetRepresentation;
  13.     int decodingIterationCount;
  14. } ThumbnailDecodingContext;
  15.  
  16. static const int kThumbnailDecodingContextMaxIterationCount = 16;
  17.  
  18. static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, size_t count)
  19. {
  20.     ThumbnailDecodingContext *decodingContext = (ThumbnailDecodingContext *)info;
  21.     ALAssetRepresentation *assetRepresentation = (__bridge ALAssetRepresentation *)decodingContext->assetRepresentation;
  22.     if (decodingContext->decodingIterationCount == kThumbnailDecodingContextMaxIterationCount) {
  23.         NSLog(@"WARNING: Image %@ is too large for thumbnail extraction.", [assetRepresentation url]);
  24.         return 0;
  25.     }
  26.    
  27.     ++decodingContext->decodingIterationCount;
  28.     NSError *error = nil;
  29.     size_t countRead = [assetRepresentation getBytes:(uint8_t *)buffer fromOffset:position length:count error:&error];
  30.     if (countRead == 0 || error != nil) {
  31.         NSLog(@"ERROR: Failed to decode image %@: %@", [assetRepresentation url], error);
  32.         return 0;
  33.     }
  34.    
  35.     return countRead;
  36. }
  37.  
  38. - (UIImage*)thumbnailImageSize:(int)size
  39. {
  40.     if ([[self valueForProperty:@"ALAssetPropertyType"] isEqualToString:@"ALAssetTypePhoto"]) {
  41.        
  42.         CGDataProviderDirectCallbacks callbacks = {
  43.             .version = 0,
  44.             .getBytePointer = NULL,
  45.             .releaseBytePointer = NULL,
  46.             .getBytesAtPosition = getAssetBytesCallback,
  47.             .releaseInfo = NULL
  48.         };
  49.        
  50.         ThumbnailDecodingContext decodingContext = {
  51.             .assetRepresentation = (__bridge void *)self.defaultRepresentation,
  52.             .decodingIterationCount = 0
  53.         };
  54.        
  55.         CGDataProviderRef provider = CGDataProviderCreateDirect((void *)&decodingContext,
  56.                         [self.defaultRepresentation size], &callbacks);
  57.         if (!provider)
  58.             return nil;
  59.        
  60.         CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL);
  61.         if (!source) {
  62.             CGDataProviderRelease(provider);
  63.             return nil;
  64.         }
  65.        
  66.     CFDictionaryRef options = (__bridge CFDictionaryRef) @{
  67.                                    (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
  68.                                    (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
  69.                                    (id) kCGImageSourceThumbnailMaxPixelSize : @(size)};
  70.    
  71.     CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(imageSourceRef, 0, options);
  72.     if (!imageRef) {
  73.             return nil;
  74.         }
  75.    
  76.         UIImage *image = [UIImage imageWithCGImage:imageRef];
  77.         CGImageRelease(imageRef);
  78.         CFRelease(source);
  79.         CGDataProviderRelease(provider);
  80.        
  81.         return image;
  82. }
  83. @end
RAW Paste Data