0

这可能是一个愚蠢的问题,但很抱歉,因为我是 iPhone 的新手。

我想为每一帧视频生成图像并将其显示在 UIImageView 内的 UIScrollview 中。

当我尝试这样做时,我收到内存警告并且我的应用程序崩溃。

下面是我的代码。

- (IBAction)onCameraButtonPressed:(id)sender
{
    // Initialize UIImagePickerController to select a movie from the camera roll.
    UIImagePickerController *videoPicker = [[UIImagePickerController alloc] init];
    videoPicker.delegate = self;
    videoPicker.modalPresentationStyle = UIModalPresentationCurrentContext;
    videoPicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
    videoPicker.mediaTypes = @[(NSString*)kUTTypeMovie];
    [self presentViewController:videoPicker animated:YES completion:nil];
}

#pragma mark Image Picker Controller Delegate

- (void)imagePickerController:(UIImagePickerController *)picker     didFinishPickingMediaWithInfo:(NSDictionary *)info
{
   [self dismissViewControllerAnimated:YES completion:nil];
    currentVideoURL = info[UIImagePickerControllerReferenceURL];
    //Video URL = assets-library://asset/asset.MOV?id=D0A4A3EE-C5F3-49C8-9E45-ADF775B9FA8C&ext=MOV
    //NSLog(@"Video URL = %@",currentVideoURL);
    //imageIndex = 0;
    for (UIImageView *subView in thumbnailScrollView.subviews)
    {
        [subView removeFromSuperview];
    }
    [self generateThumbnailsFromVideoURL:currentVideoURL];
    //[self generateAVAssetThumbnails:currentVideoURL];
    //[self appleImageGenerator:currentVideoURL];
    }

- (void)generateThumbnailsFromVideoURL:(NSURL *)videoURL
{
    AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:videoURL options:nil];
    //NSLog(@"Video duration %lld seconds",asset.duration.value/asset.duration.timescale);
    int videoDuration = (asset.duration.value/asset.duration.timescale);

    if (cmTimeArray.count>0) {
        [cmTimeArray removeAllObjects];
    }
    for (int i = 0; i<videoDuration; i++)
    {
        int64_t tempInt = i;
        CMTime tempCMTime = CMTimeMake(tempInt,1);
        int32_t interval = 15;
        for (int j = 1; j<16; j++)
        {
            CMTime newCMtime = CMTimeMake(j,interval);
            CMTime addition = CMTimeAdd(tempCMTime, newCMtime);
            [cmTimeArray addObject:[NSValue valueWithCMTime:addition]];
        }
    }
    //NSLog(@"Array of time %@ count = %d",cmTimeArray, cmTimeArray.count);
    /*for(int t=0;t < asset.duration.value;t++) {
        CMTime thumbTime = CMTimeMake(t,asset.duration.timescale);
        NSValue *v=[NSValue valueWithCMTime:thumbTime];
        [cmTimeArray addObject:v];
    }
    NSLog(@"Array of time %@ count = %d",cmTimeArray, cmTimeArray.count);*/
    __block int i = 0;
    //__block UIImage *currentImage = nil;
    AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
        if (result == AVAssetImageGeneratorSucceeded) {
            // currentImage = [UIImage imageWithCGImage:im];
            //[framesArray addObject:[UIImage imageWithCGImage:im]];
            [self performSelectorOnMainThread:@selector(insertImageToScrollView:) withObject:[UIImage imageWithCGImage:im] waitUntilDone:NO];
        }
        else
            NSLog(@"Ouch: %@", error.description);
        i++;
        imageIndex = i;
        if(i == cmTimeArray.count) {
            //[self performSelectorOnMainThread:@selector(insertImageToScrollView:) withObject:framesArray waitUntilDone:YES];
        }
    };

    // Launching the process...
    self.generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    self.generator.appliesPreferredTrackTransform=TRUE;
    self.generator.requestedTimeToleranceBefore = kCMTimeZero;
    self.generator.requestedTimeToleranceAfter = kCMTimeZero;
    self.generator.maximumSize = CGSizeMake(40, 40);
    [self.generator generateCGImagesAsynchronouslyForTimes:cmTimeArray completionHandler:handler];
    }

-(void)insertImageToScrollView:(UIImage *)image
{
    int xPosition = (5*imageIndex)+(WIDTH*imageIndex)+OFFSET;
    UIImageView *currentImageView = [[UIImageView alloc]initWithFrame:CGRectMake(xPosition, 5, WIDTH, WIDTH)];
    currentImageView.tag = imageIndex+10;
    currentImageView.image = image;
    [thumbnailScrollView addSubview:currentImageView];
    [thumbnailScrollView setContentSize:CGSizeMake(xPosition+WIDTH+5,thumbnailScrollView.frame.size.height)];
}
4

2 回答 2

3

您正在将所有图像加载到视图中,但在任何给定时间仅显示少数图像。根据图像的数量,这可能会占用大量内存。

您可以考虑以下方法:

生成所有图像并将它们写入本地存储,将图像的文件 URL 存储在一个数组中。

现在对于您的滚动视图,仅在滚动到下一个时添加所需的图像。添加图像时,您从磁盘加载它们并将它们添加到您的视图中。看看这个水平无限滚动视图的示例代码:https ://code.google.com/p/iphone-infinite-horizo​​ntal-scroller 。

您还可以使用带有自定义单元格的普通 UITableView,仅显示图像。

于 2013-04-19T09:30:51.147 回答
1

我发现了我的错误。我将原始/完整图像分配给我的 40*40 图像视图。那是产生内存警告。解决在使用以下代码生成图像时提供所需的图像大小。

self.generator.maximumSize = CGSizeMake(40, 40);
于 2013-04-23T10:37:41.687 回答