iOS图片元数据的读写

图片的本身就是各种图像数据的载体,包含着像素、色彩、灰度等各种数据信息,除此之外,还包含着曝光数据、日期、位置、版权等元数据(metadata)。
何为图片元数据

元数据包括许多重要的信息,常用的有Exif(可交换图像文件格式,Exchangeable image file format)、GPS(位置信息)和TIFF(Tagged Image File Format,标签图像文件格式)。

所谓元数据是指Data about Data,就是用来描述数据的数据。

以Exif为例,其中包含了大量信息:

Image Description 图像描述、来源. 指生成图像的工具
Artist 作者 有些相机可以输入使用者的名字
Make 生产者 指产品生产厂家
Model 型号 指设备型号
Orientation方向 有的相机支持,有的不支持
XResolution/YResolution X/Y方向分辨率 本栏目已有专门条目解释此问题。
ResolutionUnit分辨率单位 一般为PPI
Software软件 显示固件Firmware版本
DateTime日期和时间
YCbCrPositioning 色相定位
ExifOffsetExif信息位置,定义Exif在信息在文件中的写入,有些软件不显示。
ExposureTime 曝光时间 即快门速度
FNumber光圈系数
ExposureProgram曝光程序 指程序式自动曝光的设置,各相机不同,可能是Sutter Priority(快门优先)、Aperture Priority(快门优先)等等。
ISO speed ratings感光度
ExifVersionExif版本
DateTimeOriginal创建时间
DateTimeDigitized数字化时间
ComponentsConfiguration图像构造(多指色彩组合方案)
CompressedBitsPerPixel(BPP)压缩时每像素色彩位 指压缩程度
ExposureBiasValue曝光补偿。
MaxApertureValue最大光圈
MeteringMode测光方式, 平均式测光、中央重点测光、点测光等。
Lightsource光源 指白平衡设置
Flash是否使用闪光灯。
FocalLength焦距,一般显示镜头物理焦距,有些软件可以定义一个系数,从而显示相当于35mm相机的焦距 MakerNote(User Comment)作者标记、说明、记录
FlashPixVersionFlashPix版本 (个别机型支持)ColorSpace色域、色彩空间
ExifImageWidth(Pixel X Dimension)图像宽度 指横向像素数
ExifImageLength(Pixel Y Dimension)图像高度 指纵向像素数
Interoperability IFD通用性扩展项定义指针 和TIFF文件相关,具体含义不详
FileSource源文件 Compression压缩比。

这些数据就是构成一张图片的元素,也相当于一张图片的名片,包含着丰富的信息。

你可以在此了解更多关于Exif的具体研究。
在开发中使用

目前市场上的大部分智能手机拍摄的照片都支持写入元数据,因此我们可以利用图片的元数据来携带需要添加的数据。在处理图片时,我们往往需要对图片数据进行操作,除了操作其中的图像信息外,我们还可以对图片信息的元数据进行操作,包括存和取。这对于传递数据将是十分便利的,其中一方只需将数据写入图片,另一方通过读取图片的元数据就可获取所要传递的数据,而不需要传除图片之外的任何对象,在实际开发中应用场景很多。


    首先,我们需要借助与UIImagePickerControllerDelegate的代理方法,创建一个UIImagePickerController,在其代理方法- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info中就可获取info,从而获取image对象:

UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];

    为获取info的metadata,要使用ALAssetsLibrary的assetForURL: resultBlock:方法:

 //1. 首先得到Reference URL
    NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];
    //2. 创建一个ALAssetsLibrary
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    //3. 使用回调方法,得到字典类型的metadata



 [library assetForURL:assetURL
             resultBlock:^(ALAsset *asset) {

                 NSDictionary *imageMetadata = [[NSMutableDictionary alloc] initWithDictionary:asset.defaultRepresentation.metadata];

                 NSLog(@"metadata:--%@",imageMetadata);

                 NSDictionary *gpsDic = [imageMetadata objectForKey:@"{GPS}"];
                 NSDictionary *exifDic = [imageMetadata objectForKey:@"{Exif}"];
                 NSDictionary *tiffDic = [imageMetadata objectForKey:@"{TIFF}"];

                 //可交换图像文件
                 NSLog(@"Exif info:--%@",exifDic);
                 //地理位置信息
                 NSLog(@"GPS info:--%@",gpsDic);
                 //图像文件格式
                 NSLog(@"tiff info:--%@",tiffDic);
             }

以向图片元数据中写入Exif的kCGImagePropertyExifDateTimeOriginal为例。

1.先按照特定的格式创建一个日期对象:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"YYYY:MM:dd hh:mm:ss"];
NSString *now = [formatter stringFromDate:[NSDate date]];

2.将之前的exifDic中的对应字段值设为当前日期对象now:

[exifDic setValue:now forKey:(NSString*)kCGImagePropertyExifDateTimeOriginal];
[imageMetadata setValue:exifDic forKey:@"{Exif}"];

3.利用ALAssetsLibrary的writeImageToSavedPhotosAlbum: metadata: completionBlock方法写入并保存:

[library writeImageToSavedPhotosAlbum:[image CGImage] metadata:imageMetadata completionBlock:^(NSURL *assetURL, NSError *error) {
                     if (error == nil)
                         NSLog(@"metadata write success!");
                     else
                         NSLog(@"write error:%@",error.userInfo);
                 }];

这样,图片的创建时间就被写入并保存了,如果是对相册中已经存在的图片进行此写入操作,则其将被更改创建时间而另存。

如果你想写入中文或者自定义数据,可以考虑将数据写入到kCGImagePropertyExifUserComment中。

UserComment标签说明
标签号:0x9286;格式:undefined;描述:存储用户的注释,这个标签允许使用两字节的德字符或者 unicode,前8 个字节描述的是字符集,'JIS' 是日文 (著名的有 Kanji)。
'0x41,0x53,0x43,0x49,0x49,0x00,0x00,0x00':ASCII
'0x4a,0x49,0x53,0x00,0x00,0x00,0x00,0x00':JIS
'0x55,0x4e,0x49,0x43,0x4f,0x44,0x45,0x00':Unicode
'0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00':Undefined

UserComment写入的代码实现

NSString *userComment = @"你好,this is a test text for writing data in UserComment";
                 [exifDic setValue:userComment forKey:(NSString*)kCGImagePropertyExifUserComment];
                 [imageMetadata setValue:exifDic forKey:@"{Exif}"];
在 Java 中向图片写入元数据(如 EXIF 信息)通常需要使用支持图像元数据操作的库。Java 自带的图像处理功能较为基础,不直接支持 EXIF 数据读写,因此需要借助第三方库来实现。 ### 常用工具库 1. **TwelveMonkeys ImageIO** - TwelveMonkeys 是一个功能强大的图像处理库,扩展了 Java ImageIO 的功能,支持多种图像格式的元数据操作,包括 JPEG 的 EXIF IPTC 元数据。 - 使用该库可以读取写入图像的元数据,适用于需要在图片中嵌入拍摄时间、地理位置等信息的场景。 2. **metadata-extractor** - 该库主要用于读取图像的元数据,但结合其他工具(如 TwelveMonkeys)可以实现写入功能。 - 它支持多种格式的元数据解析,包括 EXIF、XMP IPTC 等。 3. **Apache Commons Imaging** - Apache Commons Imaging 提供了对图像元数据读写支持,适用于需要操作图像元数据的复杂场景。 - 该库支持多种图像格式,并允许修改保存图像的元数据。 ### 示例代码:使用 TwelveMonkeys 写入 EXIF 元数据 以下是一个使用 TwelveMonkeys 库向 JPEG 图像写入 EXIF 元数据的示例代码: ```java import com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriteParam; import com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriter; import com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriterSpi; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.stream.ImageOutputStream; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Iterator; public class ExifMetadataWriter { public static void main(String[] args) throws IOException { // 读取原始图片 File input = new File("input.jpg"); BufferedImage image = ImageIO.read(input); // 获取 JPEG 图像写入器 Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpeg"); ImageWriter writer = writers.next(); // 设置输出流 File output = new File("output.jpg"); ImageOutputStream ios = ImageIO.createImageOutputStream(output); writer.setOutput(ios); // 创建写入选项 ImageWriteParam param = new JPEGImageWriteParam(null); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(1.0f); // 不压缩 // 获取图像元数据 IIOMetadata metadata = writer.getDefaultImageMetadata(null, param); // 设置 EXIF 元数据 // 通过 XML 格式设置元数据 String exifXML = "<javax_imageio_jpeg_image_1.0>" + "<app1>" + "<tiffIFD>" + "<dateTime>2023:10:01 12:00:00</dateTime>" + "<latitude>39.9042</latitude>" + "<longitude>116.4074</longitude>" + "<altitude>100.0</altitude>" + "</tiffIFD>" + "</app1>" + "</javax_imageio_jpeg_image_1.0>"; metadata.mergeTree("javax_imageio_jpeg_image_1.0", metadata.getStandardTree("javax_imageio_jpeg_image_1.0")); // 写入图像及元数据 writer.write(null, new javax.imageio.IIOImage(image, null, metadata), param); // 关闭资源 ios.close(); writer.dispose(); } } ``` ### 说明 - 上述代码使用 TwelveMonkeys 提供的 `JPEGImageWriter` 类来写入 JPEG 图像的 EXIF 元数据。 - `mergeTree` 方法用于将新的元数据合并到现有的元数据中。 - `exifXML` 是一个 XML 格式的字符串,用于描述需要写入的 EXIF 信息,包括拍摄时间、纬度、经度海拔等。 ### Maven 依赖配置 在 `pom.xml` 中添加 TwelveMonkeys 的依赖: ```xml <dependency> <groupId>com.twelvemonkeys.imageio</groupId> <artifactId>imageio-jpeg</artifactId> <version>3.9.3</version> </dependency> ``` ### 注意事项 - 在操作图像元数据时,需确保图像格式支持元数据的写入,如 JPEG。 - 写入元数据可能会导致图像质量损失,因此建议在操作前备份原始图像。 - 使用 XML 格式设置元数据时,需遵循特定的格式规范,否则可能导致元数据无法正确写入。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值