display image from URL retrieved from ALAsset in iPhone

IphoneImageUrl

Iphone Problem Overview


I am using a ALAsset Framework for accessing the files in the device's photo gallery.

So far I am able to access the thumbnail and display it.
I want to display the actual image in an image view but I am unable to figure out how to do this.

I tried using the URLs field in the ALAsset object but was unsuccessful.

Anybody knows how this can be done?

Here's some code where I was able to access the thumbnail and place it in a table cell:

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {


  static NSString *CellIdentifier = @"Cell";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  }
  //here 'asset' represents the ALAsset object


  asset = [assets objectAtIndex:indexPath.row];
       //i am accessing the thumbnail here
  [cell.imageView setImage:[UIImage imageWithCGImage:[asset thumbnail]]];
  [cell.textLabel setText:[NSString stringWithFormat:@"Photo %d", indexPath.row+1]];

  return cell;
}

Iphone Solutions


Solution 1 - Iphone

The API has changed the rules slightly and you dont get direct file system access to the iPhoto library any more. Instead you get asset library URL's like this.

assets-library://asset/asset.JPG?id=1000000003&ext=JPG

You use the ALAssetLibrary object to access the ALAsset object via the URL.

so from the docs for ALAssetLibrary throw this in a header (or your source)

typedef void (^ALAssetsLibraryAssetForURLResultBlock)(ALAsset *asset);
typedef void (^ALAssetsLibraryAccessFailureBlock)(NSError *error);

which isnt strictly needed but keeps things pretty.
and then in your source.

-(void)findLargeImage
{
	NSString *mediaurl = [self.node valueForKey:kVMMediaURL];

	//
	ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
	{
		ALAssetRepresentation *rep = [myasset defaultRepresentation];
		CGImageRef iref = [rep fullResolutionImage];
		if (iref) {
			largeimage = [UIImage imageWithCGImage:iref];
			[largeimage retain];
		}
	};
	
	//
	ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)
	{
		NSLog(@"booya, cant get image - %@",[myerror localizedDescription]);
	};
		
	if(mediaurl && [mediaurl length] && ![[mediaurl pathExtension] isEqualToString:AUDIO_EXTENSION])
	{
		[largeimage release];
		NSURL *asseturl = [NSURL URLWithString:mediaurl];
		ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
		[assetslibrary assetForURL:asseturl 
					   resultBlock:resultblock
					  failureBlock:failureblock];
	}
}

A couple of things to note are that this uses blocks which were new to me before I started my iOS4 porting but you might like to look at

https://www.mikeash.com/pyblog/friday-qa-2008-12-26.html

and

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html

They bend your head a little but if you think of them as notification selectors or callbacks it kind of helps.

Also

  • when findLargeImage returns the resultblock wont have run yet as its a callback. So largeImage wont be valid yet.
  • largeImage needs to be an instance variable not scoped to the method.

I use this construct to do this when using the method but you may find something more suitable to your use.

[node.view findLargeImage];
UIImage *thumb = node.view.largeImage;
if (thumb) { blah blah }

Thats what I learned while trying to get this working anyway.

iOS 5 update

When the result block fires seems to be a bit slower with iOS5 & maybe single core devices so I couldnt rely on the image to be available directly after calling findLargeImage. So I changed it to call out to a delegate.

@protocol HiresImageDelegate <NSObject>
@optional
-(void)hiresImageAvailable:(UIImage *)aimage;
@end

and comme cá

//
    ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
    {
        ALAssetRepresentation *rep = [myasset defaultRepresentation];
        CGImageRef iref = [rep fullResolutionImage];
        if (iref) {
            UIImage *largeimage = [UIImage imageWithCGImage:iref];
            [delegate hiresImageAvailable:large];
        }
    };

Solution 2 - Iphone

Warren's answer worked well for me. One useful thing for some people is to include the image orientation and scale metadata at the same time. You do this in your result block like so:

ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
    ALAssetRepresentation *rep = [myasset defaultRepresentation];
    CGImageRef iref = [rep fullResolutionImage];
    if (iref) 
    {
        UIImage *largeimage = [UIImage imageWithCGImage:iref scale:[rep scale] orientation:[rep orientation]];
        [delegate hiresImageAvailable:large];
    }
};

The imageWIthCGImage call in that case has scale and orientation added when it creates a UIImage for you.

[UIImage imageWithCGImage:iref scale:[rep scale] orientation:[rep orientation]];

One trick to note is that if you use [rep fullScreenImage] instead of [rep fullResolutionImage] on iOS 5 you get an image that is already rotated - it is however at the resolution of the iPhone screen - i.e. its at a lower resolution.

Solution 3 - Iphone

Just to combine Warren's and oknox's answers into a shorter snippet:

ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
[assetsLibrary assetForURL:self.selectedPhotos[i] resultBlock: ^(ALAsset *asset){
    ALAssetRepresentation *representation = [asset defaultRepresentation];
    CGImageRef imageRef = [representation fullResolutionImage];
    if (imageRef) {
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
        imageView.image = [UIImage imageWithCGImage:imageRef scale:representation.scale orientation:representation.orientation];
        // ...
    }
} failureBlock: ^{
    // Handle failure.
}];

I personally like setting my failureBlock to nil.

Solution 4 - Iphone

     NSURL* aURL = [NSURL URLWithString:@"URL here"];
     
     ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
     [library assetForURL:aURL resultBlock:^(ALAsset *asset)
     {
     UIImage  *copyOfOriginalImage = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage] scale:0.5 orientation:UIImageOrientationUp];
     
     cell.backgroundView = [[UIImageView alloc] initWithImage:copyOfOriginalImage];
     }
     failureBlock:^(NSError *error)
     {
     // error handling
     NSLog(@"failure-----");
     }];

just provide the UIReferenceURl you got for the image in photolibrary provided above... its just works fine . . .I diplayed it in

  • UIcollectionView cell

    ..if you just wanna display it in a

  • UIImageView

    means

Change

cell.backgroundView = [[UIImageView alloc] initWithImage:copyOfOriginalImage];

To

imageView.image = copyOfOriginalImage;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBangdelView Question on Stackoverflow
Solution 1 - IphoneWarren BurtonView Answer on Stackoverflow
Solution 2 - IphoneoknoxView Answer on Stackoverflow
Solution 3 - IphoneMLQView Answer on Stackoverflow
Solution 4 - IphonesukuView Answer on Stackoverflow