Как правильно импортировать и сохранять фотографии из альбома 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];
}
Работает нормально, но когда я пытаюсь импортировать изображения с более высоким разрешением, это занимает больше времени. Как правильно импортировать с наименьшим количеством времени? Кстати: когда я конвертирую image
в NSData
,
2 ответа
Опасно использовать fullResolutionImage для этой задачи по нескольким причинам. Некоторые замечания:
- Для больших изображений могут возникнуть проблемы с памятью. при использовании метода fullResolutionImage. Обратите внимание, что Фотобиблиотека (по крайней мере, на iPad) также может содержать RAW-изображения.
- Производительность ниже оптимальной, так как внутренне из файла изображения ImageIO сначала создает CGImageRef, который затем преобразуется в JPEG. Это требует времени.
- AssetLibrary также может содержать видео. В таком случае fullResolutionImage возвращает только PreviewImage видео, но не фактическое видео.
- Нет проблем хранить реальные объекты-активы, так как они малы в памяти.
Гораздо лучшим подходом для записи изображений в каталог документов было бы использование метода 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];
}
}
Я использовал 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];