Objective-C Tips & Trick - Prioregroup.com
[Objective-C] Thumbnail image from ALAsset with a category
       
back

#import <AssetsLibrary/AssetsLibrary.h>
#import <AVFoundation/AVFoundation.h>
#import <ImageIO/ImageIO.h>

@interface ALAsset (Thumbnail)
- (UIImage*)thumbnailImageSize:(int)size;
@end

@implementation ALAsset (Thumbnail)

typedef struct {
    void *assetRepresentation;
    int decodingIterationCount;
} ThumbnailDecodingContext;

static const int kThumbnailDecodingContextMaxIterationCount = 16;

static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, size_t count)
{
    ThumbnailDecodingContext *decodingContext = (ThumbnailDecodingContext *)info;
    ALAssetRepresentation *assetRepresentation = (__bridge ALAssetRepresentation *)decodingContext->assetRepresentation;
    if (decodingContext->decodingIterationCount == kThumbnailDecodingContextMaxIterationCount) {
        NSLog(@"WARNING: Image %@ is too large for thumbnail extraction.", [assetRepresentation url]);
        return 0;
    }
    
    ++decodingContext->decodingIterationCount;
    NSError *error = nil;
    size_t countRead = [assetRepresentation getBytes:(uint8_t *)buffer fromOffset:position length:count error:&error];
    if (countRead == 0 || error != nil) {
        NSLog(@"ERROR: Failed to decode image %@: %@", [assetRepresentation url], error);
        return 0;
    }
    
    return countRead;
}

- (UIImage*)thumbnailImageSize:(int)size
{
    if ([[self valueForProperty:@"ALAssetPropertyType"] isEqualToString:@"ALAssetTypePhoto"]) {
        
        CGDataProviderDirectCallbacks callbacks = {
            .version = 0,
            .getBytePointer = NULL,
            .releaseBytePointer = NULL,
            .getBytesAtPosition = getAssetBytesCallback,
            .releaseInfo = NULL
        };
        
        ThumbnailDecodingContext decodingContext = {
            .assetRepresentation = (__bridge void *)self.defaultRepresentation,
            .decodingIterationCount = 0
        };
        
        CGDataProviderRef provider = CGDataProviderCreateDirect((void *)&decodingContext, 
						[self.defaultRepresentation size], &callbacks);
        if (!provider)
            return nil;
        
        CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL);
        if (!source) {
            CGDataProviderRelease(provider);
            return nil;
        }
        
	CFDictionaryRef options = (__bridge CFDictionaryRef) @{
                                   (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
                                   (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
                                   (id) kCGImageSourceThumbnailMaxPixelSize : @(size)};
    
	CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(imageSourceRef, 0, options);
	if (!imageRef) {
            return nil;
    	}
    
    	UIImage *image = [UIImage imageWithCGImage:imageRef];
    	CGImageRelease(imageRef);
        CFRelease(source);
        CGDataProviderRelease(provider);
        
        return image;
}
@end






Copyright © 1996-2018 Centro Studi Informatica di Danilo Priore. All rights reserved. P.I.10149810581.
prioregroup.com