第七章:提取元数据

元数据概览

大多数当前的数码相机在生成JPEG图像的时候,会把各种各样的信息片段嵌入到JPEG图像中,包括当前的日期时间、拍摄情况(例如,是否使用了闪光灯),照相机的设置(快门、光圈、景深),等等。领选的图像编辑软件Photoshop,也会把各种元数据片段嵌入到它制作的JPEG图像中,比如说作者、标题、版权提醒,等等。

由照相机嵌入的元数据的格式称为EXIF,它代表了“可交换图像文件格式”。欲了解更多关于EXIF的信息,请访问www.exif.org。Photoshop所用的格式由国际新闻通讯委员会(www.iptc.org)描述,通常把它写成IPTC

AspJpeg 1.4以后的版本可以利用OpenInfo方法和OpenInfoBinary方法,从JPEG图像中提取EXIF和IPTC元数据。两个方法的不同点就像Open方法和OpenBinary方法之间的不同点——前者从磁盘上打开一个源图像,后者从内存中打开一个源图像。

OpenInfo方法和OpenInfoBinary方法都能够返回一个Info对象的实例,它是很多InfoItem对象的集合,每个InfoItem方法代表了一个独立的EXIF或IPTC字段。该InfoItem方法支持以下属性:Name(字符串)、Value(字符串,默认属性)、Tag(整型数)和Description(字符串)。

以下代码示例从一个JPEG图像中提取并显示了所有的元数据。

VB Script:

<%
' Directory with images
Path = Server.MapPath("../images/photo.jpg")
Set Jpeg = Server.CreateObject("Persits.Jpeg")

' Open image for metadata exraction
Set Info = Jpeg.OpenInfo( Path )

' Display collection of items
For Each Item in Info
  Response.Write "<TR><TD>"
  Response.Write Item.Name & "</TD><TD>"
  Response.Write Item.Description & "</TD><TD>"
  Response.Write Item.Value & "</TD>"

  Response.Write "</TD></TR>"
Next
%>

C#

<script runat="server" LANGUAGE="C#">
void Page_Load(Object Source, EventArgs E)
{
IASPJpeg objJpeg;
objJpeg = new ASPJpeg();

// Compute path to source image
String strPath = Server.MapPath("../images/photo.jpg");

// Open source image for metadata exraction
IInfo objInfo = objJpeg.OpenInfo( strPath );

foreach( IInfoItem objItem in objInfo )
{
  TableRow objRow = new TableRow();

  TableCell objCell1 = new TableCell();
  objCell1.Controls.Add( new LiteralControl( objItem.Name ) );

  TableCell objCell2 = new TableCell();
  objCell2.Controls.Add(new LiteralControl(objItem.Description));

  TableCell objCell3 = new TableCell();
  objCell3.Controls.Add( 
    new LiteralControl( objItem.Value.ToString() ) );

  objRow.Cells.Add( objCell1 );
  objRow.Cells.Add( objCell2 );
  objRow.Cells.Add( objCell3 );
  objTable.Rows.Add( objRow );
}

}
</script>

点击以下链接以运行该代码示例:

http://localhost/aspjpeg/manual_07/07_metadata.asp

http://localhost/aspjpeg/manual_07/07_metadata.aspx

要想获得某个特定元数据字段的值,比如说相机制造商,你必须使用Info的默认Item属性,它接受字段名作为一个序列号。因为Item是它的默认属性,所以单词“Item”可以省略掉了。在C#中,必须使用方括号。以下代码片段获得了相机的制造商信息,并把它分配到一个字符串变量中:

VB Script:

Dim s
s = Info("Make")

C#:

String s = Info["Make"].Value;

所有有效的EXIF字段和IPTC字段名列罗列在下面。

EXIF项列表

下表列出了所有的有效的EXIF字段以及它们的描述。大多数现实世界中的图像如果有EXIF信息的话,也只包含这些项目的一个小小的子集。注意,除了生成图像以及照相机设置信息之外,EXIF还提供了GPS相关的数据。

名称描述
NewSubfileType档案类型
ImageWidth图像宽度
ImageLength图像高度
BitsPerSample每个成分的位数
Compression压缩方案
PhotometricInterpretation像素组成
ImageDescription图像标题
Make图像输入设备的制造商
Model图像输入设备的模式
StripOffsets图像数据定位
Orientation图像的方向
SamplesPerPixel成分数
RowsPerStrip每条行数
StripByteCounts每个压缩带的字节数
XResolution宽度方向上的图像分辨率
YResolution高度方向上的图像分辨率
PlanarConfiguration图像数据排列
ResolutionUnitX和Y分辨率的单位
TransferFunction传输函数
Software使用的软件
DateTime文件更改的日期和时间
Artist创建图像的人
HostComputer使用中的计算机和/或操作系统
WhitePoint白点色度
PrimaryChromaticities色度的初选
JPEGInterchangeFormat对JPEG SOI的偏移
JPEGInterchangeFormatLengthJPEG数据字节
YCbCrCoefficients颜色空间变换矩阵系数
YCbCrSubSamplingY到C的采样率
YCbCrPositioningY和C的和定位
ReferenceBlackWhite一对黑白参考值
Copyright版权持有人
ExifTagEXIF IFD指针
GPSTagGPS信息IFD指针
ExposureTime曝光时间
FNumberF数
ExposureProgram曝光程序
SpectralSensitivity光谱灵敏度
ISOSpeedRatingsISO速度等级
OECF光电系数
ExifVersionExif版本
DateTimeOriginal产生原始图像的日期和时间
DateTimeDigitized图像制作数字数据的日期和时间
ComponentsConfiguration各颜色成分的含义
CompressedBitsPerPixel图像压缩模式
ShutterSpeedValue快门速度
ApertureValue光圈
BrightnessValue亮度
ExposureBiasValue曝光偏差
MaxApertureValue最大透镜光圈
SubjectDistance主题距离
MeteringMode计量模式
LightSource光源
Flash闪光灯
FocalLength透镜焦距
SubjectArea主题区域
MakerNote制造商说明
UserComment用户评论
SubSecTime日期时间”“分”“秒”
SubSecTimeOriginal原始日期时间“分”“秒”
SubSecTimeDigitized数字化日期时间“分”“秒”
FlashpixVersion支持位图的版本
ColorSpace颜色空间信息
PixelXDimension有效图像宽度
PixelYDimension有效图像高度
RelatedSoundFile相关音频文件
InteroperabilityTag互操作性的IFD指针
FlashEnergy闪光灯能量
SpatialFrequencyResponse空间频率响应
FocalPlaneXResolution焦平面×分辨率
FocalPlaneYResolution焦平面分辨率
FocalPlaneResolutionUnit焦平面分辨率单元
SubjectLocation主题定位
ExposureIndex曝光指数
SensingMethod传感方法
FileSource文件来源
SceneType场景类型
CFAPatternCFA模式
CustomRendered自定义图像处理
ExposureMode曝光模式
WhiteBalance白平衡
DigitalZoomRatio数字变焦比
FocalLengthIn35mmFilm35毫米胶片焦距
SceneCaptureType场景捕捉类型
GainControl增益控制
Contrast对比度
Saturation饱和度
Sharpness锐度
DeviceSettingDescription设备设置描述
SubjectDistanceRange主题距离范围
ImageUniqueID独一无二的形象标识
RelatedImageFileFormat图像文件的文件格式
RelatedImageWidth图像宽度
RelatedImageLength图像高度
GPSVersionIDGPS标签版本
GPSLatitudeRef南北纬度
GPSLatitude纬度
GPSLongitudeRef东西经度
GPSLongitude经度
GPSAltitudeRef海拔高度基准
GPSAltitude海拔高度
GPSTimeStampGPS时间(原子钟)
GPSSatellites用于测量的GPS卫星
GPSStatusGPS接收器状态
GPSMeasureModeGPS测量模式
GPSDOP测量精度
GPSSpeedRef速度单位
GPSSpeedGPS接收器的速度
GPSTrackRef运动方向参考
GPSTrack运动方向
GPSImgDirectionRef图像方向参考
GPSImgDirection图像方向
GPSMapDatum大地测量数据
GPSDestLatitudeRef目的地纬度参考
GPSDestLatitude目的地纬度
GPSDestLongitudeRef目的地的经度参考
GPSDestLongitude目的地的经度
GPSDestBearingRef目的地方位参考
GPSDestBearing目的地方位
GPSDestDistanceRef到目的地的距离参考
GPSDestDistance到目的地的距离
GPSProcessingMethodGPS处理方法的名称
GPSAreaInformationGPS区域的名称
GPSDateStampGPS日期
GPSDifferentialGPS微分修正
WinTitle窗口资源管理器标题
WinAuthor窗口资源管理器作者
WinSubject窗口资源管理器主题
WinComments窗口资源管理器注释
WinKeywords窗口资源管理器关键词
LensSpecification焦距和光圈范围
PanasonicTitle松下标题
PanasonicTitle2松下标题2
PrintIM打印图像匹配
CameraOwnerName相机的拥有者
BodySerialNumber相机机身序列号
LensMake镜头制造商
LensModel透镜模型
Gamma伽玛系数值
RatingWindows用的标签
TimeZoneOffset相对于格林威治时间的相机钟的时区
ExposureIndex相机曝光指数设置

除了预定义的字段,一些图像可能包含自定义字段,在EXIF说明书中没有描述。自定义字段名具有Tag#nnn的格式,其中nnn是一个十进制数,比如说,Tag#37388

IPTC项目列表

以下IPTC字段受AspJpeg支持:

  • IptcByline
  • IptcBylineTitle
  • IptcCredits
  • IptcSource
  • IptcObjectName
  • IptcDateCreated
  • IptcCity
  • IptcState
  • IptcCountry
  • IptcOriginalTransmissionReference
  • IptcCopyrightNotice
  • IptcCaption
  • IptcCaptionWriter
  • IptcHeadline
  • IptcSpecialInstructions
  • IptcCategory
  • IptcSupplementalCategories
  • IptcUrgency
  • IptcKeywords
  • IptcTimeCreated
  • IptcDigitalCreationDate
  • IptcDigitalCreationTime
  • IptcOriginatingProgram
  • IptcProgramVersion
  • IptcUno
  • IptcEditStatus
  • IptcFixtureIdentifier
  • IptcReleaseDate
  • IptcReleaseTime
  • IptcObjectCycle
  • IptcImageNotes
  • IptcTextSaved
  • IptcCustom1
  • IptcCustom2
  • IptcCustom3
  • IptcCustom4
  • IptcCustom5
  • IptcCustom6
  • IptcCustom7
  • IptcCustom8
  • IptcCustom9
  • IptcCustom10
  • IptcCustom11
  • IptcCustom12
  • IptcCustom13
  • IptcCustom14
  • IptcCustom15
  • IptcCustom16
  • IptcCustom17
  • IptcCustom18
  • IptcCustom19
  • IptcCustom20
  • IptcImageURL
  • IptcCopyrighted
  • IptcXMP

注意:IptcKeywords字段可能在Info集合中出现在多次。在AspJpeg的2.0版中引入了IptcCopyrighted,它是一个True/False值。在v 2.7.0.5版中引入了IptcXMP,在本章后面讲解了它。

TIFF支持

如果被打开的图像是一个TIFF图像,则Info集合将包含一个特殊的字段,名称是“TIffPages”,它包含了该TIFF文件中的图像的页数。这个值可以用来遍历多页TIFF中的所有的图像。要想打开序列号大于1的图像,必须使用属性TiffIndex,如下所示:

<%
path = "c:\path\multipage.tif"
Set Info = jpeg.OpenInfo(path)
nPages = Info("TiffPages")

For i = 1 To nPages
  jpeg.TiffIndex = i
  jpeg.Open path
  jpeg.Save "c:\path\" & i & ".jpg"
Next
%>

元数据保留

如果被打开的图像是一个TIFF图像,则Info集合将包含一个特殊的字段,名称是“TIffPages”,它包含了该TIFF文件中的图像的页数。这个值可以用来遍历多页TIFF中的所有的图像。要想打开序列号大于1的图像,必须使用属性TiffIndex,如下所示:

<%
path = "c:\path\multipage.tif"
Set Info = jpeg.OpenInfo(path)
nPages = Info("TiffPages")

For i = 1 To nPages
  jpeg.TiffIndex = i
  jpeg.Open path
  jpeg.Save "c:\path\" & i & ".jpg"
Next
%>

编辑元数据

从v2.0版以来,利用AddMetadataItem方法,AspJpeg可以在一个图像中添加或替换IPTC值。这个方法接受两个参数:一个来自上面表格中所列出的IPTC标签,还有一个在该标签下要插入的字符串值。如果需要的话,这个方法可以被调用多次。要想使用AddMdtadataItem方法,在打开图像之前,前面章节描述的属性PreserveMetadata必须设置为True

<%
Set Jpeg = Server.CreateObject("Persits.Jpeg")
Jpeg.PreserveMetadata = True
Jpeg.Open Path
Jpeg.AddMetadataItem "IptcCaption", "New York City Skyline"
Jpeg.AddMetadataItem "IptcCaptionWriter", "John Smith"
...
Jpeg.Save ...
%>

所有的IPTC字段都是字符串,只有一个例外:在v2.0版中引入的IptcCopyrighted标签是一个开关标识。使用字符串“True”设置这个标识,或者使用字符串“False”以清除它。

从v2.0.0.1版以来,你可以利用特殊标签IptcKeywordsAdd向一个图像添加多个IptcKeyword条目。与“IptcKeywords”不同,这个方法会添加一个新的关键词条目,而不是替换掉一个已有的关键词条目。举个例子,代码片段

Jpeg.AddMetadataItem "IptcKeywordsAdd", "Art"
Jpeg.AddMetadataItem "IptcKeywordsAdd", "Portrait"

向一个图像添加了两个关键词条目“Art”和“Portrait”,而片段

Jpeg.AddMetadataItem "IptcKeywords", "Art"
Jpeg.AddMetadataItem "IptcKeywords", "Portrait"

只添加了一个条目“Portrait”(“Art”被覆盖掉了)。

在v2.1版中,还有一个特殊的标签,IptcKeywordsRemove,它移除了所有的关键词条目。在以前的版本中,它不能从图像中彻底移除所有已有的关键词。只能覆盖(或清除)最后的关键词条目,与此同时其它都完整保留。可以用如下方式使用IptcKeywordsRemove标签:

Jpeg.AddMetadataItem "IptcKeywordsRemove", ""

Adobe XMP支持

除了上前所描述的EXIF信息和IPTC信息,JPEG图像通常包含基于Adobe的可扩展的元数据平台(XMP)规范文档的元数据。XMP通常使用XML格式。

典型的嵌入在一个JPEG图像中的XMP数据可能看起来如下所示(为了简洁起见,XML代码的右边被缩截了):

从v2.7.0.5版本以来,AspJpeg可以利用Info集合和AddMetadataItem方法,在它的条目中读取并设置XMP元数据,就像它是一个普通的IPTC标签。该应用程序的开发员的责任是执行一个XML解析,以读取并设置多种XMP元数据的组成。在传统的ASP和.NET中的XmlDocument对象中,可以使用Microsoft.XMLDOM对象很轻松地实施XML处理。

对于可以通过Info集合访问的IptcXML项目,你必须在调用Jpeg.Open方法或Jpeg.OpenBinary方法之前,把属性Jpeg.PreserveMetadata设置为True。

以下代码示例从一个图像中读取了XMP数据,改变了dc:creator项目的值,然后把修改过的XML字符串插回图像。.NET代码片段要求导入了System.xml命名空间。

VB Script:

Set Jpeg = Server.CreateObject("Persits.Jpeg")
Jpeg.PreserveMetadata = true
Path = "c:\path\birds.jpg"
Jpeg.Open Path
Set Info = Jpeg.OpenInfo( Path )

Set XmlDom = Server.CreateObject("Microsoft.XMLDOM")
XmlDom.Async = False ' need synchronous operation

XmlDom.LoadXml( Info("IptcXMP") )

Set XmlNode = XmlDom.DocumentElement.SelectSingleNode ("rdf:RDF/rdf:Description/dc:creator/rdf:Seq/rdf:li")
XmlNode.text = "John Smith"

Jpeg.AddMetadataItem "IptcXMP", XmlDom.xml

Jpeg.SaveUnique "c:\path\out.jpg"

C#:

IASPJpeg objJpeg = new ASPJpeg();
objJpeg.PreserveMetadata = 1;
string strPath = @"c:\path\birds.jpg";
objJpeg.Open( strPath );
IInfo objInfo = objJpeg.OpenInfo( strPath );

XmlDocument XmlDom = new XmlDocument();
XmlDom.LoadXml( objInfo["IptcXMP"].Value.ToString() );

XmlNamespaceManager objMgr = new XmlNamespaceManager(XmlDom.NameTable);
objMgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
objMgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
objMgr.AddNamespace("x", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");

XmlNode node = XmlDom.DocumentElement.SelectSingleNode ("rdf:RDF/rdf:Description/dc:creator/rdf:Seq/rdf:li", objMgr);
node.InnerText = "John Smith";

objJpeg.AddMetadataItem( "IptcXMP", XmlDom.InnerXml );

objJpeg.SaveUnique( @"c:\mpath\out.jpg" );

以下代码片段把一个新的关键词添加到dc:subject列表上:

VB Script:

...
Set XmlNode = XmlDom.DocumentElement.SelectSingleNode ("rdf:RDF/rdf:Description/dc:subject/rdf:Bag")
Set NewNode = XmlDom.createNode( 1, "rdf:li", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
NewNode.text = "John Smith" & chrw( &H0416 )
XmlNode.AppendChild( NewNode )
...

C#:

...
XmlNode XmlNode = XmlDom.DocumentElement.SelectSingleNode("rdf:RDF/rdf:Description/dc:subject/rdf:Bag", objMgr);
XmlNode NewNode = XmlDom.CreateNode( XmlNodeType.Element, "rdf:li", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
NewNode.InnerText = "John Smith";
XmlNode.AppendChild( NewNode );
...

如果你喜欢这篇文章,敬请给站长打赏↑

除特别注明外,本站所有文章均为本站站长原译,转载请注明出处。