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];
}

正常に動作していますが、高解像度の画像をインポートしようとすると時間がかかります。最短時間でインポートする正しい方法は何ですか? imageところで: を に変換すると時間がかかりますNSData

4

2 に答える 2

23

いくつかの理由から、このタスクに fullResolutionImage を使用するのは危険です。いくつかのコメント:

  1. 大きな画像の場合、メモリの問題が発生する可能性があります。fullResolutionImage メソッドを使用する場合。Photo-Library (少なくとも iPad では) には RAW 画像も含めることができることに注意してください。
  2. イメージファイルから ImageIO が最初に CGImageRef を作成し、次に JPEG に変換するため、パフォーマンスは最適ではありません。これには時間がかかります。
  3. AssetLibrary には、ビデオを含めることもできます。このような場合、fullResolutionImage はビデオの previewImage のみを返しますが、実際のビデオは返しません。
  4. 実際の Asset-Object はメモリが小さいため、保存しても問題ありません。

画像をドキュメント ディレクトリに書き出すためのはるかに優れた方法は、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 を使用していましたが、asselt を使用して写真ライブラリから一度に複数の写真をインポートしているときに同じ問題に直面していました。インポートにかかる時間を短縮することはできませんが、クラッシュの問題は解決されます。

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];
    }
}

可能であれば、ALAsset オブジェクト全体ではなく、assetArray に AssetURL のみを格納し、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 に答える