【问题标题】:Xamarin iOS camera and photosXamarin iOS 相机和照片
【发布时间】:2018-03-09 22:39:33
【问题描述】:

我正在使用 iOS 相机拍照并尝试从图像中提取元数据。这是我的代码:-

partial void BtnCamera_TouchUpInside(UIButton sender)
        {
            UIImagePickerController imagePicker = new UIImagePickerController();
            imagePicker.PrefersStatusBarHidden();
            imagePicker.SourceType = UIImagePickerControllerSourceType.Camera;

            // handle saving picture and extracting meta-data from picture //
            imagePicker.FinishedPickingMedia += Handle_FinishedPickingMedia;

            // present //
            PresentViewController(imagePicker, true, () => { });         
        }


protected void Handle_FinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs e)
        {
            try
            {
                // determine what was selected, video or image
                bool isImage = false;
                switch (e.Info[UIImagePickerController.MediaType].ToString())
                {
                    case "public.image":
                        isImage = true;
                        break;
                }

                // get common info 
                NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceURL")] as NSUrl;
                if (referenceURL != null)
                    Console.WriteLine("Url:" + referenceURL.ToString());

我可以启动相机,拍照,然后当我单击“使用照片”时...referenceURL 返回为 NULL...如何获取 url,以便提取 GPS 坐标照片和其他属性?

【问题讨论】:

  • 我的猜测是图片永远不会保存在图库中...
  • 使用相机拍照时,没有referenceURL。如果要获取元数据,可以使用密钥UIImagePickerControllerMediaMetadata
  • @LandLu-MSFT 我想要一个示例/示例代码...你有我的链接吗?
  • 我可以为您制作样品。但首先,请告诉我你只需要 url 做什么?或者元数据可以满足您的要求。
  • @LandLu-MSFT 我希望 URL 提取元数据,如 developer.xamarin.com/recipes/ios/media/images/… 所示

标签: ios xamarin xamarin.ios camera photo


【解决方案1】:

我在使用 URL 时遇到了很多麻烦。它可以是一个文件,也可以是一个 Web url,它在每个设备上的作用都不同。我的应用程序在我的测试组中崩溃和烧毁了很多次。我终于找到了一种从数据中获取元数据的方法。有多种方法可以获取 DateTaken、宽度和高度以及 GPS 坐标。此外,我还需要相机 MFG 和模型。

string dateTaken = string.Empty;
string lat = string.Empty;
string lon = string.Empty;
string width = string.Empty;
string height = string.Empty;
string mfg = string.Empty;
string model = string.Empty;

PHImageManager.DefaultManager.RequestImageData(asset, options, (data, dataUti, orientation, info) => {

    dateTaken = asset.CreationDate.ToString();

    // GPS Coordinates
    var coord = asset.Location?.Coordinate;
    if (coord != null)
    {
        lat = asset.Location?.Coordinate.Latitude.ToString();
        lon = asset.Location?.Coordinate.Longitude.ToString();
    }

    UIImage img = UIImage.LoadFromData(data);
    if (img.CGImage != null)
    {
        width = img.CGImage?.Width.ToString();
        height = img.CGImage?.Height.ToString();
    }
    using (CGImageSource imageSource = CGImageSource.FromData(data, null))
    {
        if (imageSource != null)
        {
            var ns = new NSDictionary();
            var imageProperties = imageSource.CopyProperties(ns, 0);
            if (imageProperties != null)
            {
                width = ReturnStringIfNull(imageProperties[CGImageProperties.PixelWidth]);
                height = ReturnStringIfNull(imageProperties[CGImageProperties.PixelHeight]);

                var tiff = imageProperties.ObjectForKey(CGImageProperties.TIFFDictionary) as NSDictionary;
                if (tiff != null)
                {
                    mfg = ReturnStringIfNull(tiff[CGImageProperties.TIFFMake]);
                    model = ReturnStringIfNull(tiff[CGImageProperties.TIFFModel]);
                    //dateTaken = ReturnStringIfNull(tiff[CGImageProperties.TIFFDateTime]);
                }
            }
        }
    }
}

}

小助手功能

private string ReturnStringIfNull(NSObject inObj)
{
    if (inObj == null) return String.Empty;
    return inObj.ToString();
}

【讨论】:

    【解决方案2】:

    您可以从参考网址请求PHAsset,其中将包含一些元数据。您可以请求图像数据以获取更多。

    注意:如果您需要完整的EXIF,您需要检查以确保设备上的图像(可能是基于iCloud的),如果需要下载它,然后使用ImageIO框架加载图像数据(很多SO 的帖子涵盖了这一点)。

    public void ImagePicker_FinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs e)
    {
        void ImageData(PHAsset asset)
        {
            if (asset == null) throw new Exception("PHAsset is null");
            PHImageManager.DefaultManager.RequestImageData(asset, null, (data, dataUti, orientation, info) =>
            {
                Console.WriteLine(data);
                Console.WriteLine(info);
            });
        }
    
        PHAsset phAsset;
        if (e.ReferenceUrl == null)
        {
            e.OriginalImage?.SaveToPhotosAlbum((image, error) =>
            {
                if (error == null)
                {
                    var options = new PHFetchOptions
                    {
                        FetchLimit = 1,
                        SortDescriptors = new[] { new NSSortDescriptor("creationDate", true) }
                    };
                    phAsset = PHAsset.FetchAssets(options).FirstOrDefault() as PHAsset;
                    ImageData(phAsset);
                }
            });
        }
        else
        {
            phAsset = PHAsset.FetchAssets(new[] { e.ReferenceUrl }, null).FirstOrDefault() as PHAsset;
            ImageData(phAsset);
        }
    }
    

    注意:确保您已请求运行时照片库授权 PHPhotoLibrary.RequestAuthorization) 并已在 info.plist 中设置 Privacy - Photo Library Usage Description 字符串以避免严重的隐私崩溃

    【讨论】:

    • 我确实在我的 plist.info 文件中设置了该设置..但是仍然出现崩溃,我已经注释掉了我的 FinishedPickingMedia 函数中的所有行,除了你注意到的那些.. .
    • 不知何故崩溃发生在我的 MAin.cs UIApplication.Main(args, null, "AppDelegate");行...未处理的异常:Foundation.MonoTouchException:抛出了 Objective-C 异常。名称:NSInvalidArgumentException 原因:-[NSNull 方案]:无法识别的选择器发送到实例 0x39fb9978
    • 令我吃惊的是,这些照片从来没有专门保存在我的相册中
    • e.Info[UIImagePickerController.MediaType].ToString() 有一些与缓存中的照片相关的信息
    • 然而 NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceURL")] as NSUrl;... 为空
    猜你喜欢
    • 2017-04-15
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多