照相机和图片库(2)
来源:互联网 发布:mcgs组态软件视频教程 编辑:程序博客网 时间:2024/05/01 22:02
6.从多媒体库中获得图片和视频
6.1. 问题
你希望用户可以从多媒体库中选择一个图片或者视频以在程序中使用。
6.2. 方案通过使用 UIImagePickerController 这个类的来实现相关的功能,把源类型设置为 UIImagePickerControllerSourceTypePhotoLibrary,已经媒体类型选择 kUTTypeImage 或 kUTTypeMovie(或都选)。代码如下。
- (BOOL)isPhotoLibraryAvailable{
return [UIImagePickerControllerisSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary];
}
- (BOOL)canUserPickVideoFromPhotoLibarary{
NSArray *array = [UIImagePickerControlleravailableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
__block BOOL result =NO;
[array enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop) {
NSString *mediaType = (NSString *)obj;
if ([mediaType isEqualToString:(__bridge NSString *)kUTTypeMovie]) {
result = YES;
*stop = YES;
}
}];
return result;
}
- (BOOL) canUserPickPhotosFromPhotoLibrary{
//这里没有将两个方法合并
NSArray *array = [UIImagePickerControlleravailableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
__block BOOL result =NO;
[array enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop) {
NSString *mediaType = (NSString *)obj;
if ([mediaType isEqualToString:(__bridge NSString *)kUTTypeImage]) {
result = YES;
*stop = YES;
}
}];
return result;
}
- (void)viewDidLoad {
[superviewDidLoad];
if ([selfisPhotoLibraryAvailable]) {
controller = [[UIImagePickerControlleralloc]init];
controller.sourceType =UIImagePickerControllerSourceTypePhotoLibrary;
NSMutableArray *mediaTypes = [[NSMutableArrayalloc]init];
if ([selfcanUserPickPhotosFromPhotoLibrary]) {
[mediaTypes addObject:(__bridgeNSString *)kUTTypeImage];
}
if ([selfcanUserPickVideoFromPhotoLibarary]) {
[mediaTypes addObject:(__bridgeNSString *)kUTTypeVideo];
}
controller.mediaTypes = mediaTypes;
controller.delegate =self;
UIButton *button = [UIButtonbuttonWithType:UIButtonTypeSystem];
[button setTitle:@"选择资源"forState:UIControlStateNormal];
[button addTarget:selfaction:@selector(pushUIImagePickerController)forControlEvents:UIControlEventTouchUpInside];
}
}
- (void)pushUIImagePickerController{
[selfpresentViewController:controlleranimated:YEScompletion:nil];
}
记住,如果把 UIImagePickerController 的 mediaTypes 属性设置为 nil 或者一个空的数组,则会引发一个运行时错误。
当用户完成图片选择之后,通过 UIImagePickerControllerDelegate 协议你将收到消息来处理得到的图片或视频,参考上面第二节提到的.
你希望从 Photo 库中直接获取图片或视频,而不通过内置的 GUI 组件。
7.2. 方案
1、分配和初始化一个 ALAssetsLibrary 类型的对象。
3、使用每个群组对象的 enumerateAssetsUsingBlock:实例方法来枚举出每个群组中的资源。这个方法将接收一个 block 作为参数,用来获取单个资源。传入的这个 block 必须接收 3 个参数,并且第一个参数必须是 ALAsset 类型。
5、调用 ALAsset 的 defaultRepresentation 实例方法来获取到它的表示对象:类型为 ALAssetRepresentation。每个 asset 都可以有多个表示对象。例如,一个图片默认情况下可以 是 PNG,不过也可以用 JPEG 来表示。使用 ALAsset 的 defaultRepresentation 方法可以获取 到一个 ALAssetRepresentation 对象。
6、使用 size 和 asset 的 getBytes:fromOffset:length:error:实例方法可以加载 asset 的表示 数据。然后你可以将读取到的 bytes 写入 NSData 对象中,或者做任意你想做的操作。另 外,针对图片,还可以使用每个 ALAssetRepresentation 的 fullResolutionImage, fullScreen
Image 和 CGImageWithOptions:实例方法来获取 CGImageRef 类型图片。然后使用 UIImage 的 imageWithCGImage:类方法来从 CGImageRef 中构造一个 UIImage。
将 ALAssetsGroupAll 传入到 Assets 库实例方法 enumerateGroupsWithTypes:usingBlock:failureBlock:的 enumerateGroupsWithTypes 参数中,就可以获得所有类型的所有的 assets。下面列出来的值当做参数传入到上面的方法中,以枚举出 asset 的不同群组:
ALAssetsGroupAlbum
这个群组代表了通过 iTunes 存储到 iOS 设备上的相册。
ALAssetsGroupFaces
这个群组代表的相册是通过 iTunes 存储到 iOS 设备上的 face assets。
ALAssetsGroupSavedPhotos
这个群组代表了存储到 Photo 库中的图片。通过 Photo 程序也可以访问到。
ALAssetsGroupAll
在 Assets 库中所有可用的群组。
a.
下面我们来写一个简单的示例,用来获取 Assets 库中第一个图片的数据,并创建一个 UIImageView,然后将其添加到当前 view control 的 view 上。这样,我们就可以学习到如何 使用 asset 的 representation 来读取其中的内容。现在我们需要做的就是当这个 viewcontroller 加载的时候,我们需要初始化一个 AssetSLibrary 的对象。然后开始枚举这个 asset 库,直到找到第一个图片。这时,我们将使 用 asset 的 representation 来将图片显示在 imageview 上:
- (void)getOneImageFromAsset{
self.assetsLibrary = [[ALAssetsLibraryalloc]init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
[self.assetsLibraryenumerateGroupsWithTypes:ALAssetsGroupAllusingBlock:^(ALAssetsGroup *group,BOOL *stop) {
[group enumerateAssetsUsingBlock:^(ALAsset *result,NSUInteger index,BOOL *stop) {
__block BOOL foundThePhoto = NO;
if (foundThePhoto) {
*stop = YES;
}
//Get the asset type
NSString *assetType = [result valueForProperty:ALAssetPropertyType];
if ([assetType isEqualToString:ALAssetTypePhoto]) {
NSLog(@"This is a photo asset");
foundThePhoto = YES;
*stop = YES;
//get the asset's representation object
ALAssetRepresentation *assetRepresentation = [resultdefaultRepresentation];
/* We need the scale and orientation to be able to construct a properly oriented and scaled UIImage out of the representation object */
CGFloat imageScale = [assetRepresentationscale];
UIImageOrientation imageOrientation = (UIImageOrientation)[assetRepresentationorientation];
dispatch_async(dispatch_get_main_queue(), ^{
CGImageRef imageReference = [assetRepresentationfullResolutionImage];
//Construct the image now
UIImage *image = [[UIImagealloc]initWithCGImage:imageReferencescale:imageScaleorientation:imageOrientation];
if (image != nil) {
self.imageView = [[UIImageViewalloc]initWithFrame:self.view.bounds];
self.imageView.contentMode =UIViewContentModeScaleAspectFit;
self.imageView.image = image;
[self.viewaddSubview:self.imageView];
}
});
}
}];
} failureBlock:^(NSError *error){
NSLog(@"Failed to enumerate the asset groups.");
}];
});
}
b.
针对视频文件,处理过程有一些不同,因为 ALAssetRepresentation 类没有任何方法可以 返回关于视频文件的对象。因此,我们需要将视频文件内容读取到一个 buffer 中,然后将其 保存到 Documents 文件目录中。当然,这也取决于你的程序。在这里的示例代码中,我将找 出第一个视频文件,然后将其存储到程序的 Documents 目录下,文件命名为 Temp.MOV:
- (void)getOneVideoFromAsset{
self.assetsLibrary = [[ALAssetsLibraryalloc]init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
[self.assetsLibraryenumerateGroupsWithTypes:ALAssetsGroupAllusingBlock:^(ALAssetsGroup *group,BOOL *stop) {
__block BOOL foundTheVideo = NO;
[group enumerateAssetsUsingBlock:^(ALAsset *result,NSUInteger index,BOOL *stop) {
//得到asset的类型
NSString *assetType = [result valueForProperty:ALAssetPropertyType];
if ([assetType isEqualToString:ALAssetTypeVideo]) {
NSLog(@"This is a video asset");
foundTheVideo = YES;
*stop = YES;
//如果是video类型的,并且得到asset的representation
ALAssetRepresentation *assetRepresentation = [resultdefaultRepresentation];
const NSUInteger BufferSize = 1024;
uint8_t buffer[BufferSize];
NSUInteger bytesRead = 0;
long long currentOffset = 0;
NSError *readingError = nil;
//选择存储视频的路径
NSArray *documents =NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory,NSUserDomainMask,YES);
//创建存储视频的文件
NSString *videoPath = [[documentsobjectAtIndex:0]stringByAppendingPathComponent:@"Temp.MOV"];
NSFileManager *fileManager = [[NSFileManageralloc]init];
//如果不存在,创建该文件
if ([fileManager fileExistsAtPath:videoPath] == NO) {
[fileManager createFileAtPath:videoPathcontents:nilattributes:nil];
}
//用文件句柄将media assets的数据写入磁盘
NSFileHandle *fileHandle = [NSFileHandlefileHandleForWritingAtPath:videoPath];
do {
/* Read as many bytes as we can put in the buffer */
bytesRead = [assetRepresentation getBytes:(uint8_t *)&buffer
fromOffset:currentOffset
length:BufferSize
error:&readingError];
/* If we couldn't read anything, we will exit this loop */
if (bytesRead == 0) {
break;
}
//Keep the offset up to date
currentOffset += bytesRead;
//Put the buffer into an NSData
NSData *readData = [[NSDataalloc]initWithBytes:(constvoid *)buffer length:bytesRead];
//write the data to file
[fileHandle writeData:readData];
} while (bytesRead > 0);
NSLog(@"Finished reading and storing the video in the documents folder");
}
}];
if (foundTheVideo) {
*stop = YES;
}
} failureBlock:^(NSError *error) {
NSLog(@"Failed to enumerate the asset groups.");
}];
});
}
1.获取第一个视频的默认 representation
2.在程序的 Documents 目录下创建一个 Temp.MOV 文件,用来存储视频内容。
4.在将数据读取到 buffer 中后,使用 NSData 的初始化方法 initWithBytes:length:将数据封装为 NSData 对象。然后使用 NSFileHandle 的 writeData:实例方法将这些数据写入 到之前创建的文件中。
你希望用户可以在你的程序中对视频直接进行编辑.
8.2. 方案通过使用 UIVideoEditorController 这个类。在这里给出的实例中,我们将会利用这个类 和 imagePickercontroleller 来共同解决这个问题,我们会先让用户从多媒体库中选择一个视频 文件,然后我们把这个文件加载在 UIVideoEditorController 中让用户来编辑。
8.3. 讨论iOS SDK 的 UIVideoEditorController 这个类可以为用户提供展示编辑视频的相关 UI 界面。你所需要做的就是只需要提供视频的 URL 连接地址。你不应该在这个 View 上面添加其他的什么视图,并且你不能修改这个视图。
要遵守UIVideoEditorControllerDelegate协议
#pragma mark - video editor delegate
- (void)videoEditorController:(UIVideoEditorController *)editor didSaveEditedVideoToPath:(NSString *)editedVideoPath{
NSLog(@"The video editor finished saving video");
NSLog(@"The edited video path is at = %@", editedVideoPath);
[editor dismissViewControllerAnimated:YEScompletion:nil];
}
- (void)videoEditorController:(UIVideoEditorController *)editor didFailWithError:(NSError *)error{
NSLog(@"Video editor error occurred = %@", error);
[editor dismissViewControllerAnimated:YEScompletion:nil];
}
- (void)videoEditorControllerDidCancel:(UIVideoEditorController *)editor{
NSLog(@"The video editor was cancelled");
[editor dismissViewControllerAnimated:YEScompletion:nil];
}
//当我们的视图加载时,我们需要给用户显示一个 video选取器,这样用户才能从媒体库中选择一个 video。然后才让用户进行编辑这个 video:
- (BOOL)cameraSupportsMedia:(NSString *)paramMediaType sourceType:(UIImagePickerControllerSourceType)paramSourceType{
__block BOOL result =NO;
if ([paramMediaType length] == 0) {
NSLog(@"Media type is empty");
return NO;
}
NSArray *availableMediaTypes = [UIImagePickerControlleravailableMediaTypesForSourceType:paramSourceType];
[availableMediaTypes enumerateObjectsUsingBlock:^(id obj,NSUInteger idx, BOOL *stop) {
NSString *mediaType = (NSString *)obj;
if ([mediaType isEqualToString:paramMediaType]) {
result = YES;
*stop = YES;
}
}];
return result;
}
- (BOOL)canUserPickVideosFromPhotoLibrary{
return [selfcameraSupportsMedia:(__bridgeNSString *)kUTTypeMoviesourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}
- (void)xianshi{
if ([selfisPhotoLibraryAvailable] && [selfcanUserPickVideosFromPhotoLibrary]) {
UIImagePickerController *imagePicker = [[UIImagePickerControlleralloc]init];
imagePicker.sourceType =UIImagePickerControllerSourceTypePhotoLibrary;
NSArray *mediaType = [[NSArrayalloc]initWithObjects:(__bridgeNSString *)kUTTypeMovie,nil];
imagePicker.mediaTypes = mediaType;
imagePicker.delegate = self;
[selfpresentViewController:imagePicker animated:YEScompletion:nil];
}
}
//现在当用户完成 video 选取时,我们需要知道,所以我们来处理一下 image picker协议 的各种 delegate 方法吧:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSLog(@"Picker returned successfully");
NSString *mediaType = [infoobjectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:(__bridge NSString *)kUTTypeMovie]) {
self.videoURLToEdit = [infoobjectForKey:UIImagePickerControllerMediaURL];
}
[picker dismissViewControllerAnimated:YEScompletion:nil];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
NSLog(@"Picker was cancelled");
self.videoURLToEdit =nil;
[picker dismissViewControllerAnimated:YEScompletion:nil];
}
//当用户选择好视频之后,我们就可以显示 video editor了:
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSString *videoPath = [self.videoURLToEditpath];
if ([UIVideoEditorControllercanEditVideoAtPath:videoPath]) {
UIVideoEditorController *videoEditor = [[UIVideoEditorControlleralloc]init];
videoEditor.delegate = self;
videoEditor.videoPath = videoPath;
[selfpresentViewController:videoEditor animated:YEScompletion:nil];
self.videoURLToEdit =nil;
}else{
NSLog(@"Cannot edit the video at this path");
}
}
- 照相机和图片库(2)
- 照相机和图片库(1)
- IOS 使用照相机和图片库
- 上传头像(照相机、图片库)
- Swift学习笔记(4)使用UIImagePickerController实现从设备图片库和照相机获取图片
- 调用照相机与图片库并实现保存图片到图片库
- 使用 Lightbox 2 和 JavaScript 构建出色的图片库
- 使用 Lightbox 2 和 JavaScript 构建出色的图片库
- 图片库
- 图片库
- 照片库和照相机
- 访问照相机和照片
- 四.照相机和摄像头
- 系统相册和照相机
- 照相机和录制
- 照相机2-----调用函数
- Android_照相机(2)
- 照相机
- 多进程和多线程
- 反向输出一个链表(链表逆置)
- C++复习学习提纲
- 推荐:Mr. Process的一生-Linux内核的社会视角 (1)调度
- linux system common command
- 照相机和图片库(2)
- 两个栈实现队列
- mongoDB使用
- 关于ngx的一些常用函数和结构体
- CentOS下/etc/sysconfig/下找不到iptables文件
- Swift中出现“no such module cocoa”的错误
- centos6.5下如何安装SVN同时配置多个版本库
- CAShapeLayer 跟 UIBezierPath 进行动画绘图
- C++函数返回局部变量指针的问题