Load UIImage from photos album by url [duplicate] - ios

I have a class that stores information about the assets on the phone (images, videos).
My class has the ResourceURLString defined as such
#property NSURL *ResourceURL;
I am setting the property while looping trough the assets on the phone as such
Item.ResourceURLString = [[asset valueForProperty:ALAssetPropertyURLs] objectForKey:[[asset valueForProperty:ALAssetPropertyRepresentations] objectAtIndex:0]];
When the user clicks on an image I want to load the image.
The code that I have is this
NSData *imageUrl = [NSData dataWithContentsOfURL:[NSURL URLWithString:[CurrentItem.ResourceURL absoluteString]]];
Img = [UIImage imageWithData:imageUrl];
But the Image is always nil
I have verified that the ResourceURL property contains the URL
assets: library://asset/asset.JPG?id=82690321-91C1-4650-8348-F3FD93D14613&ext=JPG

You can't load images in this way.
You need to use ALAssetsLibrary class for this.
Add assetslibrary framework to your project and add header files.
Use the below code for loading image:
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
if (iref) {
UIImage *largeimage = [UIImage imageWithCGImage:iref];
yourImageView.image = largeImage;
}
};
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
NSLog(#"Can't get image - %#",[myerror localizedDescription]);
};
NSURL *asseturl = [NSURL URLWithString:yourURL];
ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:asseturl
resultBlock:resultblock
failureBlock:failureblock];

Since iOS 8 you can use the Photos Framework here is how to do it in Swift 3
import Photos // use the Photos Framework
// declare your asset url
let assetUrl = URL(string: "assets-library://asset/asset.JPG?id=9F983DBA-EC35-42B8-8773-B597CF782EDD&ext=JPG")!
// retrieve the list of matching results for your asset url
let fetchResult = PHAsset.fetchAssets(withALAssetURLs: [assetUrl], options: nil)
if let photo = fetchResult.firstObject {
// retrieve the image for the first result
PHImageManager.default().requestImage(for: photo, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFill, options: nil) {
image, info in
let myImage = image //here is the image
}
}
Use PHImageManagerMaximumSize if you want to retrieve the original size of the picture. But if you want to retrieve a smaller or specific size you can replace PHImageManagerMaximumSize by CGSize(width:150, height:150)

As of iOS 9.0 ALAssetsLibraryis deprecated. Since iOS 8.0, this works with the PHPhotoLibrary. This is a small UIImage extension, Swift 2X.
This uses a fixed image size.
import Photos
extension UIImageView {
func imageFromAssetURL(assetURL: NSURL) {
let asset = PHAsset.fetchAssetsWithALAssetURLs([assetURL], options: nil)
guard let result = asset.firstObject where result is PHAsset else {
return
}
let imageManager = PHImageManager.defaultManager()
imageManager.requestImageForAsset(result as! PHAsset, targetSize: CGSize(width: 200, height: 200), contentMode: PHImageContentMode.AspectFill, options: nil) { (image, dict) -> Void in
if let image = image {
self.image = image
}
}
}
}
Getting the imageReferenceURL from the UIImagePickerController delegate:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
imageURL = info[UIImagePickerControllerReferenceURL] as? NSURL
}
Setting the image
let imageView = UIImageView()
imageView.imageFromAssetURL(imageURL)
There might be effects I haven't encountered yet, a classic would be UITableViewCell or thread problems. I'll keep this updated, also appreciate your feedback.

For Swift 5
fetchAssets(withALAssetURLs) will be removed in a future release. Hence we using fetchAssets to get image from asset local identifier
extension UIImageView {
func imageFromLocalIdentifier(localIdentifier: String, targetSize: CGSize) {
let fetchOptions = PHFetchOptions()
// sort by date desending
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
// fetch photo with localIdentifier
let results = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: fetchOptions)
let manager = PHImageManager.default()
results.enumerateObjects { (thisAsset, _, _) in
manager.requestImage(for: thisAsset, targetSize: targetSize, contentMode: .aspectFit, options: nil, resultHandler: {(image, _) in
DispatchQueue.main.async {[weak self] in
self?.image = image
}
})
}
}
}
Update
let image = UIImage(data: NSData(contentsOf: imageURL as URL)! as Data)

ALAsset *asset = "asset array index"
[tileView.tileImageView setImage:[UIImage imageWithCGImage:[asset thumbnail]]];

Related

How to get original image using PHImageManager

I am using below code to get original image from PHAsset:
PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
requestOptions.resizeMode = PHImageRequestOptionsResizeModeNone;
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
[[PHImageManager defaultManager] requestImageForAsset:phasset
targetSize:PHImageManagerMaximumSize
contentMode:PHImageContentModeDefault
options:requestOptions
resultHandler:^void(UIImage *image, NSDictionary *info) {
if (image) {
}
}];
But found that, image size is greater than the original size. I picked 54 MB file but found its size 123.5MB in response.
Using below code to calculate image size:
NSData *imgData = UIImageJPEGRepresentation(image, 1.0);
NSLog(#"img size: %#", [[NSByteCountFormatter new] stringFromByteCount:imgData.length]);
Any idea how to get an original image using [[PHImageManager defaultManager] requestImageForAsset: API.
I am going to share my code in Swift 5.
In my case, the following code works well on iOS 14.5.1.
extension PHAsset {
func getImageData(_ index: Int, completionHandler: #escaping((_ index: Int, _ image: UIImage?)->Void)) {
let options = PHImageRequestOptions()
options.isSynchronous = true
options.isNetworkAccessAllowed = true
PHImageManager.default().requestImage(for: self, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: options, resultHandler: { (image, info) in
completionHandler(index, image)
})
}
}
Because I call getImageData in background thread and the return value is not correctly ordered, I use a variable named index for calling order and in turn, pass it to completionHanlder so that I can know from where the return value is.
If you don't need index variable, you can delete it.
I wrote a function to get original image below, it worked for me. Hope it works for you, too.
func getAssetThumbnail(asset: PHAsset) -> UIImage {
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
option.isNetworkAccessAllowed = true
option.resizeMode = .none
manager.requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: option) { (result, info) in
thumbnail = result!
}
return thumbnail
}
Use following code to get original image. I have code in Swift, you should convert it to Objective-C
PHImageManager.default().requestImage(for: phAssets.firstObject!, targetSize: PHImageManagerMaximumSize, contentMode: PHImageContentMode.default, options: requestOption) { (image, dictResult) in
// Get file path url of original image.
if let url = dictResult!["PHImageFileURLKey"] as? URL {
self.getImageFromFileUrl(url)
}
}
func getImageFromFileUrl(_ fileUrl: URL) {
// Get dat from url, here I have not using catch block, you must use it for swift.
let imageData = try? Data(contentsOf: fileUrl)
// Get image from data
let image = UIImage(data: imageData!)
// Size count, which is same as original image
let size = ByteCountFormatter()
print("image size = \(size.string(fromByteCount: Int64(imageData!.count)))")
}
For details, I have added comment above the line of code.
I hope this will help you.

get thumbnail images in list and full size image when click on the item of list

So I am using below code to fetch all the images from library which is working fine :
func grabPhotos(){
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
if let fetchResults : PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions){
if fetchResults.count>0{
for i in 0..<fetchResults.count{
imgManager.requestImage(for: fetchResults.object(at: i), targetSize: CGSize(width:100, height: 100), contentMode: .aspectFill, options: requestOptions, resultHandler: {
image, error in
self.Galleryimages.append(image!)
print("array count is ",self.Galleryimages.count)
self.photoCollectionview.reloadData()
})
}
}
}
}
I am showing all the images in my UICollectionView, but I didn't find any way to get original image whenever clicking on any thumbnail image. I want to fetch the original image (full size image) when user clicks on any thumbnail image which is populated in UICollectionView.
Thank you.
To load thumbnail image.
Got the solution after doing too much stuff, may be it can help to others. Below are the steps to do this.
Step 1 : Declare object of PHFetchResult
var Galleryimages: PHFetchResult<PHAsset>!
Step 2 : Fetch results from gallery using below code:
func grabPhotos(){
Galleryimages = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: nil)
}
Step 3 : Show the thumbnail images in your UI (collectionview/Tableview) using below code :
let imageview = cell.viewWithTag(1) as! UIImageView
PHImageManager.default().requestImage(for: (Galleryimages?[indexPath.row])!, targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: nil) { (image: UIImage?, info: [AnyHashable: Any]?) -> Void in
imageview.image = image
}
Step 4 : And finally get the full size image using below code.
let options = PHImageRequestOptions()
options.deliveryMode = .highQualityFormat
options.resizeMode = .exact
PHImageManager.default().requestImage(for: (Galleryimages[indexPath.row]), targetSize: PHImageManagerMaximumSize, contentMode: .aspectFill, options: options) { (image: UIImage?, info: [AnyHashable: Any]?) -> Void in
if let image = image {
//Use this originan image
}
}
You are resizing images when U fetch from PHAsset. So use
targetsize : PHImageManagerMaximumSize
From this U can get original image with its original size. and for your collectionview you can direclty make thumbnail from it and display images. So when user taps on thumbnail, now you can show original image
Please use autoreleasepool for memory management.
for(PHAsset *asset in self.assets) {
// This autorelease pool seems good (a1)
autoreleasepool {
NSLog(#"started requesting image %i", i);
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:[self imageRequestOptions] resultHandler:^(UIImage *image, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
//you can add autorelease pool here as well (a2)
#autoreleasepool {
assetCount++;
NSError *error = [info objectForKey:PHImageErrorKey];
if (error) NSLog(#"Image request error: %#",error);
else {
NSString *imagePath = [appDelegate.docsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%i.png",i]];
NSData *imageData = UIImagePNGRepresentation(image);
if(imageData) {
[imageData writeToFile:imagePath atomically:YES];
[self.imagesArray addObject:imagePath];
}
else {
NSLog(#"Couldn't write image data to file.");
}
[self checkAddComplete];
NSLog(#"finished requesting image %i", i);
}
} //a2 ends here
});
}];
i++;
} // a1 ends here
}

Copy PHAsset from Gallery to other directory in iOS 9

I came through the following link which demonstrated how to copy file from Gallery to application or other directory (in right answer):
How to copy an image file from iOS Photo Library (ALAssetsLibrary) to the local directory of an App?
But with ALAssetsLibrary class documentation Apple said its now deprecated as of iOS 9.0 instead use Photos framework.
The Assets Library framework is deprecated as of iOS 9.0. Instead, use
the Photos framework instead, which in iOS 8.0 and later provides more
features and better performance for working with a user’s photo
library. For more information, see Photos Framework Reference.
How I can use Photos framework to copy assets from Gallery to other URL?
This seems fairly easy. I added an example code for someone whom it may help:
var item: PHAsset! // you update with actual PHAsset at runtime
let docuPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.ApplicationDirectory, NSSearchPathDomainMask.UserDomainMask, true) as NSArray
let targetImgeURL = (docuPath[0] as! String) + "/IMG_0005.JPG"
let phManager = PHImageManager.defaultManager()
let options = PHImageRequestOptions()
options.synchronous = true; // do it if you want things running in background thread
phManager.requestImageDataForAsset(item, options: options)
{ imageData,dataUTI,orientation,info in
if let newData:NSData = imageData
{
try! newData.writeToFile(targetImgeURL, atomically: true)
}
}
Here is the Objective C solution.
-(NSURL*)createVideoCopyFromReferenceUrl:(NSURL*)inputUrlFromVideoPicker{
NSURL __block *videoURL;
PHFetchResult *phAssetFetchResult = [PHAsset fetchAssetsWithALAssetURLs:#[inputUrlFromVideoPicker ] options:nil];
PHAsset *phAsset = [phAssetFetchResult firstObject];
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
if ([asset isKindOfClass:[AVURLAsset class]]) {
NSURL *url = [(AVURLAsset *)asset URL];
NSLog(#"Final URL %#",url);
NSData *videoData = [NSData dataWithContentsOfURL:url];
// optionally, write the video to the temp directory
NSString *videoPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"%f.mp4",[NSDate timeIntervalSinceReferenceDate]]];
videoURL = [NSURL fileURLWithPath:videoPath];
BOOL writeResult = [videoData writeToURL:videoURL atomically:true];
if(writeResult) {
NSLog(#"video success");
}
else {
NSLog(#"video failure");
}
dispatch_group_leave(group);
// use URL to get file content
}
}];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
return videoURL;
}
In Swift use below set of code
import Photos
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
self.dismissViewControllerAnimated(true, completion: nil)
if let referenceURL = info[UIImagePickerControllerReferenceURL] as? NSURL {
let fetchResult = PHAsset.fetchAssetsWithALAssetURLs([referenceURL], options: nil)
if let phAsset = fetchResult.firstObject as? PHAsset {
PHImageManager.defaultManager().requestAVAssetForVideo(phAsset, options: PHVideoRequestOptions(), resultHandler: { (asset, audioMix, info) -> Void in
if let asset = asset as? AVURLAsset {
let videoData = NSData(contentsOfURL: asset.URL)
// optionally, write the video to the temp directory
let videoPath = NSTemporaryDirectory() + "tmpMovie.MOV"
let videoURL = NSURL(fileURLWithPath: videoPath)
let writeResult = videoData?.writeToURL(videoURL, atomically: true)
if let writeResult = writeResult where writeResult {
print("success")
}
else {
print("failure")
}
}
})
}
}
}

iOS - How to get thumbnail from video without play?

I'm trying to get thumbnail from video and show it in my tableview. Here is my code:
- (UIImage *)imageFromVideoURL:(NSURL *)contentURL {
AVAsset *asset = [AVAsset assetWithURL:contentURL];
// Get thumbnail at the very start of the video
CMTime thumbnailTime = [asset duration];
thumbnailTime.value = 25;
// Get image from the video at the given time
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:thumbnailTime actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return thumbnail;
}
But image allways return black. What's wrong?
Using Swift 5, as an extension function on AVAsset:
import AVKit
extension AVAsset {
func generateThumbnail(completion: #escaping (UIImage?) -> Void) {
DispatchQueue.global().async {
let imageGenerator = AVAssetImageGenerator(asset: self)
let time = CMTime(seconds: 0.0, preferredTimescale: 600)
let times = [NSValue(time: time)]
imageGenerator.generateCGImagesAsynchronously(forTimes: times, completionHandler: { _, image, _, _, _ in
if let image = image {
completion(UIImage(cgImage: image))
} else {
completion(nil)
}
})
}
}
}
Usage:
AVAsset(url: url).generateThumbnail { [weak self] (image) in
DispatchQueue.main.async {
guard let image = image else { return }
self?.imageView.image = image
}
}
Use this :
Swift 3 -
func createThumbnailOfVideoFromFileURL(videoURL: String) -> UIImage? {
let asset = AVAsset(url: URL(string: videoURL)!)
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
let time = CMTimeMakeWithSeconds(Float64(1), 100)
do {
let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)
let thumbnail = UIImage(cgImage: img)
return thumbnail
} catch {
return UIImage(named: "ico_placeholder")
}
}
Important Note :
You will need to use this in an if else as it is resource extensive. You will have to store the image in an array or model and check that if once thumbnail has been created it refers to the cache/array so that cellForRowAtIndexPath does not cause a lag in scrolling your UITableView
Just use this code.. Pass your video URL and get an image.
+(UIImage *)getPlaceholderImageFromVideo:(NSString *)videoURL {
NSURL *url = [NSURL URLWithString:videoURL];
AVAsset *asset = [AVAsset assetWithURL:url];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
CMTime time = [asset duration];
time.value = 0;
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return thumbnail;
}
Hope, this is what you're looking for. Any concern get back to me. :)
//(Local URL)
NSURL *videoURL = [NSURL fileURLWithPath:filepath];// filepath is your video file path
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
AVAssetImageGenerator *generateImg = [[AVAssetImageGenerator alloc] initWithAsset:asset];
NSError *error = NULL;
CMTime time = CMTimeMake(1, 1);
CGImageRef refImg = [generateImg copyCGImageAtTime:time actualTime:NULL error:&error];
NSLog(#"error==%#, Refimage==%#", error, refImg);
UIImage *frameImage= [[UIImage alloc] initWithCGImage:refImg];
return frameImage;
Please check the link for "Generating Thumbnails from Videos"
https://littlebitesofcocoa.com/115-generating-thumbnails-from-videos
It's quite common for an app to need to display one or more thumbnails (small still-image previews) of what's in a video. However, depending on where the video is coming from, we might not have easy access to pre-made thumbnail(s) for it. Let's look at how we can use AVAssetImageGenerator to grab our own.
We start with a simple NSURL for the video, this can be local or remote. We'll create an AVAsset with it and that to a new AVAssetImageGenerator object. We'll configure the generator to apply preferred transforms so our thumbnails are in the correct orientation.
import AVFoundation
if let asset = AVAsset(URL: videoURL) {
let durationSeconds = CMTimeGetSeconds(asset.duration)
let generator = AVAssetImageGenerator(asset: asset)
generator.appliesPreferredTrackTransform = true
let time = CMTimeMakeWithSeconds(durationSeconds/3.0, 600)
var thumbnailImage: CGImageRef
generator.generateCGImagesAsynchronouslyForTimes([NSValue(CMTime: time)]) {
(requestedTime: CMTime, thumbnail: CGImage?, actualTime: CMTime, result: AVAssetImageGeneratorResult, error: NSError?) in
self.videoThumbnailImageView.image = UIImage(CGImage: thumbnail)
}
}
Swift 4 code for #Disha's answer:
let imageGenerator = AVAssetImageGenerator(asset: avAsset)
let time = CMTime(seconds: seconds, preferredTimescale: 600)
let times = [NSValue(time: time)]
imageGenerator.generateCGImagesAsynchronously(forTimes: times, completionHandler: {
requestedTime, image, actualTime, result, error in
guard let cgImage = image else
{
print("No image!")
return
}
let uiImage = UIImage(cgImage: cgImage)
UIImageWriteToSavedPhotosAlbum(uiImage, nil, nil, nil);
})
func getThumbnailFrom(path: URL) -> UIImage? {
do {
let asset = AVURLAsset(url: path , options: nil)
let imgGenerator = AVAssetImageGenerator(asset: asset)
imgGenerator.appliesPreferredTrackTransform = true
let timestamp = asset.duration
print("Timestemp: \(timestamp)")
let cgImage = try imgGenerator.copyCGImage(at: timestamp, actualTime: nil)
let thumbnail = UIImage(cgImage: cgImage)
return thumbnail
} catch let error {
print("*** Error generating thumbnail: \(error.localizedDescription)")
return nil
}
}
This Code is working.
SWIFT 5.2 VERSION:
You can find my original post here, where I took inspiration from rozochkin's answer.
func getCurrentFrame() -> UIImage? {
guard let player = self.player, let avPlayerAsset = player.currentItem?.asset else {return nil}
let assetImageGenerator = AVAssetImageGenerator(asset: avPlayerAsset)
assetImageGenerator.requestedTimeToleranceAfter = .zero
assetImageGenerator.requestedTimeToleranceBefore = .zero
assetImageGenerator.appliesPreferredTrackTransform = true
let imageRef = try! assetImageGenerator.copyCGImage(at: player.currentTime(), actualTime: nil)
let image = UIImage(cgImage: imageRef)
return image
}
IMPORTANT NOTES:
requestedTimeToleranceAfter and requestedTimeToleranceBefore should be set to .zero, because, according to source code, "The actual time of the generated images [...] may differ from the requested time for efficiency".
appliesPreferredTrackTransform must be set to TRUE (default is FALSE), otherwise you get a bad-rotated frame. With this property set to TRUE you get what you really see in the player.

Create thumbnail from a video url in IPhone SDK

I am trying to acquire a thumbnail from a video url. The video is a stream (HLS) with the m3u8 format.
I've already tried requestThumbnailImagesAtTimes from the MPMoviePlayerController, but that didn't work. Does anyone have a solution for that problem? If so how'd you do it?
If you don't want to use MPMoviePlayerController, you can do this:
AVAsset *asset = [AVAsset assetWithURL:sourceURL];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
CMTime time = CMTimeMake(1, 1);
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef); // CGImageRef won't be released by ARC
Here's an example in Swift:
func thumbnail(sourceURL sourceURL:NSURL) -> UIImage {
let asset = AVAsset(URL: sourceURL)
let imageGenerator = AVAssetImageGenerator(asset: asset)
let time = CMTime(seconds: 1, preferredTimescale: 1)
do {
let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil)
return UIImage(CGImage: imageRef)
} catch {
print(error)
return UIImage(named: "some generic thumbnail")!
}
}
I prefer using AVAssetImageGenerator over MPMoviePlayerController because it is thread-safe, and you can have more than one instantiated at a time.
Acquire a thumbnail from a video url.
NSString *strVideoURL = #"http://www.xyzvideourl.com/samplevideourl";
NSURL *videoURL = [NSURL URLWithString:strVideoURL] ;
MPMoviePlayerController *player = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL]autorelease];
UIImage *thumbnail = [player thumbnailImageAtTime:1.0 timeOption:MPMovieTimeOptionNearestKeyFrame];
player = nil;
Replace your video URL string with strVideoURL.
You will get thumbnail as a output from video.
And thumbnail is UIImage type data !
-(UIImage *)loadThumbNail:(NSURL *)urlVideo
{
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:urlVideo options:nil];
AVAssetImageGenerator *generate = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generate.appliesPreferredTrackTransform=TRUE;
NSError *err = NULL;
CMTime time = CMTimeMake(1, 60);
CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:NULL error:&err];
NSLog(#"err==%#, imageRef==%#", err, imgRef);
return [[UIImage alloc] initWithCGImage:imgRef];
}
Add AVFoundation framework in your project and don't forget to import <AVFoundation/AVFoundation.h> and you have to pass the path of your video saved in document directory as a parameter and receive the image as UIImage.
you can get the thumbnail from your video url with the use of below code
MPMoviePlayerController *player = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL]autorelease];
UIImage *thumbnail = [player thumbnailImageAtTime:0.0 timeOption:MPMovieTimeOptionNearestKeyFrame];
Maybe this is useful for someone else who faces the same problem. I needed an easy solution for creating a thumbnail for Images, PDFs and Videos. To solve that problem I've created the following Library (in Swift).
https://github.com/prine/ROThumbnailGenerator
The usage is very straightforward:
var thumbnailImage = ROThumbnail.getThumbnail(url)
It has internally three different implementations and depending on the file extension it does create the thumbnail. You can easily add your own implementation if you need a thumbnail creator for another file extension.
Swift 3 Version :
func createThumbnailOfVideoFromFileURL(videoURL: String) -> UIImage? {
let asset = AVAsset(url: URL(string: videoURL)!)
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
let time = CMTimeMakeWithSeconds(Float64(1), 100)
do {
let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)
let thumbnail = UIImage(cgImage: img)
return thumbnail
} catch {
// Set a default image if Image is not acquired
return UIImage(named: "ico_placeholder")
}
}
For Swift 3.0:
func generateThumbnailForVideoAtURL(filePathLocal: NSString) -> UIImage? {
let vidURL = NSURL(fileURLWithPath:filePathLocal as String)
let asset = AVURLAsset(url: vidURL as URL)
let generator = AVAssetImageGenerator(asset: asset)
generator.appliesPreferredTrackTransform = true
let timestamp = CMTime(seconds: 1, preferredTimescale: 60)
do {
let imageRef = try generator.copyCGImage(at: timestamp, actualTime: nil)
let frameImg : UIImage = UIImage(cgImage: imageRef)
return frameImg
} catch let error as NSError {
print("Image generation failed with error ::\(error)")
return nil
}
}
For Swift 5 you can get it this way:
First import AVKit or AVFoundation to ViewController
import AVKit
Code:
// Get Thumbnail Image from URL
private func getThumbnailFromUrl(_ url: String?, _ completion: #escaping ((_ image: UIImage?)->Void)) {
guard let url = URL(string: url ?? "") else { return }
DispatchQueue.main.async {
let asset = AVAsset(url: url)
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
let time = CMTimeMake(value: 2, timescale: 1)
do {
let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)
let thumbnail = UIImage(cgImage: img)
completion(thumbnail)
} catch {
print("Error :: ", error.localizedDescription)
completion(nil)
}
}
}
Usage
#IBOutlet weak imgThumbnail: ImageView!
and then call getThumbnailFromUrl method and pass URL as a Sting
self.getThumbnailFromUrl(videoURL) { [weak self] (img) in
guard let `self` = self else { return }
if let img = img {
self.imgThumbnail.image = img
}
}
Thank you
Swift 2 code with AVAssetImageGenerator:
func thumbnailImageForVideo(url:NSURL) -> UIImage?
{
let asset = AVAsset(URL: url)
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
var time = asset.duration
//If possible - take not the first frame (it could be completely black or white on camara's videos)
time.value = min(time.value, 2)
do {
let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil)
return UIImage(CGImage: imageRef)
}
catch let error as NSError
{
print("Image generation failed with error \(error)")
return nil
}
}

Resources