【问题标题】:Copy UImages from photo library to another directory将 UImages 从照片库复制到另一个目录
【发布时间】:2014-04-23 18:44:52
【问题描述】:

我想将照片库中的图片复制到我的应用程序的另一个目录中,这里的附加代码一切正常,但是当我尝试复制大量图像时,应用程序立即崩溃我认为这是因为附加的代码是用一个线程完成的,所以每个图像都需要它的线程,所以如果有太多图片无法复制应用程序崩溃。 我在这里需要相同的代码,但不在线程中,这意味着应用程序应该被阻止,直到图像被复制到另一个目录,如果有人有另一个好主意,我将不胜感激。 for 循环正在保存每个图像。

for (int i = 0; i< countt ;i++) {

        NSURL *referenceURL = [self.ToSaveArray objectAtIndex:i];
        ALAssetsLibrary *assetLibrary=[[ALAssetsLibrary alloc] init];
        [assetLibrary assetForURL:referenceURL resultBlock:^(ALAsset *asset) {
            ALAssetRepresentation *rep = [asset defaultRepresentation];
            Byte *buffer = (Byte*)malloc(rep.size);
            NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
            NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];//this is NSData may be what you want
            NSLog(@"length %d",[data length]);
            UIImage *image= [UIImage imageWithData:data];
            [self SavePhoto:image withnum:i];
            //[data writeToFile:photoFile atomically:YES];//you can save image later
        } failureBlock:^(NSError *err) {
            NSLog(@"Error: %@",[err localizedDescription]);
        }];

    }

保存照片代码:

-(bool)SavePhoto:(UIImage *) imageTosave withnum:(int)num{


    float goodScal = imageTosave.size.width/75.0;

    CGSize newSize =CGSizeMake(imageTosave.size.width/goodScal, imageTosave.size.height/goodScal);
    UIImage* smallImage = [self resizeImage:imageTosave toSize:newSize];
    NSData *JpgDataS = UIImageJPEGRepresentation(smallImage, 1);
    NSData *JpgData = UIImageJPEGRepresentation(imageTosave, 1);



    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
    NSString *dataPath = [documentsPath stringByAppendingPathComponent:@"/CapturesPhotos"];
    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init]autorelease];
    NSTimeZone *zone = [NSTimeZone localTimeZone];
    [formatter setTimeZone:zone];
    [formatter setDateFormat:@"yyyyMMddHHmmss"];
    NSString* Bnamee = [NSString stringWithFormat:@"/IMG%d_%@B.jpg",num,[formatter stringFromDate:date]];
    NSString* Snamee = [NSString stringWithFormat:@"/IMG%d_%@S.jpg",num,[formatter stringFromDate:date]];
    //NSString *filePath = [dataPath stringByAppendingPathComponent:namee]; //Add the file name
    NSString *filePath = [dataPath stringByAppendingPathComponent:Bnamee]; //Add the file name
    NSString *filePathS = [dataPath stringByAppendingPathComponent:Snamee]; //Add the file name
    [JpgData writeToFile:filePath atomically:YES]; //Write the file
    [JpgDataS writeToFile:filePathS atomically:YES]; //Write the file
    //[pngData writeToFile:filePath atomically:YES]; //Write the file
    return true;
}

提前致谢

【问题讨论】:

  • SavePhoto的实现呢?
  • 我已经用代码编辑了我的问题。
  • 应用程序终止时日志中显示了什么?
  • 有关确定多个块何时完成执行的方法,请参阅我的答案here
  • 我得到:收到内存警告!

标签: ios objective-c nsdata


【解决方案1】:

似乎一开始很多异步操作会耗尽您的内存,请尝试使用串行队列序列化其中昂贵的(内存方面)部分:

dispatch_queue_t    queue = dispatch_queue_create("save", DISPATCH_QUEUE_SERIAL);

// Move this out of loop for efficiency
ALAssetsLibrary*    assetLibrary=[[ALAssetsLibrary alloc] init];

for (int i = 0; i< ToSaveArray.count ;i++) {

    NSURL *referenceURL = [ToSaveArray objectAtIndex:i];
    [assetLibrary assetForURL:referenceURL resultBlock:^(ALAsset *asset) {
        ALAssetRepresentation *rep = [asset defaultRepresentation];
        dispatch_async(queue, ^{

            Byte *buffer = (Byte*)malloc(rep.size);
            NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
            NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];//this is NSData may be what you want
            NSLog(@"length %d",[data length]);
            UIImage *image= [UIImage imageWithData:data];
            [self SavePhoto:image withnum:i];
        });
        //[data writeToFile:photoFile atomically:YES];//you can save image later
    } failureBlock:^(NSError *err) {
        NSLog(@"Error: %@",[err localizedDescription]);
    }];

}

dispatch_async(queue, ^{
    // Some code to execute when all the saving is done
});

我不确定这是否真的能解决问题,但值得一试:)

另外,关于如何更干净地获取 UIImage 的更正版本(来自 this answer):

UIImage*            image = [UIImage imageWithCGImage:[rep fullResolutionImage]
                                                scale:[rep scale]
                                          orientation:UIImageOrientationUp];

尽管在您的情况下,继续获取图像数据本身可能会更好,但只需将其传递到您的保存例程中,这样您就可以节省转换 jpg->image->jpg 的费用。您仍然需要创建图像,以便还可以保存缩略图,但这是另一回事。

【讨论】:

  • 不,那不正确你的答案没有解决问题,线程正在同时工作这就是问题,你提供的答案也会翻转图像!
  • 注意:freeWhenDone:YES 表示缓冲区在使用完毕后被释放。
  • freeWhenDone:YES 请注意这个!!
  • 从技术上讲,我认为我的代码取消了它。 iOS 有点作弊,实际上并没有从相机中旋转照片,而是改变了 jpg 图像方向,CGImage 丢失了 jpeg 图像方向信息,并且图像取消翻转。
猜你喜欢
  • 2012-02-15
  • 2017-11-18
  • 2014-07-18
  • 2011-12-28
  • 2013-06-01
  • 2020-06-22
  • 2014-08-12
  • 2013-10-24
相关资源
最近更新 更多