如何在 iCloud Drive 上生成图像的缩略图?
How to generate thumbnails of images on iCloud Drive?
这看起来很简单,但由于缺乏文档,这道题很难猜到。
我的应用程序的 icloud 驱动器上有图片和视频,我想创建这些资产的缩略图。我说的是 iCloud Drive 上的资产,而不是相机胶卷中的 iCloud 照片流。我说的是真正的 iCloud Drive 文件夹。
与图像相比,从视频创建缩略图 "easy"。你只需要 2 周的时间来弄清楚它是如何工作的,考虑到苹果写的糟糕的文档,但图像的缩略图似乎是不可能的。
我现在拥有的是一个 NSMetadataItem
数组,每个数组描述 iCloud 文件夹中的一个项目。
目前我已经尝试过这些方法不起作用:
方法一
[fileURL startAccessingSecurityScopedResource];
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] init];
__block NSError *error;
[coordinator coordinateReadingItemAtURL:fileURL
options:NSFileCoordinatorReadingImmediatelyAvailableMetadataOnly
error:&error
byAccessor:^(NSURL *newURL) {
NSDictionary *thumb;
BOOL success = [newURL getResourceValue:&thumb forKey:NSURLThumbnailDictionaryKey error:&error];
UIImage *thumbnail = thumb[NSThumbnail1024x1024SizeKey];
}];
[fileURL stopAccessingSecurityScopedResource];
这种方法的结果非常棒。准备好了吗?我们开始:success = YES
、error = nil
和 thumbnail = nil.
另一种方法
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:fileURL
options:nil];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
imageGenerator.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMake(0, 60); // time range in which you want
NSValue *timeValue = [NSValue valueWithCMTime:time];
[imageGenerator generateCGImagesAsynchronouslyForTimes:@[timeValue] completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * error) {
thumbnail = [[UIImage alloc] initWithCGImage:image];
}];
error = The requested URL was not found on this server.
和 thumbnail = nil
此方法似乎仅适用于视频。我正在尝试以防万一。此方法是否等效于图像?
原始方法
NSData *tempData = [NSData dataWithContentsOfUrl:tempURL];
没有 - 数据=无
方法 4
第四种可能的方法是使用 ALAsset
但这在 iOS 9.
上已被弃用
我认为所有这些方法都会失败,因为如果资源是本地的,它们就可以工作(无论是否有错误)。关于如何下载图像以便获取缩略图的任何想法?
还有其他想法吗?
谢谢
编辑:经过多次测试后,我发现方法 1 是唯一似乎方向正确的方法。这种方法效果不佳,有时会抓住图标,但大部分时间都不起作用。
还有一点就是这个。无论人们向我提出什么建议,他们总是说要下载整个图像以获得缩略图。我不认为这是要走的路。看看如何获取视频缩略图。您不会下载整个视频来获取其缩略图。
所以这个
问题仍然悬而未决。
Photos-Framework 或 AssetsLibrary 在这里不起作用,因为您必须先将 iCloud Drive 照片导入 PhotoLibrary 才能使用这两个框架的任何方法。
你应该看的是ImageIO:
将 iCloud Drive Photo 的内容获取为 NSData,然后按如下方式进行:
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)(imageData), NULL );
NSDictionary* thumbOpts = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageAlways,
[NSNumber numberWithInt:160],(id)kCGImageSourceThumbnailMaxPixelSize,
nil];
CGImageRef thumbImageRef = CGImageSourceCreateThumbnailAtIndex(source,0,(__bridge CFDictionaryRef)thumbOpts);
UIImage *thumbnail = [[UIImage alloc] initWithCGImage: thumbImageRef];
在测试了几种解决方案之后,似乎效果更好的是这个:
[fileURL startAccessingSecurityScopedResource];
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] init];
__block NSError *error;
[coordinator coordinateReadingItemAtURL:fileURL
options:NSFileCoordinatorReadingImmediatelyAvailableMetadataOnly
error:&error
byAccessor:^(NSURL *newURL) {
NSDictionary *thumb;
BOOL success = [newURL getResourceValue:&thumb forKey:NSURLThumbnailDictionaryKey error:&error];
UIImage *thumbnail = thumb[NSThumbnail1024x1024SizeKey];
}];
[fileURL stopAccessingSecurityScopedResource];
这个解决方案并不完美。有时它会无法显示缩略图,但我无法找到任何其他 100% 有效的解决方案。其他人比那更糟糕。
您似乎是在事后生成缩略图。如果这是您的文档并且您使用的是 UIDocument,请覆盖 fileAttributesToWriteToURL:forSaveOperation:error:
以在保存文档时插入缩略图。
这适用于 me.It 有点不同
func genereatePreviewForOnce(at size: CGSize,completionHandler: @escaping (UIImage?) -> Void) {
_ = fileURL.startAccessingSecurityScopedResource()
let fileCoorinator = NSFileCoordinator.init()
fileCoorinator.coordinate(readingItemAt: fileURL, options: .immediatelyAvailableMetadataOnly, error: nil) { (url) in
if let res = try? url.resourceValues(forKeys: [.thumbnailDictionaryKey]),
let dict = res.thumbnailDictionary {
let image = dict[.NSThumbnail1024x1024SizeKey]
completionHandler(image)
} else {
fileURL.removeCachedResourceValue(forKey: .thumbnailDictionaryKey)
completionHandler(nil)
}
fileURL.stopAccessingSecurityScopedResource()
}
}
这看起来很简单,但由于缺乏文档,这道题很难猜到。
我的应用程序的 icloud 驱动器上有图片和视频,我想创建这些资产的缩略图。我说的是 iCloud Drive 上的资产,而不是相机胶卷中的 iCloud 照片流。我说的是真正的 iCloud Drive 文件夹。
与图像相比,从视频创建缩略图 "easy"。你只需要 2 周的时间来弄清楚它是如何工作的,考虑到苹果写的糟糕的文档,但图像的缩略图似乎是不可能的。
我现在拥有的是一个 NSMetadataItem
数组,每个数组描述 iCloud 文件夹中的一个项目。
目前我已经尝试过这些方法不起作用:
方法一
[fileURL startAccessingSecurityScopedResource];
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] init];
__block NSError *error;
[coordinator coordinateReadingItemAtURL:fileURL
options:NSFileCoordinatorReadingImmediatelyAvailableMetadataOnly
error:&error
byAccessor:^(NSURL *newURL) {
NSDictionary *thumb;
BOOL success = [newURL getResourceValue:&thumb forKey:NSURLThumbnailDictionaryKey error:&error];
UIImage *thumbnail = thumb[NSThumbnail1024x1024SizeKey];
}];
[fileURL stopAccessingSecurityScopedResource];
这种方法的结果非常棒。准备好了吗?我们开始:success = YES
、error = nil
和 thumbnail = nil.
另一种方法
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:fileURL
options:nil];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
imageGenerator.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMake(0, 60); // time range in which you want
NSValue *timeValue = [NSValue valueWithCMTime:time];
[imageGenerator generateCGImagesAsynchronouslyForTimes:@[timeValue] completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * error) {
thumbnail = [[UIImage alloc] initWithCGImage:image];
}];
error = The requested URL was not found on this server.
和 thumbnail = nil
此方法似乎仅适用于视频。我正在尝试以防万一。此方法是否等效于图像?
原始方法
NSData *tempData = [NSData dataWithContentsOfUrl:tempURL];
没有 - 数据=无
方法 4
第四种可能的方法是使用 ALAsset
但这在 iOS 9.
我认为所有这些方法都会失败,因为如果资源是本地的,它们就可以工作(无论是否有错误)。关于如何下载图像以便获取缩略图的任何想法?
还有其他想法吗?
谢谢
编辑:经过多次测试后,我发现方法 1 是唯一似乎方向正确的方法。这种方法效果不佳,有时会抓住图标,但大部分时间都不起作用。
还有一点就是这个。无论人们向我提出什么建议,他们总是说要下载整个图像以获得缩略图。我不认为这是要走的路。看看如何获取视频缩略图。您不会下载整个视频来获取其缩略图。
所以这个 问题仍然悬而未决。
Photos-Framework 或 AssetsLibrary 在这里不起作用,因为您必须先将 iCloud Drive 照片导入 PhotoLibrary 才能使用这两个框架的任何方法。
你应该看的是ImageIO: 将 iCloud Drive Photo 的内容获取为 NSData,然后按如下方式进行:
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)(imageData), NULL );
NSDictionary* thumbOpts = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageAlways,
[NSNumber numberWithInt:160],(id)kCGImageSourceThumbnailMaxPixelSize,
nil];
CGImageRef thumbImageRef = CGImageSourceCreateThumbnailAtIndex(source,0,(__bridge CFDictionaryRef)thumbOpts);
UIImage *thumbnail = [[UIImage alloc] initWithCGImage: thumbImageRef];
在测试了几种解决方案之后,似乎效果更好的是这个:
[fileURL startAccessingSecurityScopedResource];
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] init];
__block NSError *error;
[coordinator coordinateReadingItemAtURL:fileURL
options:NSFileCoordinatorReadingImmediatelyAvailableMetadataOnly
error:&error
byAccessor:^(NSURL *newURL) {
NSDictionary *thumb;
BOOL success = [newURL getResourceValue:&thumb forKey:NSURLThumbnailDictionaryKey error:&error];
UIImage *thumbnail = thumb[NSThumbnail1024x1024SizeKey];
}];
[fileURL stopAccessingSecurityScopedResource];
这个解决方案并不完美。有时它会无法显示缩略图,但我无法找到任何其他 100% 有效的解决方案。其他人比那更糟糕。
您似乎是在事后生成缩略图。如果这是您的文档并且您使用的是 UIDocument,请覆盖 fileAttributesToWriteToURL:forSaveOperation:error:
以在保存文档时插入缩略图。
这适用于 me.It 有点不同
func genereatePreviewForOnce(at size: CGSize,completionHandler: @escaping (UIImage?) -> Void) {
_ = fileURL.startAccessingSecurityScopedResource()
let fileCoorinator = NSFileCoordinator.init()
fileCoorinator.coordinate(readingItemAt: fileURL, options: .immediatelyAvailableMetadataOnly, error: nil) { (url) in
if let res = try? url.resourceValues(forKeys: [.thumbnailDictionaryKey]),
let dict = res.thumbnailDictionary {
let image = dict[.NSThumbnail1024x1024SizeKey]
completionHandler(image)
} else {
fileURL.removeCachedResourceValue(forKey: .thumbnailDictionaryKey)
completionHandler(nil)
}
fileURL.stopAccessingSecurityScopedResource()
}
}