3

我正在将 iPhone 相册中的照片导入到我的应用程序的文档文件夹中。这是我的代码。

for (int j=0; j<[assetArray count]; j++) {

    ALAsset *assest = [assetArray objectAtIndex:j];
    CGImageRef imageRef = assest.defaultRepresentation.fullResolutionImage;
    UIImage *image = [UIImage imageWithCGImage:imageRef];
    NSData *imageData = UIImageJPEGRepresentation(image);
    [imageData writeToFile:documentsPath atomically:YES];
}

它工作正常,但是当我尝试导入更高分辨率的图像时,它需要更多时间。用最少的时间导入的正确方法是什么?顺便说一句:我将转换imageNSData.

4

2 回答 2

23

出于多种原因,将 fullResolutionImage 用于此任务是很危险的。一些备注:

  1. 对于大图像,可能会出现内存问题。使用 fullResolutionImage 方法时。请注意,照片库(至少在 iPad 上)也可以包含 RAW 图像。
  2. 性能不是最理想的,因为图像文件 ImageIO 在内部首先创建了一个 CGImageRef,然后将其转换为 JPEG。这需要时间。
  3. AssetLibrary 还可以包含视频。在这种情况下,fullResolutionImage 只返回视频的 previewImage,而不是实际的视频。
  4. 存储实际的资产对象没有问题,因为它们在内存中很小。

将图像写入文档目录的更好方法是使用 ALAssetsRepresentation 的 getBytes 方法。这应该是更快和更有效的记忆方式。它还为您提供原始图像文件(包括元数据),也适用于视频。

然后重写的示例代码如下所示:

//reading out the orginal images
    for (int j=0; j<[assetArray count]; j++) {

    ALAssetRepresentation *representation = [[assetArray objectAtIndex:j] defaultRepresentation];
    NSString* filename = [documentPath stringByAppendingPathComponent:[representation filename]];

    [[NSFileManager defaultManager] createFileAtPath:filename contents:nil attributes:nil];
    NSOutputStream *outPutStream = [NSOutputStream outputStreamToFileAtPath:filename append:YES];
    [outPutStream open];

    long long offset = 0;
    long long bytesRead = 0;

    NSError *error;
    uint8_t * buffer = malloc(131072);
    while (offset<[representation size] && [outPutStream hasSpaceAvailable]) {
        bytesRead = [representation getBytes:buffer fromOffset:offset length:131072 error:&error];
        [outPutStream write:buffer maxLength:bytesRead];
        offset = offset+bytesRead;
    }
    [outPutStream close];
    free(buffer);
}


//reading out the fullScreenImages and thumbnails
for (int j=0; j<[assetArray count]; j++) 
{
    @autoreleasepool
    {

        ALAsset *asset = [assetArray objectAtIndex:j];

         NSString *orgFilename = [representation filename];
         NSString *filenameFullScreen = [NSString stringWithFormat:@"%@_fullscreen.png",[orgFilename stringByDeletingPathExtension]]
         NSString* pathFullScreen = [documentPath stringByAppendingPathComponent:filenameFullScreen];

         CGImageRef imageRefFullScreen = [[asset defaultRepresentation] fullScreenImage];
         UIImage *imageFullScreen = [UIImage imageWithCGImage:imageRefFullScreen];
         NSData *imageDataFullScreen = UIImagePNGRepresentation(imageFullScreen);
         [imageDataFullScreen writeToFile:pathFullScreen atomically:YES];

         NSString *filenameThumb = [NSString stringWithFormat:@"%@_thumb.png",[orgFilename stringByDeletingPathExtension]]
         NSString* pathThumb = [documentPath stringByAppendingPathComponent:filenameThumb];

         CGImageRef imageRefThumb = [asset thumbnail];
         UIImage *imageThumb = [UIImage imageWithCGImage:imageRefThumb];
         NSData *imageDataThumb = UIImagePNGRepresentation(imageThumb);
         [imageDataThumb writeToFile:pathThumb atomically:YES];

    }
}
于 2012-04-08T11:44:30.977 回答
5

我使用的是 ELCImagePicker 并且在使用 asselts 从照片库一次导入多张照片时遇到了同样的问题。我们无法减少导入时间,但崩溃问题将得到解决。

for (int j=0; j<[assetArray count]; j++) 
{
    @autoreleasepool // This is compiler level feature so will only work on xcode 4.1 or above
    {
         ALAsset *assest = [assetArray objectAtIndex:j];
         CGImageRef imageRef = assest.defaultRepresentation.fullResolutionImage;
         UIImage *image = [UIImage imageWithCGImage:imageRef];
         NSData *imageData = UIImagePNGRepresentation(image);
         [imageData writeToFile:documentsPath atomically:YES];
    }
}

如果可能,请尝试仅将 AssetURL 存储在assetArray 中,而不是整个 ALAsset 对象,并从 url 一次创建 ALAsset,这样可能有助于减少内存消耗。在这种情况下,您将需要使用块作为

ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
    CGImageRef iref = [[myasset defaultRepresentation] fullResolutionImage];
    if (iref) //You have image so use it 
    {
    }
};

ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)
{
    NSLog(@"Can't get image - %@",[myerror localizedDescription]);
};

ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:imageURL resultBlock:resultblock failureBlock:failureblock];
于 2012-04-02T08:59:16.660 回答