2012-04-02 12 views
3

iPhoneのアルバムから自分のアプリケーションのドキュメントフォルダに写真をインポートしています。これは私のコードです。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に変換すると時間がかかります。

+0

私は同じ問題を抱えていたが、私は、データベース内の資産のURLを保存して、それを解決して、私はドキュメントディレクトリに画像を保存する必要があるときに私はで資産1を取得しますドキュメントディレクトリにイメージを格納します。 1つの理由は、配列のアセット資産を保存することである可能性があります。アセットのURLと、メモリーの問題を減らす自動解放プールのループでもう1つこれを実行します。 – Leena

答えて

23

このタスクには、いくつかの理由でfullResolutionImageを使用することは危険です。 備考:

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

ドキュメントディレクトリにイメージを書き込む方がはるかに良い方法は、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]; 

    } 
} 
+0

非常にうまく働いてくれてありがとう..しかし、どうやってサムネイルイメージとフルスクリーンイメージをドキュメントフォルダにコピーできますか?またはドキュメントフォルダのALAssetsRepresentationからこれらのイメージを取得するための他の方法がありますか? – Aravindhan

+1

fullScreenImageとサムネイルの読み込みを含むソースコードを修正しました。これらの2つのイメージでは、以前のアプローチを使用することができます。これは、サイズが限られており、fullResolutionImageとは対照的に、予測可能な量のメモリしか消費しないためです。あなたがしたいことに応じて、fullScreenImageをPNGの代わりにJPEGとして保存することを検討するかもしれませんが、これはマイナーなコード変更です。 – holtmann

+0

あなたの答えをありがとう..そのうまくいく:) – Aravindhan

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

可能であればので、それはメモリの消費量を減らすのに役立ちかもしれ全体ではなく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]; 
+0

時間を短縮できます。このアプリはhttp://itunes.apple.com/us/app/lock-photo-video-note-audio/id448033053?mt=8非常にすばやくインポートされていました。 – Aravindhan

+0

シミュレータではなくデバイスで写真を読み込むためにコードを実行するのに何時間かかりますか?あなたは写真の解像度のような詳細を追加してくださいできますか? –

+0

1 MBイメージを保存するのに6秒かかります。私はiPod2を使用しています.. – Aravindhan

関連する問題