Skip to content

Instantly share code, notes, and snippets.

@jder
Last active March 20, 2018 06:51
Show Gist options
  • Save jder/4331450 to your computer and use it in GitHub Desktop.
Save jder/4331450 to your computer and use it in GitHub Desktop.

Revisions

  1. jder revised this gist May 6, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Downscaling ALAssets
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    // See http://mindsea.com/2012/12/18/downscaling-huge-alassets-without-fear-of-sigkill for details
    // For details, see http://mindsea.com/2012/12/18/downscaling-huge-alassets-without-fear-of-sigkill

    #import <AssetsLibrary/AssetsLibrary.h>
    #import <ImageIO/ImageIO.h>
  2. jder revised this gist Dec 18, 2012. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions Downscaling ALAssets
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,7 @@
    #import <AssetsLibrary/AssetsLibrary.h>
    #import <ImageIO/ImageIO.h>

    // Helper methods for thumbnailForAsset:ofSize:
    // Helper methods for thumbnailForAsset:maxPixelSize:
    static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, size_t count) {
    ALAssetRepresentation *rep = (__bridge id)info;

    @@ -12,14 +12,14 @@ static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, si

    if (countRead == 0 && error) {
    // We have no way of passing this info back to the caller, so we log it, at least.
    NSLog(@"thumbnailForAsset:ofSize: got an error reading an asset: %@", error);
    NSLog(@"thumbnailForAsset:maxPixelSize: got an error reading an asset: %@", error);
    }

    return countRead;
    }

    static void releaseAssetCallback(void *info) {
    // The info here is an ALAssetRepresentation which we CFRetain in thumbnailForAsset:ofSize:.
    // The info here is an ALAssetRepresentation which we CFRetain in thumbnailForAsset:maxPixelSize:.
    // This release balances that retain.
    CFRelease(info);
    }
    @@ -28,7 +28,7 @@ static void releaseAssetCallback(void *info) {
    // The resulting UIImage will be already rotated to UIImageOrientationUp, so its CGImageRef
    // can be used directly without additional rotation handling.
    // This is done synchronously, so you should call this method on a background queue/thread.
    - (UIImage *)thumbnailForAsset:(ALAsset *)asset ofSize:(NSUInteger)size {
    - (UIImage *)thumbnailForAsset:(ALAsset *)asset maxPixelSize:(NSUInteger)size {
    NSParameterAssert(asset != nil);
    NSParameterAssert(size > 0);

  3. jder revised this gist Dec 18, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Downscaling ALAssets
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    // See http://mindsea.com/?p=1426 for details
    // See http://mindsea.com/2012/12/18/downscaling-huge-alassets-without-fear-of-sigkill for details

    #import <AssetsLibrary/AssetsLibrary.h>
    #import <ImageIO/ImageIO.h>
  4. jder renamed this gist Dec 18, 2012. 1 changed file with 0 additions and 0 deletions.
  5. jder created this gist Dec 18, 2012.
    65 changes: 65 additions & 0 deletions Downscaling Huge ALAssets Without Fear of SIGKILL
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    // See http://mindsea.com/?p=1426 for details

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

    // Helper methods for thumbnailForAsset:ofSize:
    static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, size_t count) {
    ALAssetRepresentation *rep = (__bridge id)info;

    NSError *error = nil;
    size_t countRead = [rep getBytes:(uint8_t *)buffer fromOffset:position length:count error:&error];

    if (countRead == 0 && error) {
    // We have no way of passing this info back to the caller, so we log it, at least.
    NSLog(@"thumbnailForAsset:ofSize: got an error reading an asset: %@", error);
    }

    return countRead;
    }

    static void releaseAssetCallback(void *info) {
    // The info here is an ALAssetRepresentation which we CFRetain in thumbnailForAsset:ofSize:.
    // This release balances that retain.
    CFRelease(info);
    }

    // Returns a UIImage for the given asset, with size length at most the passed size.
    // The resulting UIImage will be already rotated to UIImageOrientationUp, so its CGImageRef
    // can be used directly without additional rotation handling.
    // This is done synchronously, so you should call this method on a background queue/thread.
    - (UIImage *)thumbnailForAsset:(ALAsset *)asset ofSize:(NSUInteger)size {
    NSParameterAssert(asset != nil);
    NSParameterAssert(size > 0);

    ALAssetRepresentation *rep = [asset defaultRepresentation];

    CGDataProviderDirectCallbacks callbacks = {
    .version = 0,
    .getBytePointer = NULL,
    .releaseBytePointer = NULL,
    .getBytesAtPosition = getAssetBytesCallback,
    .releaseInfo = releaseAssetCallback,
    };

    CGDataProviderRef provider = CGDataProviderCreateDirect((void *)CFBridgingRetain(rep), [rep size], &callbacks);
    CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL);

    CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(source, 0, (__bridge CFDictionaryRef) @{
    (NSString *)kCGImageSourceCreateThumbnailFromImageAlways : @YES,
    (NSString *)kCGImageSourceThumbnailMaxPixelSize : [NSNumber numberWithInt:size],
    (NSString *)kCGImageSourceCreateThumbnailWithTransform : @YES,
    });
    CFRelease(source);
    CFRelease(provider);

    if (!imageRef) {
    return nil;
    }

    UIImage *toReturn = [UIImage imageWithCGImage:imageRef];

    CFRelease(imageRef);

    return toReturn;
    }