Пример #1
0
        public static async Task <string> GetIOSFilePath(this PHAsset photo)
        {
            var tcs = new TaskCompletionSource <NSUrl>();

            if (photo.MediaType == PHAssetMediaType.Image)
            {
                var options = new PHContentEditingInputRequestOptions();
                options.CanHandleAdjustmentData = _ => true;
                photo.RequestContentEditingInput(options, (contentEditingInput, requestStatusInfo) => {
                    tcs.SetResult(contentEditingInput.FullSizeImageUrl);
                });
            }
            else if (photo.MediaType == PHAssetMediaType.Video)
            {
                var options = new PHVideoRequestOptions();
                options.Version = PHVideoRequestOptionsVersion.Original;
                PHImageManager.DefaultManager.RequestAvAsset(photo, options, (asset, audioMix, info) => {
                    if (asset is AVUrlAsset urlAsset)
                    {
                        tcs.SetResult(urlAsset.Url);
                        return;
                    }
                    tcs.SetException(new InvalidDataException("RequestAvAsset didn't get AVUrlAsset"));
                });
            }
            var origfilepath = await tcs.Task.ConfigureAwait(false);

            return(origfilepath.Path);
        }
Пример #2
0
        private static string StorePickedVideo(PHAsset asset)
        {
            var tcs          = new TaskCompletionSource <string>();
            var task         = tcs.Task;
            var imageManager = PHImageManager.DefaultManager;

            using (var requestOptions = new PHVideoRequestOptions
            {
                NetworkAccessAllowed = true,
                DeliveryMode = PHVideoRequestOptionsDeliveryMode.MediumQualityFormat
            })
            {
                imageManager.RequestExportSession(asset, requestOptions, AVAssetExportSession.PresetPassthrough, (exportSession, info) =>
                {
                    Task.Factory.StartNew(async() =>
                    {
                        var targetDir = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                        var error     = (NSError)info["PHImageErrorKey"];
                        if (error != null)
                        {
                            var description = error.LocalizedDescription;
                            var reason      = error.UserInfo.ValueForKey((NSString)"NSUnderlyingError");
                            tcs.SetException(new FileLoadException($"{description}. {reason}"));
                            return;
                        }

                        var resources   = PHAssetResource.GetAssetResources(asset);
                        var orgFilename = resources[0].OriginalFilename;
                        var path        = Path.Combine(targetDir, orgFilename);
                        File.Delete(path);
                        exportSession.OutputUrl      = new NSUrl($"file://{path}");
                        exportSession.OutputFileType = AVFileType.Mpeg4;
                        await exportSession.ExportTaskAsync();
                        if (exportSession.Status == AVAssetExportSessionStatus.Completed)
                        {
                            tcs.TrySetResult(path);
                        }
                        else
                        {
                            tcs.SetException(new Exception(exportSession.Error.Description));
                        }
                    });
                });
            }

            return(task.Result);
        }
Пример #3
0
        private void HandleImage(IEnumerable <PHObject> images)
        {
            foreach (PHAsset image in images)
            {
                if (image.MediaType == PHAssetMediaType.Image)
                {
                    PHImageRequestOptions options = new PHImageRequestOptions()
                    {
                        NetworkAccessAllowed = false,
                        ResizeMode           = PHImageRequestOptionsResizeMode.Exact,
                        Version = PHImageRequestOptionsVersion.Original
                    };

                    PHImageManager.DefaultManager.RequestImageData(image, options, async(d, t, o, i) =>
                    {
                        string path     = ((NSUrl)i["PHImageFileURLKey"])?.Path;
                        string mimeType = UTType.GetPreferredTag(t, UTType.TagClassMIMEType);

                        await _probe.CreateAndStoreDatumAsync(path, mimeType, (DateTime)image.CreationDate);
                    });
                }
                else if (image.MediaType == PHAssetMediaType.Video)
                {
                    PHVideoRequestOptions options = new PHVideoRequestOptions()
                    {
                        NetworkAccessAllowed = false,
                        Version = PHVideoRequestOptionsVersion.Original
                    };

                    PHImageManager.DefaultManager.RequestAvAsset(image, options, async(a, _, i) =>
                    {
                        if (a is AVUrlAsset urlAsset)
                        {
                            string path                  = urlAsset.Url.Path;
                            string extension             = urlAsset.Url.PathExtension;
                            string uniformTypeIdentifier = UTType.CreatePreferredIdentifier(UTType.TagClassFilenameExtension, extension, null);
                            string mimeType              = UTType.GetPreferredTag(uniformTypeIdentifier, UTType.TagClassMIMEType);

                            await _probe.CreateAndStoreDatumAsync(path, mimeType, (DateTime)image.CreationDate);
                        }
                    });
                }
            }
        }
Пример #4
0
        private void ChangeVideo(PHAsset asset, PHImageManager imageManager,
                                 PHVideoRequestOptions options)
        {
            DispatchQueue.DefaultGlobalQueue.DispatchAsync(() =>
                                                           imageManager?.RequestAvAsset(asset, options,
                                                                                        (ass, mix, info) =>
                                                                                        DispatchQueue.MainQueue.DispatchAsync(() =>
            {
                CurrentMediaType = MediaType.Video;
                _albumView.ImageCropView.Hidden = true;
                _albumView.MovieView.Hidden     = false;

                var urlAsset = ass as AVUrlAsset;
                if (urlAsset == null)
                {
                    return;
                }
                _albumView.MoviePlayerController.ContentUrl = urlAsset.Url;
                _albumView.MoviePlayerController.PrepareToPlay();
            })));
        }
Пример #5
0
        async void FinishedPickingAssets(object sender, MultiAssetEventArgs args)
        {
            IList <MediaFile> results = new List <MediaFile>();
            TaskCompletionSource <IList <MediaFile> > tcs = new TaskCompletionSource <IList <MediaFile> >();

            var options = new Photos.PHImageRequestOptions()
            {
                NetworkAccessAllowed = true
            };

            options.Synchronous  = false;
            options.ResizeMode   = PHImageRequestOptionsResizeMode.Fast;
            options.DeliveryMode = PHImageRequestOptionsDeliveryMode.HighQualityFormat;
            bool completed = false;

            for (var i = 0; i < args.Assets.Length; i++)
            {
                var asset = args.Assets[i];

                string fileName = string.Empty;
                if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
                {
                    fileName = PHAssetResource.GetAssetResources(asset).FirstOrDefault().OriginalFilename;
                }

                switch (asset.MediaType)
                {
                case PHAssetMediaType.Video:

                    PHImageManager.DefaultManager.RequestImageForAsset(asset, new SizeF(150.0f, 150.0f),
                                                                       PHImageContentMode.AspectFill, options, async(img, info) =>
                    {
                        var startIndex = fileName.IndexOf(".", StringComparison.CurrentCulture);

                        string path = "";
                        if (startIndex != -1)
                        {
                            path = FileHelper.GetOutputPath(MediaFileType.Image, TemporalDirectoryName, $"{fileName.Substring(0, startIndex)}-THUMBNAIL.JPG");
                        }
                        else
                        {
                            path = FileHelper.GetOutputPath(MediaFileType.Image, TemporalDirectoryName, string.Empty);
                        }

                        if (!File.Exists(path))
                        {
                            img.AsJPEG().Save(path, true);
                        }

                        TaskCompletionSource <string> tvcs = new TaskCompletionSource <string>();

                        var vOptions = new PHVideoRequestOptions();
                        vOptions.NetworkAccessAllowed = true;
                        vOptions.Version      = PHVideoRequestOptionsVersion.Original;
                        vOptions.DeliveryMode = PHVideoRequestOptionsDeliveryMode.FastFormat;


                        PHImageManager.DefaultManager.RequestAvAsset(asset, vOptions, (avAsset, audioMix, vInfo) =>
                        {
                            var vPath = FileHelper.GetOutputPath(MediaFileType.Video, TemporalDirectoryName, fileName);

                            if (!File.Exists(vPath))
                            {
                                AVAssetExportSession exportSession = new AVAssetExportSession(avAsset, AVAssetExportSession.PresetHighestQuality);

                                exportSession.OutputUrl      = NSUrl.FromFilename(vPath);
                                exportSession.OutputFileType = AVFileType.QuickTimeMovie;


                                exportSession.ExportAsynchronously(() =>
                                {
                                    Console.WriteLine(exportSession.Status);

                                    tvcs.TrySetResult(vPath);
                                    //exportSession.Dispose();
                                });
                            }
                        });

                        var videoUrl = await tvcs.Task;
                        var meFile   = new MediaFile()
                        {
                            Type        = MediaFileType.Video,
                            Path        = videoUrl,
                            PreviewPath = path
                        };
                        results.Add(meFile);
                        OnMediaPicked?.Invoke(this, meFile);

                        if (args.Assets.Length == results.Count && !completed)
                        {
                            completed = true;
                            tcs.TrySetResult(results);
                        }
                    });



                    break;

                default:

                    Photos.PHImageManager.DefaultManager.RequestImageData(asset, options, (data, dataUti, orientation, info) =>
                    {
                        string path = FileHelper.GetOutputPath(MediaFileType.Image, TemporalDirectoryName, fileName);

                        if (!File.Exists(path))
                        {
                            Debug.WriteLine(dataUti);
                            var imageData = data;
                            //var image = UIImage.LoadFromData(imageData);

                            //if (imageScale < 1.0f)
                            //{
                            //    //begin resizing image
                            //    image = image.ResizeImageWithAspectRatio((float)imageScale);
                            //}

                            //if (imageQuality < 100)
                            //{
                            //    imageData = image.AsJPEG(Math.Min(imageQuality,100));
                            //}

                            imageData?.Save(path, true);
                        }

                        var meFile = new MediaFile()
                        {
                            Type        = MediaFileType.Image,
                            Path        = path,
                            PreviewPath = path
                        };

                        results.Add(meFile);
                        OnMediaPicked?.Invoke(this, meFile);
                        if (args.Assets.Length == results.Count && !completed)
                        {
                            completed = true;
                            tcs.TrySetResult(results);
                        }
                    });

                    break;
                }
            }


            mediaPickTcs?.TrySetResult(await tcs.Task);
        }
Пример #6
0
        async void FinishedPickingAssets(object sender, MultiAssetEventArgs args)
        {
            var picker = (GMImagePickerController)sender;

            picker.FinishedPickingAssets -= FinishedPickingAssets;
            picker.Canceled -= OnPickerCanceled;

            // synchronous: NO.异步。
            // a.deliveryMode: Opportunistic: 会返回多张图片
            //  1). ResizeMode.None: 先返回低清的缩略图,再返回原图大小
            //  2). ResizeMode.Fast: 先返回低清的缩略图,再返回的原图会使用targetSize来最优解码图片,获得的图片大小可能比targetSize大
            //  3). ResizeMode.Exact: 先返回低清的缩略图,再返回的原图会使用targetSize的高质量图

            // b.deliveryMode: HighQualityFormat: 只会返回一张高清图片
            //  1). ResizeMode.None: 返回的是原图大小
            //  2). ResizeMode.Fast: 当原图是压缩图时,会使用targetSize来最优解码图片,获得的图片大小可能比targetSize大
            //  3). ResizeMode.Exact: 解压和Fast一样,但是返回的是指定targetSize的高质量图

            // c.deliveryMode: FastFormat: 只会返回一张图片,并且可能是低清图
            //  1). ResizeMode.None: 返回一张低清图
            //  2). ResizeMode.Fast: 返回一张低清图
            //  3). ResizeMode.Exact: 返回一张低清图
            var options = new PHImageRequestOptions
            {
                NetworkAccessAllowed = true,
                Synchronous          = false,
                DeliveryMode         = PHImageRequestOptionsDeliveryMode.HighQualityFormat,
                ResizeMode           = PHImageRequestOptionsResizeMode.Exact,
            };

            var             tcs       = new TaskCompletionSource <object>();
            bool            completed = false;
            List <FileData> result    = new List <FileData>();

            for (var i = 0; i < args.Assets.Length; i++)
            {
                var asset = args.Assets[i];
                switch (asset.MediaType)
                {
                case PHAssetMediaType.Video:
                    // 未测
                    PHImageManager.DefaultManager.RequestImageForAsset(
                        asset,
                        new SizeF(FileData.ThumbSize, FileData.ThumbSize),
                        PHImageContentMode.AspectFit,
                        options,
                        async(img, info) =>
                    {
                        // 获取路径,麻烦
                        TaskCompletionSource <NSUrl> tcsUrl = new TaskCompletionSource <NSUrl>();
                        var vOptions = new PHVideoRequestOptions
                        {
                            NetworkAccessAllowed = true,
                            Version      = PHVideoRequestOptionsVersion.Original,
                            DeliveryMode = PHVideoRequestOptionsDeliveryMode.FastFormat,
                        };
                        PHImageManager.DefaultManager.RequestAvAsset(
                            asset,
                            vOptions,
                            (avAsset, audioMix, vInfo) =>
                        {
                            if (avAsset is AVUrlAsset avUrl)
                            {
                                tcsUrl.TrySetResult(avUrl.Url);
                            }
                            else
                            {
                                tcsUrl.TrySetResult(null);
                            }
                        });
                        NSUrl url = await tcsUrl.Task;

                        // 生成文件描述和缩略图
                        var fd       = ParseUrl(url);
                        fd.Desc      = $"{asset.PixelWidth} x {asset.PixelHeight} ({fd.Ext.TrimStart('.')})";
                        fd.ThumbPath = Path.Combine(Kit.CachePath, Kit.NewGuid + "-t.jpg");
                        img.AsJPEG().Save(fd.ThumbPath, true);
                        result.Add(fd);

                        if (args.Assets.Length == result.Count && !completed)
                        {
                            completed = true;
                            tcs.TrySetResult(null);
                        }
                    });

                    break;

                default:
                    PHImageManager.DefaultManager.RequestImageForAsset(
                        asset,
                        new SizeF(FileData.ThumbSize, FileData.ThumbSize),
                        PHImageContentMode.AspectFit,
                        options,
                        async(img, info) =>
                    {
                        // 获取路径,麻烦
                        TaskCompletionSource <NSUrl> tcsUrl = new TaskCompletionSource <NSUrl>();
                        asset.RequestContentEditingInput(new PHContentEditingInputRequestOptions(), (input, _) =>
                        {
                            tcsUrl.TrySetResult(input.FullSizeImageUrl);
                        });
                        NSUrl url = await tcsUrl.Task;

                        // 生成文件描述和缩略图
                        var fd  = ParseUrl(url);
                        fd.Desc = $"{asset.PixelWidth} x {asset.PixelHeight} ({fd.Ext.TrimStart('.')})";
                        if (asset.PixelWidth > FileData.ThumbSize || asset.PixelHeight > FileData.ThumbSize)
                        {
                            fd.ThumbPath = Path.Combine(Kit.CachePath, Kit.NewGuid + "-t.jpg");
                            img.AsJPEG().Save(fd.ThumbPath, true);
                        }
                        result.Add(fd);

                        if (args.Assets.Length == result.Count && !completed)
                        {
                            completed = true;
                            tcs.TrySetResult(null);
                        }
                    });

                    break;
                }
            }

            // 用临时tcs等待比直接在回调方法中用_tcs速度大幅提高!!!
            await tcs.Task;

            _tcs.TrySetResult(result);
        }
        async Task <IList <MediaAsset> > LoadMediaAsync()
        {
            IList <MediaAsset> assets = new List <MediaAsset>();
            var imageManager          = new PHCachingImageManager();
            var hasPermission         = await RequestPermissionAsync();

            if (hasPermission)
            {
                await Task.Run(async() =>
                {
                    var thumbnailRequestOptions                  = new PHImageRequestOptions();
                    thumbnailRequestOptions.ResizeMode           = PHImageRequestOptionsResizeMode.Fast;
                    thumbnailRequestOptions.DeliveryMode         = PHImageRequestOptionsDeliveryMode.FastFormat;
                    thumbnailRequestOptions.NetworkAccessAllowed = true;
                    thumbnailRequestOptions.Synchronous          = true;

                    var requestOptions                  = new PHImageRequestOptions();
                    requestOptions.ResizeMode           = PHImageRequestOptionsResizeMode.Exact;
                    requestOptions.DeliveryMode         = PHImageRequestOptionsDeliveryMode.HighQualityFormat;
                    requestOptions.NetworkAccessAllowed = true;
                    requestOptions.Synchronous          = true;

                    var fetchOptions             = new PHFetchOptions();
                    fetchOptions.SortDescriptors = new NSSortDescriptor[] { new NSSortDescriptor("creationDate", false) };
                    fetchOptions.Predicate       = NSPredicate.FromFormat($"mediaType == {(int)PHAssetMediaType.Image} || mediaType == {(int)PHAssetMediaType.Video}");
                    var fetchResults             = PHAsset.FetchAssets(fetchOptions);
                    var tmpPath       = Path.GetTempPath();
                    var allAssets     = fetchResults.Select(p => p as PHAsset).ToArray();
                    var thumbnailSize = new CGSize(300.0f, 300.0f);

                    imageManager.StartCaching(allAssets, thumbnailSize, PHImageContentMode.AspectFit, thumbnailRequestOptions);
                    imageManager.StartCaching(allAssets, PHImageManager.MaximumSize, PHImageContentMode.AspectFit, requestOptions);


                    foreach (var result in fetchResults)
                    {
                        var phAsset = (result as PHAsset);
                        var name    = PHAssetResource.GetAssetResources(phAsset)?.FirstOrDefault()?.OriginalFilename;
                        var asset   = new MediaAsset()
                        {
                            Id   = phAsset.LocalIdentifier,
                            Name = name,
                            Type = phAsset.MediaType == PHAssetMediaType.Image ? MediaAssetType.Image : MediaAssetType.Video,
                        };

                        imageManager.RequestImageForAsset(phAsset, thumbnailSize, PHImageContentMode.AspectFit, thumbnailRequestOptions, (image, info) =>
                        {
                            if (image != null)
                            {
                                NSData imageData = null;
                                if (image.CGImage.RenderingIntent == CGColorRenderingIntent.Default)
                                {
                                    imageData = image.AsJPEG(0.8f);
                                }
                                else
                                {
                                    imageData = image.AsPNG();
                                }

                                if (imageData != null)
                                {
                                    var fileName  = Path.Combine(tmpPath, $"tmp_thumbnail_{Path.GetFileNameWithoutExtension(name)}.jpg");
                                    NSError error = null;
                                    imageData.Save(fileName, true, out error);
                                    if (error == null)
                                    {
                                        asset.PreviewPath = fileName;
                                    }
                                }
                            }
                        });
                        switch (phAsset.MediaType)
                        {
                        case PHAssetMediaType.Image:

                            imageManager.RequestImageForAsset(phAsset, PHImageManager.MaximumSize, PHImageContentMode.AspectFit, requestOptions, (image, info) =>
                            {
                                if (image != null)
                                {
                                    NSData imageData = null;
                                    if (image.CGImage.RenderingIntent == CGColorRenderingIntent.Default)
                                    {
                                        imageData = image.AsJPEG(0.8f);
                                    }
                                    else
                                    {
                                        imageData = image.AsPNG();
                                    }

                                    if (imageData != null)
                                    {
                                        var fileName  = Path.Combine(tmpPath, $"tmp_{name}");
                                        NSError error = null;
                                        imageData.Save(fileName, true, out error);
                                        if (error == null)
                                        {
                                            asset.Path = fileName;
                                        }
                                    }
                                }
                            });
                            break;

                        case PHAssetMediaType.Video:
                            var videoRequestOptions = new PHVideoRequestOptions();
                            videoRequestOptions.NetworkAccessAllowed = true;
                            var tcs = new TaskCompletionSource <bool>();
                            imageManager.RequestAvAsset(phAsset, null, (vAsset, audioMix, info) =>
                            {
                                var avAsset   = vAsset as AVUrlAsset;
                                var avData    = NSData.FromUrl(avAsset.Url);
                                NSError error = null;
                                var path      = Path.Combine(tmpPath, $"tmp_{name}");
                                avData.Save(path, true, out error);
                                if (error == null)
                                {
                                    asset.Path = path;


                                    tcs.TrySetResult(true);
                                }
                                else
                                {
                                    tcs.TrySetResult(false);
                                }
                            });
                            await tcs.Task;
                            break;
                        }

                        UIApplication.SharedApplication.InvokeOnMainThread(delegate
                        {
                            OnMediaAssetLoaded?.Invoke(this, new MediaEventArgs(asset));
                        });
                        assets.Add(asset);

                        if (requestStop)
                        {
                            break;
                        }
                    }
                });

                imageManager.StopCaching();
            }

            return(assets);
        }
Пример #8
0
        partial void Play(NSObject sender)
        {
            // An AVPlayerLayer has already been created for this asset; just play it.
            if (playerLayer != null)
            {
                playerLayer.Player.Play();
            }
            else
            {
                var options = new PHVideoRequestOptions
                {
                    NetworkAccessAllowed = true,
                    DeliveryMode         = PHVideoRequestOptionsDeliveryMode.Automatic,
                    ProgressHandler      = (double progress, NSError error, out bool stop, NSDictionary info) =>
                    {
                        stop = false;

                        // Handler might not be called on the main queue, so re-dispatch for UI work.
                        DispatchQueue.MainQueue.DispatchSync(() =>
                        {
                            ProgressView.Progress = (float)progress;
                        });
                    }
                };

                // Request an AVAsset for the displayed PHAsset and set up a layer for playing it.
                PHImageManager.DefaultManager.RequestPlayerItem(Asset, options, (playerItem, info) =>
                {
                    DispatchQueue.MainQueue.DispatchSync(() =>
                    {
                        if (this.playerLayer != null || playerItem == null)
                        {
                            return;
                        }

                        // Create an AVPlayer and AVPlayerLayer with the AVPlayerItem.
                        AVPlayer player;

                        if (Asset.PlaybackStyle == PHAssetPlaybackStyle.VideoLooping)
                        {
                            var queuePlayer = AVQueuePlayer.FromItems(new[] { playerItem });
                            playerLooper    = AVPlayerLooper.FromPlayer(queuePlayer, playerItem);
                            player          = queuePlayer;
                        }
                        else
                        {
                            player = AVPlayer.FromPlayerItem(playerItem);
                        }

                        var playerLayer = AVPlayerLayer.FromPlayer(player);

                        // Configure the AVPlayerLayer and add it to the view.
                        playerLayer.VideoGravity = AVLayerVideoGravity.ResizeAspect;
                        playerLayer.Frame        = View.Layer.Bounds;
                        View.Layer.AddSublayer(playerLayer);

                        player.Play();

                        // Refer to the player layer so we can remove it later.
                        this.playerLayer = playerLayer;
                    });
                });
            }
        }