Как правильно импортировать и сохранять фотографии из альбома iPhone? - PullRequest
3 голосов
/ 02 апреля 2012

Я импортирую фотографии из альбома 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.

Ответы [ 2 ]

23 голосов
/ 08 апреля 2012

Опасно использовать fullResolutionImage для этой задачи по нескольким причинам. Некоторые замечания:

  1. Для больших изображений могут возникнуть проблемы с памятью. при использовании метода fullResolutionImage. Обратите внимание, что Фотобиблиотека (по крайней мере, на iPad) также может содержать RAW-изображения.
  2. Производительность ниже оптимальной, поскольку внутренне из файла изображения ImageIO сначала создает CGImageRef, который затем преобразуется в JPEG. Это требует времени.
  3. AssetLibrary также может содержать видео. В таком случае fullResolutionImage возвращает только предварительный просмотр видео, но не фактическое видео.
  4. Нет проблем в сохранении реальных объектов-активов, так как они малы в памяти.

Гораздо лучшим подходом для записи изображений в каталог документов было бы использование метода getBytes объекта ALAssetsRepresentation. Это должно быть намного быстрее и эффективнее с точки зрения памяти. Он также предоставляет исходный файл изображения (включая метаданные), а также работает с видео.

Ваш пример кода, переписанный тогда, будет выглядеть так:

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

    }
}
5 голосов
/ 02 апреля 2012

Я использовал ELCImagePicker и столкнулся с той же проблемой при импорте нескольких фотографий одновременно из библиотеки фотографий с использованием ассетов. Мы не можем сократить время, необходимое для импорта, но проблема сбоя будет решена.

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 и одновременно создавать ALAsset из URL, что может помочь уменьшить потребление памяти. В таком случае вам нужно будет использовать блоки как

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];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...