Generating custom thumbnail from ALAssetRepresentation
You can use CGImageSourceCreateThumbnailAtIndex
to create a small image from a potentially-large image source. You can load your image from disk using the ALAssetRepresentation
's getBytes:fromOffset:length:error:
method, and use that to create a CGImageSourceRef.
Then you just need to pass the kCGImageSourceThumbnailMaxPixelSize
and kCGImageSourceCreateThumbnailFromImageAlways
options to CGImageSourceCreateThumbnailAtIndex
with the image source you've created, and it will create a smaller version for you without loading the huge version into memory.
I've written a blog post and gist with this technique fleshed out in full.
How to get a low res image, or Thumbnail from the ALAssetRepresentation in Swift
Here's an example (there might be some minor compilation issues, depending what version of Swift you are using):
let src = CGImageSourceCreateWithURL(url, nil)
let scale = UIScreen.mainScreen().scale
let w = // desired display width, multiplied by scale
let d : [NSObject:AnyObject] = [
kCGImageSourceShouldAllowFloat : true,
kCGImageSourceCreateThumbnailWithTransform : true,
kCGImageSourceCreateThumbnailFromImageAlways : true,
kCGImageSourceThumbnailMaxPixelSize : w
]
let imref = CGImageSourceCreateThumbnailAtIndex(src, 0, d)
let im = UIImage(CGImage: imref, scale: scale, orientation: .Up)!
However, note that you should not be using ALAssetsLibrary any longer. It is deprecated in iOS 9. Switch to Photo Kit, and welcome to the modern world! Now you can call PHImageManager.defaultManager().requestImageForAsset
, which allows you to supply a targetSize
for the desired image.
How do I get a thumbnail or saveable path from UIImagePickerController to use for a UIImageView?
//If you are reading this and look at the comments below and think ??WTF?? it is because I am editing my original Answer instead of posting two Answers in hopes that things will be cleaner. It is important to know that ALAssetsLibrary is an iOS 4.x thing.
The code below will function to take an asset-library URL and then make a UIImage out of the thumbnail representation. Though I use the asset-library url directly there is no reason that this same code couldn't begin by transforming a string representation into a NSURL in order to satisfy the imageURL
assignment. Disclaimer: this code probably leaks or something worse, but it answers the original poster's question and is hopefully of value.
The code below is borrowing heavily on this Stack Overflow question that covers basically this same topic. In addition to the code here, I have included AssetsLibrary.framework and the ALAssetsLibrary typedefs referenced in the other question.
The whole trick is that you cannot reference the NSURL from an asset-library directly. I think (though I don't know) that it is somehow referencing a data store instead of a file so the data returned from the URL isn't straight NSData so you cannot use it the old way.
There is a UIImageView in the code that is called photo
. Hopefully everything else is easy to figure out.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
NSLog(@"%@",imageURL);
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
CGImageRef iref = [myasset thumbnail];
if (iref) {
UIImage *theThumbnail = [UIImage imageWithCGImage:iref];
[[self photo] setImage:theThumbnail];
}
};
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
NSLog(@"booya, cant get image - %@",[myerror localizedDescription]);
};
if(imageURL)
{
ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:imageURL
resultBlock:resultblock
failureBlock:failureblock];
}
[self dismissModalViewControllerAnimated:YES];
}
If you don't want the thumbnail but do want the full photo, you will just change the code in the AssetForURLResult block to something like this:
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
We can leave that exercize for the user.
Good luck, hope this helps clear things up for you.
How to get thumbnail image of video from ALAsset in iOS?
Code form reference site : Thumbnail image from Video
Objective - C
-(UIImage *)generateThumbImage : (NSString *)filepath
{
NSURL *url = [NSURL fileURLWithPath:filepath];
AVAsset *asset = [AVAsset assetWithURL:url];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
self.imageGenerator.appliesPreferredTrackTransform = YES;
CMTime time = [asset duration];
time.value = 0;
Float duration = CMTimeGetSeconds([myAsset duration]);
for(Float i = 0.0; i<duration; i=i+0.1)
{
CGImageRef imgRef = [self.imageGenerator copyCGImageAtTime:CMTimeMake(i, duration) actualTime:NULL error:nil];
UIImage* thumbnail = [[UIImage alloc] initWithCGImage:imgRef scale:UIViewContentModeScaleAspectFit orientation:UIImageOrientationUp];
[thumbnailImages addObject:thumbnail];
}
}
Swift
func generateThumbImage(url : NSURL) -> UIImage{
var asset : AVAsset = AVAsset.assetWithURL(url) as! AVAsset
var assetImgGenerate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
var error : NSError? = nil
var time : CMTime = CMTimeMake(1, 30)
var img : CGImageRef = assetImgGenerate.copyCGImageAtTime(time, actualTime: nil, error: &error)
var frameImg : UIImage = UIImage(CGImage: img)!
return frameImg
}
display image from URL retrieved from ALAsset in 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];
}
};
Getting thumbnail of a video picked from photos library
If you are loading videos from image library, it should already have the embedded thumbnail of the video. This can be accessed using thumbnail
or aspectRatioThumnail
methods of ALAsset
class.
So in your case the thumbnails could be loaded like:
ALAssetLibrary* lib = [ALAssetLibrary new];
[lib assetForURL:contentURL resultBlock:^(ALAsset* asset) {
CGImageRef thumb = [asset thumbnail];
dispatch_async(dispatch_get_main_queue(), ^{
//do any UI operation here with thumb
});
}];
Please make sure to make any UIKit call in the main queue as assetForURL::
method may invoke the resultBlock
in some background thread.
Related Topics
Where Is the Official Documentation for Cvopenglestexture Method Types
How to Properly Animate Uiscrollview Contentoffset
Xcode 8 with Mixed Swift and Objective-C Project Generated "Modulename-Swift.H" Header Not Found
Where to Place a .Txt File and Read from It in a iOS Project
Annotation Along Route in Mapkit
Passing Data Between 2 Uiviewcontroller Using Delegate and Protocol
How to Pass Data to Another Controller on Dismiss Viewcontroller
How to Change the Development Language in Xcode Before Internationalizing My App
How to Use Uiactivityitemprovider to Send an Email with Attachment with Uiactivityviewcontroller
Opening Word,Excel, and PDF Files Without Using Uiwebview on iOS
How to Install the "App Store" in an iOS Simulator
Delete Cell from Uicollectionview Without Reloading from Top
React-Native iOS Not Showing Images (Pods Issue)
Dragging Scnnode in Arkit Using Scenekit
Intercept Request with Wkwebview
Ios/Swift - Hide/Show Uitabbarcontroller When Scrolling Down/Up