2012-04-02 4 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]; 
} 

잘 작동하지만 더 높은 해상도의 이미지를 가져 오려고하면 더 많은 시간이 걸립니다. 최소한의 시간으로 가져 오는 올바른 방법은 무엇입니까? BTW : imageNSData으로 변환하면 더 많은 시간이 걸립니다.

+0

내가이 같은 문제가 없었다하지만 난 데이터베이스에 자산 URL을 저장하여 그것을 해결하고 난 문서 디렉토리에 이미지를 저장해야 할 때 난으로 자산 하나를 얻을 하나는 문서 디렉토리에 이미지를 저장합니다. 한 가지 이유는 배열에 자산을 저장하고 자산 URL을 저장하는 것이고 메모리 문제를 줄이는 자동 릴리스 풀의 루프에 대해 하나 더 실행하는 것입니다. – Leena

답변

23

그것은 여러 가지 이유로이 작업에 대한 fullResolutionImage를 사용하는 위험으로 블록을 사용해야합니다. 일부 설명 :

  1. 큰 이미지의 경우 메모리 문제가 발생할 수 있습니다. fullResolutionImage 메소드를 사용할 때. Photo-Library (적어도 iPad에서는)에도 RAW 이미지가 포함될 수 있습니다.
  2. 성능이 이미지 파일 내부적으로 최적이 아닙니다. ImageIO는 먼저 JPEG로 변환 된 CGImageRef를 먼저 만듭니다. 이것은 시간이 걸립니다.
  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]; 

    } 
} 
+0

감사합니다. 매우 멋지게 작동합니다.하지만 어떻게 축소판 이미지와 전체 화면 이미지를 문서 폴더에 복사 할 수 있습니까?또는 문서 폴더의 ALAssetsRepresentation에서 이러한 이미지를 가져 오는 다른 방법이 있습니까? – Aravindhan

+1

fullScreenImage 및 축소판을 읽는 것을 포함하도록 소스 코드를 수정했습니다. 이 두 이미지의 경우 이전의 접근 방식을 사용할 수 있습니다. 크기가 제한되어 있고 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]; 
    } 
} 

가능한 시도가 assetArray 대신 전체 ALAsset 객체 만 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

관련 문제