高级别摘要: 我想用更高质量的版本替换相当低分辨率的ALAsset组图像 [group posterImage] ,以便它们可以在屏幕上显示得更大。通常我会根据需要加载它们,但 [ALAssetsGroup enumerateAssetsAtIndexes] 非常慢。 (我可以预先加载超过可见量的x量,并且可能仍然会这样做,但这似乎比它的价值更麻烦,并且仍然受到响应缓慢的影响,特别是在iOS5中)
我认为我可以做的是请求每个组中的第一个资产,然后对其进行缩放,存储结果。然而,即使考虑到更大尺寸的图像,我对正在发生的内存分配感到惊讶。使用VM Tracker,我看到了大量的CGImage分配以及我正在创建的“映射文件”缩略图。我正在使用ARC,所以我预计原始的大图像会丢失,但我的VM Tracker结果并没有证明这一点。
如果我使用默认的 posterImage 实现,我的Resident Mem~ = 30mb,Dirty Mem~ = 80mb,Virtual tops~240mb(自身大)。 '直播'<每个分配分析器10mb。
如果我使用以下代码,我会崩溃加载150中的~80th图像。此时我的Resident Mem> 480mb,Dirty Mem> 420mb和Virtual是一个惊人的750mb。显然这是站不住脚的。
以下是我在NSOperationQueue中使用的代码,用于抓取每个组的第一张图像以用作高分辨率海报图像。
NSIndexSet* i = [NSIndexSet indexSetWithIndex:0];
ALAssetsGroupEnumerationResultsBlock assetsEnumerationBlock = ^(ALAsset *result, NSUInteger i, BOOL *stop) {
if (result) {
// pull the full resolution image and then scale it to fit our desired area
ALAssetRepresentation *assetRepresentation = [result defaultRepresentation];
CGImageRef ref = [assetRepresentation fullScreenImage];
CGFloat imgWidth = CGImageGetWidth(ref);
CGFloat imgHeight = CGImageGetHeight(ref);
CGFloat minDimension = MIN(imgWidth,imgHeight);
// grab a square subset of the image, centered, to use
CGRect subRect = CGRectMake(0, 0, minDimension, minDimension);
subRect.origin = CGPointMake(imgWidth / 2 - minDimension / 2, imgHeight / 2 - minDimension / 2);
CGImageRef squareRef = CGImageCreateWithImageInRect(ref,subRect);
// now scale it down to fit
CGFloat heightScale = dimension / minDimension;
UIImage* coverImage = [UIImage imageWithCGImage:squareRef scale:1/heightScale orientation:UIImageOrientationUp];
if (coverImage) {
[mainViewController performSelectorOnMainThread:@selector(imageDidLoad:)
withObject:[NSArray arrayWithObjects:coverImage, [NSNumber numberWithInt:photoIndex], nil]
waitUntilDone:NO];
}
CGImageRelease(squareRef);
// DO NOT RELEASE 'ref' it will be 'zombied' as it is already handled by the system
//CGImageRelease(ref);
*stop = YES;
}
else {
// default image grab....
}
};
[group enumerateAssetsAtIndexes:i options:NSEnumerationConcurrent usingBlock:assetsEnumerationBlock];
我是否对上述内容有所不妥,或者我只是因为加载所有图片而不聪明?我想的越多,我就越想加载一个可见图像窗口加上一个缓冲区就可以了,但我想了解更多关于我上面代码可能做错的事情。 谢谢!
答案 0 :(得分:0)
我做了与你完全相同的事情但是由于这个答案:Fetching the last image captured through iPhone camera,我设法让它快得多,而不是耗尽尽可能多的内存。
这当然会使图像变小,因为你没有获取fullScreenImage而只是缩略图..
我的最终代码:
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
// Within the group enumeration block, filter to enumerate just photos.
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
int nrOfPhotos = 200;
[group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, nrOfPhotos)]
options:0
usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {
// The end of the enumeration is signaled by asset == nil.
if (alAsset) {
NSLog(@"Index: %i", index);
CGImageRef imageRef = [alAsset thumbnail];
UIImage *latestPhoto = [UIImage imageWithCGImage:imageRef scale:1.f orientation:UIImageOrientationUp];
//Do something with images
}
}];
}
failureBlock: ^(NSError *error) {
// Typically you should handle an error more gracefully than this.
NSLog(@"No groups");
}];