【问题标题】:How to get image metadata in ios如何在ios中获取图像元数据
【发布时间】:2012-09-10 19:19:28
【问题描述】:

我想使用 ios 显示图像元数据。 元数据,如光圈、快门速度、曝光补​​偿、ISO、镜头焦距等。 因此,如果有人有想法,请帮助我。

【问题讨论】:

  • 图像元数据(名称、大小等)是什么意思?请详细说明...

标签: ios image metadata


【解决方案1】:
CGImageSourceRef source = CGImageSourceCreateWithURL( (CFURLRef) aUrl, NULL);
CGImageSourceRef source = CGImageSourceCreateWithData( (CFDataRef) theData, NULL);
NSDictionary* metadata = (NSDictionary *)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source,0,NULL));
CFRelease(source);

查看字典内容here

【讨论】:

  • 感谢乔纳斯施内利。它对我有很大帮助。谢谢朋友。
  • 当然,您应该提到,您必须将#import 添加到您的标题中才能使用该类...
  • 如果您使用 ARC,请像这样拆分它以避免内存泄漏CFDictionaryRef dictRef = CGImageSourceCopyPropertiesAtIndex(source,0,NULL); NSDictionary* metadata = (__bridge NSDictionary *)dictRef; <do your thing> CFRelease(source); CFRelease(dictRef);
【解决方案2】:

这是从图像路径获取元数据的代码:

NSData *imagedata = [NSData dataWithContentsOfFile:imagePath];
CGImageSourceRef source = CGImageSourceCreateWithData((CFMutableDataRef)imagedata, NULL);
NSDictionary *metadata = [(NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source,0,NULL)autorelease];

或者,如果使用 swift 4.0:

var imagedata = Data(contentsOfFile: imagePath) 
var source: CGImageSourceRef = CGImageSourceCreateWithData((imagedata as? CFMutableDataRef), nil) 
var metadata = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [AnyHashable: Any]

【讨论】:

  • 如何在 swift3 或 swift4 中做到这一点?
  • var imagedata = Data(contentsOfFile: imagePath) var source: CGImageSourceRef = CGImageSourceCreateWithData((imagedata as?CFMutableDataRef), nil) var metadata = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as? [AnyHashable: 任意]
  • 希望对你有帮助
  • 是的!我也尝试过同样的方法并且正在工作!我认为你需要在你的答案中更新这个
【解决方案3】:

斯威夫特 4

static func imageDataProperties(_ imageData: Data) -> NSDictionary? {
    if let imageSource = CGImageSourceCreateWithData(imageData as CFData, nil)
    {
      if let dictionary = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) {
        return dictionary
      }
    }
    return nil
  }

【讨论】:

    【解决方案4】:

    通过包装为 Swift 结构的 Core Graphics 读取图像属性:

    struct ImageMetadata {
    
        var imageProperties : [CFString: Any]
    
        init?(data: Data) {
            let options = [kCGImageSourceShouldCache: kCFBooleanFalse]
            if let imageSource = CGImageSourceCreateWithData(data as CFData, options as CFDictionary),
                let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [CFString: Any] {
                self.imageProperties = imageProperties
            } else {
                return nil
            }
        }
    
        var dpi : Int? { imageProperties[kCGImagePropertyDPIWidth] as? Int }
        var width : Int? { imageProperties[kCGImagePropertyPixelWidth] as? Int }
        var height : Int? { imageProperties[kCGImagePropertyPixelHeight] as? Int }
    
    }
    

    【讨论】:

      【解决方案5】:
      -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
      {
        NSURL *referenceURL = [info objectForKey:UIImagePickerControllerReferenceURL];
      
          if(referenceURL) {
          ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
          [library assetForURL:referenceURL resultBlock:^(ALAsset *asset) {
              ALAssetRepresentation *rep = [asset defaultRepresentation];
              NSDictionary *metadata = rep.metadata;
              NSLog(@"image data %@", metadata);
      
      
          } failureBlock:^(NSError *error) {
              // error handling
          }];
      }
      

      【讨论】:

      • 最好在你的回答中给出一些解释。
      【解决方案6】:

      使用照片框架更新到 iOS 11

      目标 - C:

      #import <Photos/Photos.h>
      
      - (void)imagePickerController:(UIImagePickerController *)imagePicker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
      
          PHAsset* asset = info[UIImagePickerControllerPHAsset];
      
          [asset requestContentEditingInputWithOptions:nil completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
              CIImage *fullImage = [CIImage imageWithContentsOfURL:contentEditingInput.fullSizeImageURL];
      
              NSLog(@"%@", fullImage.properties.description);
          }];
      
          [imagePicker dismissViewControllerAnimated:YES completion:nil];
      }
      

      你还需要照片库使用权限(NSPhotoLibraryUsageDescription),然后可以添加以下代码来查看是否加载或查看是否出现

      [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
          switch (status) {
              case PHAuthorizationStatusAuthorized:
                  NSLog(@"PHAuthorizationStatusAuthorized");
                  break;
              case PHAuthorizationStatusDenied:
                  NSLog(@"PHAuthorizationStatusDenied");
                  break;
              case PHAuthorizationStatusNotDetermined:
                  NSLog(@"PHAuthorizationStatusNotDetermined");
                  break;
              case PHAuthorizationStatusRestricted:
                  NSLog(@"PHAuthorizationStatusRestricted");
                  break;
          }
      }];
      

      【讨论】:

        【解决方案7】:

        这是我用来获取图像大小的:

        + (CGSize) sizeOfImage:(NSString *) fileName withPath: (NSURL *) fullDirectoryPath;
        {
            NSURL *imageNameWithPath = [NSURL URLWithString:fileName relativeToURL:fullDirectoryPath];
        
            CGImageSourceRef source = CGImageSourceCreateWithURL( (CFURLRef) imageNameWithPath, NULL);
            if (!source) return CGSizeZero;
        
            CFDictionaryRef dictRef = CGImageSourceCopyPropertiesAtIndex(source,0,NULL);
            NSDictionary* metadata = (__bridge NSDictionary *)dictRef;
            NSLog(@"metadata= %@", metadata);
            CGSize result = CGSizeZero;
            CGFloat width = [metadata[@"PixelWidth"] floatValue];
            CGFloat height = [metadata[@"PixelHeight"] floatValue];
            NSLog(@"width= %f, height= %f", width, height);
        
            // The orientation in the metadata does *not* map to UIImageOrientation. Rather, see: https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGImageProperties_Reference/index.html#//apple_ref/doc/constant_group/Individual_Image_Properties
            // This idea of orientation seems a little odd to me, but it seems it translates to even numbers need to be switched in width/height, odd numbers do not.
            NSUInteger orientation = [metadata[@"Orientation"] integerValue];
        
            switch (orientation) {
                // Comments give "Location of the origin of the image"
                case 1: // Top, left
                case 3: // Bottom, right
                case 5: // Left, top
                case 7: // Right, bottom
                    result = CGSizeMake(width, height);
                    break;
        
                case 2: // Top, right
                case 4: // Bottom, left
                case 6: // Right, top
                case 8: // Left, bottom
                    result = CGSizeMake(height, width);
                    break;
        
                default:
                    NSAssert(NO, @"Should not get to here!");
                    break;
            }
        
            CFRelease(source);
            NSLog(@"size: %@, orientation: %d", NSStringFromCGSize(result), orientation);
        
            return result;
        }
        
        /* Example meta data:
            ColorModel = RGB;
            Depth = 8;
            Orientation = 6;
            PixelHeight = 1936;
            PixelWidth = 2592;
            "{Exif}" =     {
                ColorSpace = 1;
                PixelXDimension = 2592;
                PixelYDimension = 1936;
            };
            "{JFIF}" =     {
                DensityUnit = 0;
                JFIFVersion =         (
                                       1,
                                       1
                                       );
                XDensity = 1;
                YDensity = 1;
            };
            "{TIFF}" =     {
                Orientation = 6;
            };
        }
        */
        

        【讨论】:

          【解决方案8】:

          回答我自己的问题。获取 GPS 元数据的内存有效且快速的方法是

          let options = [kCGImageSourceShouldCache as String: kCFBooleanFalse]
          if let data = NSData(contentsOfURL: url), imgSrc = CGImageSourceCreateWithData(data, options) {
              let metadata = CGImageSourceCopyPropertiesAtIndex(imgSrc, 0, options) as Dictionary
              let gpsData = metadata[kCGImagePropertyGPSDictionary] as? [String : AnyObject]
          }
          

          第二个选项是

          if let img = CIImage(contentsOfURL: url), metadata = img.properties(), 
          gpsData = metadata[kCGImagePropertyGPSDictionary] as? [String : AnyObject] { … }
          

          它在 Swift 中看起来更好,但使用更多内存(通过 Profiler 测试)。

          【讨论】:

            【解决方案9】:

            这是一个示例代码,可帮助我们读取光圈、快门速度、曝光补​​偿、ISO、镜头、焦距等并将其转换为字典格式。
            考虑单个类的以下所有功能

            guard let imageSource = CGImageSourceCreateWithURL(fileURL as CFURL, nil),
                  let metadata = CGImageSourceCopyMetadataAtIndex(imageSource, 0, nil),
                  let tags = CGImageMetadataCopyTags(metadata),
                  let imageInfo = self.readMetadataTagArr(tagArr: tags) else { return }
            

            还有一些帮助函数实际上完成了将数据提取/转换为字典格式的所有工作。

                /// Reads the Arrays of tags and convert them into a dictionary of [String: Any]
            private static func readMetadataTagArr(tagArr: CFArray) -> [String: Any]? {
                var result = [String: Any]()
                for (_, tag) in (tagArr as NSArray).enumerated() {
                    let tagMetadata = tag as! CGImageMetadataTag
                    if let cfName = CGImageMetadataTagCopyName(tagMetadata) {
                        let name = String(cfName)
                        result[name] = self.readMetadataTag(metadataTag: tagMetadata)
                    }
                }
                return result
            }
            
                /// convert CGImageMetadataTag to a dictionary of [String: Any]
            private static func readMetadataTag(metadataTag: CGImageMetadataTag) -> [String: Any] {
                var result = [String: Any]()
                guard let cfName = CGImageMetadataTagCopyName(metadataTag) else { return result }
                let name = String(cfName)
                let value = CGImageMetadataTagCopyValue(metadataTag)
                
                /// checking the type of `value` object and then performing respective operation on `value`
                if CFGetTypeID(value) == CFStringGetTypeID() {
                    let valueStr = String(value as! CFString)
                    result[name] = valueStr
                } else if CFGetTypeID(value) == CFDictionaryGetTypeID() {
                    let nsDict: NSDictionary = value as! CFDictionary
                    result[name] = self.getDictionary(from: nsDict)
                } else if CFGetTypeID(value) == CFArrayGetTypeID() {
                    let valueArr: NSArray = value as! CFArray
                    for (_, item) in valueArr.enumerated() {
                        let tagMetadata = item as! CGImageMetadataTag
                        result[name] = self.readMetadataTag(metadataTag: tagMetadata)
                    }
                } else {
                    // when the data was of some other type
                    let descriptionString: CFString = CFCopyDescription(value);
                    let str = String(descriptionString)
                    result[name] = str
                }
                return result
            }
            
                /// Converting CGImage Metadata dictionary to [String: Any]
            private static func getDictionary(from nsDict: NSDictionary) -> [String: Any] {
                var subDictionary = [String: Any]()
                for (key, val) in nsDict {
                    guard let key = key as? String else { continue }
                    let tempDict: [String: Any] = [key: val]
                    if JSONSerialization.isValidJSONObject(tempDict) {
                        subDictionary[key] = val
                    } else {
                        let mData = val as! CGImageMetadataTag
                        let tempDict: [String: Any] = [key: self.readMetadataTag(metadataTag: mData)]
                        if JSONSerialization.isValidJSONObject(tempDict) {
                            subDictionary[key] = tempDict
                        }
                    }
                }
                return subDictionary
            }
            

            这是提取的所有字典键的列表

            这里有一些示例字典值,例如 FocalLength、ApertureValue、LensSpecification 等

            LensModel、ShutterSpeedValue 等

            【讨论】:

              【解决方案10】:

              您需要使用资产库来读取图片的exif元数据。

              #import <AssetsLibrary/AssetsLibrary.h>
              

              然后添加以下代码:

              - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
              {
                  NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];
              
                  ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
                  __block NSMutableDictionary *imageMetadata = nil;
                  [library assetForURL:assetURL
                           resultBlock:^(ALAsset *asset)  {
                               NSDictionary *metadata = asset.defaultRepresentation.metadata;
                               imageMetadata = [[NSMutableDictionary alloc] initWithDictionary:metadata];
                               NSLog(@"%@",imageMetadata.description);
                           }
                          failureBlock:^(NSError *error) {
                          }];
              }
              

              希望这会有所帮助

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-08-27
                • 1970-01-01
                • 1970-01-01
                • 2022-07-09
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多