这可能是一个愚蠢的问题,但很抱歉,因为我是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)];
}
答案 0 :(得分:3)
您正在将所有图像加载到视图中,但在任何给定时间只显示少数图像。根据图像的数量,这可能占用大量内存。
您可以考虑以下方法:
生成所有图像并将其写入本地存储,将图像的文件URL存储在数组中。
现在,对于滚动视图,只需在需要时添加图像,滚动到下一个图像。添加图像时,从磁盘加载图像并将其添加到视图中。看看这个示例代码的水平无限滚动视图:https://code.google.com/p/iphone-infinite-horizontal-scroller。
你也可以使用普通的UITableView和自定义单元格,只显示图像。
答案 1 :(得分:1)
我发现了自己的错误。我正在为我的40 * 40图像视图分配原始/完整图像。这是产生记忆警告。使用以下代码生成图像时解决所需的图像尺寸。
self.generator.maximumSize = CGSizeMake(40, 40);