数码照片的文件高级信息获取
////调用
string strfile = "fffff.jpg";//文件名
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(strfile);
exif.exifextractor er = new exif.exifextractor(ref bmp, "\n");
string a = strfile + "</br>";
foreach (exif.pair pr in er)
{
a += pr.first + ":" + pr.second + "<br />";
}
div1.InnerHtml = a;
--------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
namespace exif
{
/// <summary>
/// summary description for translation.
/// </summary>
public class translation : Hashtable
{
/// <summary>
///
/// </summary>
public translation()
{
this.Add(0x8769, "exif ifd_Exif 子IFD的偏移量");//Exif 子IFD的偏移量
this.Add(0x8825, "gps ifd");//GPSInfo
this.Add(0xfe, "new subfile type");//NewSubfileType
this.Add(0xff, "subfile type");//SubfileType
//表示缩略图的大小.
this.Add(0x100, "image width_缩略图的大小");
this.Add(0x101, "image height_缩略图的大小");
this.Add(0x102, "bits per sample_当图像格式没有经过压缩, 这个值表示每像素的比特位的数目");//当图像格式没有经过压缩, 这个值表示每像素的比特位的数目. 通常这个值是 '8,8,8'
this.Add(0x103, "compression_压缩的方式");//代表压缩的方式. '1' 表示非压缩, '6' 表示JPEG 压缩格式.
this.Add(0x106, "photometric interp_图像数据组件的色彩空间");//表示图像数据组件的色彩空间. '1' 意味着单色, '2'表示 RGB, '6' 表示 YCbCr.
this.Add(0x107, "thresh holding");
this.Add(0x108, "cell width");
this.Add(0x109, "cell height");
this.Add(0x10a, "fill order");
this.Add(0x10d, "document name");
this.Add(0x10e, "image description_描述图像");//用来描述图像. 双字节的字符码不能使用, 如 中文/韩文/日文.
this.Add(0x10f, "equip make_数字相机的制造商");//表示数字相机的制造商. 在 Exif 标准中, 这个标签是可选的, 但是在DCF中它是必需的.
this.Add(0x110, "equip model_数字相机的模块代码");//表示数字相机的模块代码. 在 Exif 标准中, 这个标签是可选的, 但在DCF中它也是必需的.
this.Add(0x111, "strip offsets_图像数据的偏移量");//如果图像格式没有经过压缩, 这个值表示的是到图像数据的偏移量. 在图像数据被分割的 情况下它有多个值.
//当拍照时, 相机相对于场景的方向. 在右边表示的是'0th row' 以及 '0th column' 在视觉位置上的关系.
//Value|0th Row |0th Column
//1 |top |left side
//2 |top |right side
//3 |bottom |right side
//4 |bottom |left side
//5 |left side |top
//6 |right side|top
//7 |right side|bottom
//8 |left side |bottom
this.Add(0x112, "orientation_相机相对于场景的方向");
this.Add(0x115, "samples perpixel_每个像素中存储的组件数目");//如果图像格式没有经过压缩, 这个值表示每个像素中存储的组件数目. 在彩色图像中, 此值为 '3'.
this.Add(0x116, "rows per strip_每条数据带存储了多少行数据");//如果图像格式没有经过压缩 并且 图像被分割存储, 这个值表示每条数据带存储了多少行数据 . 如果图像没有被分割, 它与ImageLength(0x0101)同值.
this.Add(0x117, "strip bytes count_每条数据带使用了多少字节的 数据 且 有多个值");//如果图像格式没有经过压缩 并且 图像被分割存储, 这个值表示每条数据带使用了多少字节的 数据 且 有多个值. 如果图像没有被分割, 它只有一个且表示为图像的所有数据的大小.
this.Add(0x118, "min sample value");
this.Add(0x119, "max sample value");
//图像的 显示/打印 分辨率. 缺省值是 1/72英寸, 但是它没有意义因为个人PC在 显示/打印 图像的时候不使用这个值.
this.Add(0x11a, "x resolution_图像的 显示/打印 分辨率");
this.Add(0x11b, "y resolution_图像的 显示/打印 分辨率");
this.Add(0x11c, "planar config_YCbCr数据的字节对齐顺序");//如果图像格式是非压缩YCbCr的, 这个值表示YCbCr数据的字节对齐顺序. '1', 表示Y/Cb/Cr值是一个 chunky format, 对于每个子采样像素都是连续的. '2', 则表示Y/Cb/Cr 值被分割存储在 Y plane/Cb plane/Cr plane 格式中.
this.Add(0x11d, "page name");
this.Add(0x11e, "x position");
this.Add(0x11f, "y position");
this.Add(0x120, "free offset");
this.Add(0x121, "free byte counts");
this.Add(0x122, "gray response unit");
this.Add(0x123, "gray response curve");
this.Add(0x124, "t4 option");
this.Add(0x125, "t6 option");
this.Add(0x128, "resolution unit_分辨率单位");//XResolution(0x011a)/YResolution(0x011b)的单位. '1' 表示没有单位, '2' 意味着英寸, '3' 表示厘米. 缺省值是 '2'(英寸).
this.Add(0x129, "page number");
this.Add(0x12d, "transfer funcition");
this.Add(0x131, "software used_显示固件的版本号");//显示固件的版本号(数字相机的内部控制软件).
this.Add(0x132, "date time_图像最后一次被修改时的日期/时间");//图像最后一次被修改时的日期/时间. 日期的格式是 "YYYY:MM:DD HH:MM:SS"+0x00, 一共 20个字节. 如果没有设置时钟或者数字相机没有时钟, 则这个域是用空格来填充. 通常, 它和DateTimeOriginal(0x9003)具有相同的值
this.Add(0x13b, "artist");
this.Add(0x13c, "host computer");
this.Add(0x13d, "predictor");
this.Add(0x13e, "white point_定义图像白点");//定义图像白点(white point/白点:在彩色分色、照相或摄影时作为色彩平衡测量用途的参考点) 的色度(chromaticity). 如果图像是用CIE标准照度 D65(著名的是 '光线/daylight'的国际标准), 这个值是 '3127/10000,3290/10000'.
this.Add(0x13f, "primary chromaticities_定义图像的原始色度");//定义图像的原始色度. 如果图像使用 CCIR 推荐 709原始色度, 则这个值是 '640/1000,330/1000,300/1000,600/1000,150/1000,0/1000'.
this.Add(0x140, "colormap");
this.Add(0x141, "halftone hints");
this.Add(0x142, "tile width");
this.Add(0x143, "tile length");
this.Add(0x144, "tile offset");
this.Add(0x145, "tile bytecounts");
this.Add(0x14c, "inkset");
this.Add(0x14d, "ink names");
this.Add(0x14e, "number of inks");
this.Add(0x150, "dot range");
this.Add(0x151, "target printer");
this.Add(0x152, "extra samples");
this.Add(0x153, "sample format");
this.Add(0x154, "s min sample value");
this.Add(0x155, "s max sample value");
this.Add(0x156, "transfer range");
this.Add(0x200, "jpeg proc_照片的拍摄模式");//表示照片的拍摄模式. 第一个值的意思是 0=正常, 1=未知, 2=快速, 3=全景. 第二个值意思是序列号, 第三个值表示全景的方向 1=从左到右, 2=从右到左, 3=从下到上, 4=从上到下.
this.Add(0x201, "jpeg interformat_到 JPEG 数据的偏移量");//当图像格式是JPEG时, 这个值表示到 JPEG 数据的偏移量.
this.Add(0x202, "jpeg interlength_JPEG 图像的数据大小");//当图像格式是JPEG时, 表示JPEG 图像的数据大小.
this.Add(0x203, "jpeg restartinterval");
this.Add(0x205, "jpeg losslesspredictors");
this.Add(0x206, "jpeg pointtransforms");
this.Add(0x207, "jpeg qtables_固件版本");//表示固件版本.
this.Add(0x208, "jpeg dctables_包含 ASCII 格式的数据");//包含 ASCII 格式的数据如 [PictureInfo]. 它跟老的奥林帕斯数码相机(没有采用Exif 数据格式, 如C1400/C820/D620/D340等)采用相同的数据格式.
this.Add(0x209, "CameraID 的数据");//包含CameraID 的数据, 用户可以使用客户端工具来改变它的内容
this.Add(0x211, "ycbcr coefficients_转换成 RGB格式的一个常量");//当图像的格式是 YCbCr(JPEG的格式), 这个值表示转换成 RGB格式的一个常量. 通常, 这个值是'0.299/0.587/0.114'.
this.Add(0x212, "ycbcr subsampling_有多少个色度数据被采样了");//当图像格式是YCbCr时 并且 使用子采样(色度数据的剪切值, 所有的数字相机都使用)时, 这个值表示有多少个色度数据被采样了. 首先第一个值表示水平的, 下一个值表示垂直的 采样率.
this.Add(0x213, "ycbcr positioning_定义了被采样的像素阵列的色度采样点");//当图像格式是YCbCr时 并且 使用子采样(色度数据的剪切值, 所有的数字相机都使用)时, 这个值定义了被采样的像素阵列的色度采样点. '1' 表示像素阵列的中心, '2' 表示基准点(0,0).
this.Add(0x214, "ref black white_黑点/白点的参考值");//表示黑点/白点的参考值. 在 YCbCr 格式的情况下, 前两个表示了Y的黑/白, 下两个是 Cb, 最后两个是 Cr. 在 RGB 的情况下, 前两个表示R的黑/白, 下两个是 G, 最后两个是 B.
this.Add(0x8773, "icc profile");
this.Add(0x301, "gamma");
this.Add(0x302, "icc profile descriptor");
this.Add(0x303, "srgb renderingintent");
this.Add(0x320, "image title");
this.Add(0x8298, "copyright_版权信息");//表示版权信息
this.Add(0x5001, "resolution x unit");
this.Add(0x5002, "resolution y unit");
this.Add(0x5003, "resolution x lengthunit");
this.Add(0x5004, "resolution y lengthunit");
this.Add(0x5005, "print flags");
this.Add(0x5006, "print flags version");
this.Add(0x5007, "print flags crop");
this.Add(0x5008, "print flags bleed width");
this.Add(0x5009, "print flags bleed width scale");
this.Add(0x500a, "halftone lpi");
this.Add(0x500b, "halftone lpiunit");
this.Add(0x500c, "halftone degree");
this.Add(0x500d, "halftone shape");
this.Add(0x500e, "halftone misc");
this.Add(0x500f, "halftone screen");
this.Add(0x5010, "jpeg quality");
this.Add(0x5011, "grid size");
this.Add(0x5012, "thumbnail format");
this.Add(0x5013, "thumbnail width");
this.Add(0x5014, "thumbnail height");
this.Add(0x5015, "thumbnail colordepth");
this.Add(0x5016, "thumbnail planes");
this.Add(0x5017, "thumbnail rawbytes");
this.Add(0x5018, "thumbnail size");
this.Add(0x5019, "thumbnail compressedsize");
this.Add(0x501a, "color transfer function");
this.Add(0x501b, "thumbnail data");
this.Add(0x5020, "thumbnail imagewidth");
this.Add(0x502, "thumbnail imageheight");
this.Add(0x5022, "thumbnail bitspersample");
this.Add(0x5023, "thumbnail compression");
this.Add(0x5024, "thumbnail photometricinterp");
this.Add(0x5025, "thumbnail imagedescription");
this.Add(0x5026, "thumbnail equipmake");
this.Add(0x5027, "thumbnail equipmodel");
this.Add(0x5028, "thumbnail stripoffsets");
this.Add(0x5029, "thumbnail orientation");
this.Add(0x502a, "thumbnail samplesperpixel");
this.Add(0x502b, "thumbnail rowsperstrip");
this.Add(0x502c, "thumbnail stripbytescount");
this.Add(0x502d, "thumbnail resolutionx");
this.Add(0x502e, "thumbnail resolutiony");
this.Add(0x502f, "thumbnail planarconfig");
this.Add(0x5030, "thumbnail resolutionunit");
this.Add(0x5031, "thumbnail transferfunction");
this.Add(0x5032, "thumbnail softwareused");
this.Add(0x5033, "thumbnail datetime");
this.Add(0x5034, "thumbnail artist");
this.Add(0x5035, "thumbnail whitepoint");
this.Add(0x5036, "thumbnail primarychromaticities");
this.Add(0x5037, "thumbnail ycbcrcoefficients");
this.Add(0x5038, "thumbnail ycbcrsubsampling");
this.Add(0x5039, "thumbnail ycbcrpositioning");
this.Add(0x503a, "thumbnail refblackwhite");
this.Add(0x503b, "thumbnail copyright");
this.Add(0x5090, "luminance table");
this.Add(0x5091, "chrominance table");
this.Add(0x5100, "frame delay");
this.Add(0x5101, "loop count");
this.Add(0x5110, "pixel unit");
this.Add(0x5111, "pixel perunit x");
this.Add(0x5112, "pixel perunit y");
this.Add(0x5113, "palette histogram");
this.Add(0x829a, "exposure time_曝光时间");//曝光时间 (快门速度的倒数). 单位是秒.
this.Add(0x829d, "f-number_拍照时的光圈");//拍照时的光圈F-number(F-stop).
this.Add(0x8822, "exposure prog_拍照时相机使用的曝光程序");//拍照时相机使用的曝光程序. '1' 表示手动曝光, '2' 表示正常程序曝光, '3' 表示光圈优先曝光, '4' 表示快门优先曝光, '5' 表示创意程序(慢速程序), '6' 表示动作程序(高速程序), '7'表示 肖像模式, '8' 表示风景模式.
this.Add(0x8824, "spectral sense");
this.Add(0x8827, "iso speed_CCD 的感光度");//CCD 的感光度, 等效于 Ag-Hr 胶片的速率.
this.Add(0x8828, "oecf");
this.Add(0x9000, "ver_Exif 的版本号");//Exif 的版本号. 用4个ASCII字符来存储. 如果图片是基于Exif V2.1的, 这个值是 "0210". 因为它不是一个用NULL(0x00)来终结的字符串,所以这里的类型是 'undefined'.
this.Add(0x9003, "dtorig_照片在被拍下来的日期/时间");//照片在被拍下来的日期/时间. 使用用户的软件是不能被修改这个值的. 日期的格式是 "YYYY:MM:DD HH:MM:SS"+0x00, 一共占用20个字节. 如果数字相机没有设置时钟或者 数字相机没有时钟, 这个域使用空格来填充. 在Exif标准中, 这个标签是可选的, 但是在 DCF中是必需的.
this.Add(0x9004, "dtdigitized_照片被数字化时的日期/时间");//照片被数字化时的日期/时间. 通常, 它与DateTimeOriginal(0x9003)具有相同的值. 数据格式是 "YYYY:MM:DD HH:MM:SS"+0x00, 一共占用20个字节. 如果数字相机没有设置时钟或者 数字相机没有时钟, 这个域使用空格来填充. 在Exif标准中, 这个标签是可选的, 但是在 DCF中是必需的.
this.Add(0x9101, "compconfig_像素数据的顺序");//表示的是像素数据的顺序. 大多数情况下RGB格式使用 '0x04,0x05,0x06,0x00' 而YCbCr 格式使用 '0x01,0x02,0x03,0x00'. 0x00:并不存在, 其他的对应关系为 0x01:Y, 0x02:Cb, 0x03:Cr, 0x04:Red, 0x05:Green, 0x06:Bllue.
this.Add(0x9102, "compbpp_平均压缩率");//JPEG (粗略的估计)的平均压缩率.
this.Add(0x9201, "shutter speed_出的快门速度");//用APEX表示出的快门速度. 为了转换成原始的 'Shutter Speed'; 则先要计算2的ShutterSpeedValue次幂, 然后求倒数. 例如, 如果 ShutterSpeedValue 是 '4', 快门速度则是1/(24)=1/16秒.
this.Add(0x9202, "aperture_拍照时镜头的光圈");//拍照时镜头的光圈. 单位是 APEX. 为了转换成普通的 F-number(F-stop), 则要先计算出根号2 2 (=1.4142)的ApertureValue次幂. 例如, 如果ApertureValue 是 '5', F-number 就等于1.41425 = F5.6.
this.Add(0x9203, "brightness_被拍摄对象的明度");//被拍摄对象的明度, 单位是 APEX. 为了从BrigtnessValue(Bv)计算出曝光量(Ev), 你必须加上 SensitivityValue(Sv). Ev=Bv+Sv Sv=log2(ISOSpeedRating/3.125) ISO100:Sv=5, ISO200:Sv=6, ISO400:Sv=7, ISO125:Sv=5.32.
this.Add(0x9204, "exposure bias_照片拍摄时的曝光补偿");//照片拍摄时的曝光补偿. 单位是APEX(EV).
this.Add(0x9205, "maxaperture_镜头的最大光圈值");//镜头的最大光圈值. 你可以通过计算根号2的MaxApertureValue次幂来转换成普通的光圈 F-number (跟ApertureValue:0x9202的处理过程一样).
this.Add(0x9206, "subjectdist_到焦点的距离");//到焦点的距离, 单位是米.
this.Add(0x9207, "metering mode_曝光的测光方法");//曝光的测光方法. '0' 表示未知, '1' 为平均测光, '2' 为中央重点测光, '3' 是点测光, '4' 是多点测光, '5' 是多区域测光, '6' 部分测光, '255' 则是其他.
this.Add(0x9208, "lightsource_光源, 实际上是表示白平衡设置");//光源, 实际上是表示白平衡设置. '0' 意味着未知, '1'是日光, '2'是荧光灯, '3' 白炽灯(钨丝), '10' 闪光灯, '17' 标准光A, '18' 标准光B, '19' 标准光C, '20' D55, '21' D65, '22' D75, '255' 为其他.
this.Add(0x9209, "flash_闪光灯");//'0' 表示闪光灯没有闪光, '1' 表示闪光灯闪光, '5' 表示闪光但没有检测反射光, '7' 表示闪光且检测了反射光.
this.Add(0x920a, "focallength_拍摄照片时的镜头的焦距长度");//拍摄照片时的镜头的焦距长度. 单位是毫米.
this.Add(0x927c, "_maker note制造商的内部数据");//制造商的内部数据. 一些制造商如 Olympus/Nikon/Sanyo 等在这个区域中使用IFD 格式的数据.
//存储用户的注释. 这个标签允许使用两字节的德字符或者 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
this.Add(0x9286, "user comment_存储用户的注释");
//一些数字相机每秒能拍摄 2~30 张照片, 但是DateTime/DateTimeOriginal/DateTimeDigitized 标签只能记录到秒单位的时间. SubsecTime 标签就是用来记录秒后面的数据(微秒).
//例如, DateTimeOriginal = "1996:09:01 09:15:30", SubSecTimeOriginal = "130", 合并起来的原始的拍摄 时间就是 "1996:09:01 09:15:30.130"
this.Add(0x9290, "dtsubsec_拍摄微秒时间");
this.Add(0x9291, "dtorigss_拍摄微秒时间");
this.Add(0x9292, "dtdigss_拍摄微秒时间");
this.Add(0xa000, "fpxver_存储FlashPix 的版本信息");//存储FlashPix 的版本信息. 如果图像数据是基于 FlashPix formar Ver.1.0, 则这个值为 "0100". 因为它不是一个用NULL(0x00)来终结的字符串,所以这里的类型是 'undefined'.
this.Add(0xa001, "colorspace_定义色彩空间");//定义色彩空间. DCF 图像必须使用 sRGB 色彩空间因此这个值总是 '1'. 如果这个照片使用了 其他的色彩空间, 这个值是 '65535':未校准(Uncalibrated).
//主图像的尺寸大小.
this.Add(0xa002, "pixxdim_主图像的尺寸大小Width");//ExifImageWidth
this.Add(0xa003, "pixydim_主图像的尺寸大小Height");//ExifImageHeight
this.Add(0xa004, "relatedwav_音频数据的名字");//如果数字相机能够纪录图像的音频数据, 则表示音频数据的名字.
this.Add(0xa005, "interop_扩展");//表示这是一个扩展"ExifR98", 细节未知. 这个值经常是IFD格式的数据. 当前这儿有两个 目录项, 第一个是 Tag0x0001, 值是"R98", 下一个是 Tag0x0002, 它的值为 "0100".
this.Add(0xa20b, "flashenergy");
this.Add(0xa20c, "spatialfr");
//表示CCD的像素密度. 如果你的相机是百万像素的并且是用低分辨率(如VGA模式) 来拍摄照片, 这个值可以通过照片的分辨率来重新采样. 在这种情况下, FocalPlaneResolution 就不是CCD的实际的分辨率.
this.Add(0xa20e, "focalxres_CCD的像素密度");
this.Add(0xa20f, "focalyres_CCD的像素密度");
//FocalPlaneXResoluton/FocalPlaneYResolution的单位. '1' 表示没有单位, '2'是英寸inch, '3' 表示厘米.
//注意:一些Fujifilm的数码相机(如.FX2700,FX2900,Finepix4700Z/40i 等) 使用的值是 '3' 所以它的单位一定是 '厘米' , 但是它们的分辨率单位就变成'8.3mm?'(1/3in.?). 这是Fuji 的 BUG? 从Finepix4900Z 开始这个值就使用 '2' 了但仍然跟实际的值不吻合.
this.Add(0xa210, "focalresunit_FocalPlaneXResoluton/FocalPlaneYResolution的单位");
this.Add(0xa214, "subject loc");
this.Add(0xa215, "exposure index");//跟ISOSpeedRatings(0x8827)一样但是数据类型是 unsigned rational. 只有Kodak的数字相机使用 这个标签来替代 ISOSpeedRating, 我不知道这是为什么(历史原因?).
this.Add(0xa217, "sensing method_图像传感器单元的类型");//表示图像传感器单元的类型. '2' 意味着这是一个芯片颜色区域传感器, 几乎所有的数字相机都 使用这个类型.
this.Add(0xa300, "filesource_显示图像来源");//显示图像来源. 值 '0x03' 表示图像源是数字定格相机.
this.Add(0xa301, "scenetype_拍摄场景的类型");//表示拍摄场景的类型. 值 '0x01' 表示图像是通过相机直接拍摄出来的.
//表示色彩过滤阵列(CFA) 几何模式.
//长度类型意义
//2 shortHorizontal repeat pixel unit = n
//2 shortVertical repeat pixel unit = m
//1 byteCFA value[0,0]
//: : :
//1 byteCFA value[n-1,0]
//1 byteCFA value[0,1]
//: : :
//1 byteCFA value[n-1,m-1]
//色彩过滤和CFA值之间的关系.
//Filter ColorRedGreenBlueCyanMagentaYellowWhite
//CFA value 01 2 3 4 5 6
//RG例如, 普通的 RGB 过滤器使用左表的副本, 这个值是 '0x0002,0x0002,0x00,0x01,0x01,0x02'.
//GB
this.Add(0xa302, "cfapattern_色彩过滤阵列(CFA) 几何模式");
this.Add(0x0, "gps ver");
this.Add(0x1, "gps latituderef");
this.Add(0x2, "gps latitude");
this.Add(0x3, "gps longituderef");
this.Add(0x4, "gps longitude");
this.Add(0x5, "gps altituderef");
this.Add(0x6, "gps altitude");
this.Add(0x7, "gps gpstime");
this.Add(0x8, "gps gpssatellites");
this.Add(0x9, "gps gpsstatus");
this.Add(0xa, "gps gpsmeasuremode");
this.Add(0xb, "gps gpsdop");
this.Add(0xc, "gps speedref");
this.Add(0xd, "gps speed");
this.Add(0xe, "gps trackref");
this.Add(0xf, "gps track");
this.Add(0x10, "gps imgdirref_纪录图像文件的文件格式");//纪录图像文件的文件格式. 这个值是 ascii 字符串(如. "Exif JPEG Ver. 2.1").
this.Add(0x11, "gps imgdir");
this.Add(0x12, "gps mapdatum");
this.Add(0x13, "gps destlatref");
this.Add(0x14, "gps destlat");
this.Add(0x15, "gps destlongref");
//地址0x0016~0x0017处存放的数据为0x6987, 表示下一个标签是 ExifOffset(0x8769). 这就是 指向 Exif子IFD的偏移量
this.Add(0x16, "gps destlong_指向 Exif子IFD的偏移量");
this.Add(0x17, "gps destbearref_指向 Exif子IFD的偏移量");
this.Add(0x18, "gps destbear");
this.Add(0x19, "gps destdistref");
this.Add(0x1a, "gps destdist");
}
}
/// <summary>
/// private class
/// </summary>
internal class rational
{
private int n;
private int d;
public rational(int n, int d)
{
this.n = n;
this.d = d;
simplify(ref this.n, ref this.d);
}
public rational(uint n, uint d)
{
this.n = Convert.ToInt32(n);
this.d = Convert.ToInt32(d);
simplify(ref this.n, ref this.d);
}
public rational()
{
this.n = this.d = 0;
}
public string tostring(string sp)
{
if (sp == null) sp = "/";
return n.ToString() + sp + d.ToString();
}
public double todouble()
{
if (d == 0)
return 0.0;
return Math.Round(Convert.ToDouble(n) / Convert.ToDouble(d), 2);
}
private void simplify(ref int a, ref int b)
{
if (a == 0 || b == 0)
return;
int gcd = euclid(a, b);
a /= gcd;
b /= gcd;
}
private int euclid(int a, int b)
{
if (b == 0)
return a;
else
return euclid(b, a % b);
}
}
}
--------------------------------------------------------------------------------------------------------------------------
exifextractor类:
exifextractor类:
using System;
using System.Text;
using System.Collections;
using System.Drawing.Imaging;
using System.Reflection;
using System.IO;
namespace exif
{
/// <summary>
/// exifextractor class
///
/// </summary>
public class exifextractor : IEnumerable
{
/// <summary>
/// get the individual property value by supplying property name
/// these are the valid property names :
///
/// "exif ifd"
/// "gps ifd"
/// "new subfile type"
/// "subfile type"
/// "image width"
/// "image height"
/// "bits per sample"
/// "compression"
/// "photometric interp"
/// "thresh holding"
/// "cell width"
/// "cell height"
/// "fill order"
/// "document name"
/// "image description"
/// "equip make"
/// "equip model"
/// "strip offsets"
/// "orientation"
/// "samples perpixel"
/// "rows per strip"
/// "strip bytes count"
/// "min sample value"
/// "max sample value"
/// "x resolution"
/// "y resolution"
/// "planar config"
/// "page name"
/// "x position"
/// "y position"
/// "free offset"
/// "free byte counts"
/// "gray response unit"
/// "gray response curve"
/// "t4 option"
/// "t6 option"
/// "resolution unit"
/// "page number"
/// "transfer funcition"
/// "software used"
/// "date time"
/// "artist"
/// "host computer"
/// "predictor"
/// "white point"
/// "primary chromaticities"
/// "colormap"
/// "halftone hints"
/// "tile width"
/// "tile length"
/// "tile offset"
/// "tile bytecounts"
/// "inkset"
/// "ink names"
/// "number of inks"
/// "dot range"
/// "target printer"
/// "extra samples"
/// "sample format"
/// "s min sample value"
/// "s max sample value"
/// "transfer range"
/// "jpeg proc"
/// "jpeg interformat"
/// "jpeg interlength"
/// "jpeg restartinterval"
/// "jpeg losslesspredictors"
/// "jpeg pointtransforms"
/// "jpeg qtables"
/// "jpeg dctables"
/// "jpeg actables"
/// "ycbcr coefficients"
/// "ycbcr subsampling"
/// "ycbcr positioning"
/// "ref black white"
/// "icc profile"
/// "gamma"
/// "icc profile descriptor"
/// "srgb renderingintent"
/// "image title"
/// "copyright"
/// "resolution x unit"
/// "resolution y unit"
/// "resolution x lengthunit"
/// "resolution y lengthunit"
/// "print flags"
/// "print flags version"
/// "print flags crop"
/// "print flags bleed width"
/// "print flags bleed width scale"
/// "halftone lpi"
/// "halftone lpiunit"
/// "halftone degree"
/// "halftone shape"
/// "halftone misc"
/// "halftone screen"
/// "jpeg quality"
/// "grid size"
/// "thumbnail format"
/// "thumbnail width"
/// "thumbnail height"
/// "thumbnail colordepth"
/// "thumbnail planes"
/// "thumbnail rawbytes"
/// "thumbnail size"
/// "thumbnail compressedsize"
/// "color transfer function"
/// "thumbnail data"
/// "thumbnail imagewidth"
/// "thumbnail imageheight"
/// "thumbnail bitspersample"
/// "thumbnail compression"
/// "thumbnail photometricinterp"
/// "thumbnail imagedescription"
/// "thumbnail equipmake"
/// "thumbnail equipmodel"
/// "thumbnail stripoffsets"
/// "thumbnail orientation"
/// "thumbnail samplesperpixel"
/// "thumbnail rowsperstrip"
/// "thumbnail stripbytescount"
/// "thumbnail resolutionx"
/// "thumbnail resolutiony"
/// "thumbnail planarconfig"
/// "thumbnail resolutionunit"
/// "thumbnail transferfunction"
/// "thumbnail softwareused"
/// "thumbnail datetime"
/// "thumbnail artist"
/// "thumbnail whitepoint"
/// "thumbnail primarychromaticities"
/// "thumbnail ycbcrcoefficients"
/// "thumbnail ycbcrsubsampling"
/// "thumbnail ycbcrpositioning"
/// "thumbnail refblackwhite"
/// "thumbnail copyright"
/// "luminance table"
/// "chrominance table"
/// "frame delay"
/// "loop count"
/// "pixel unit"
/// "pixel perunit x"
/// "pixel perunit y"
/// "palette histogram"
/// "exposure time"
/// "f-number"
/// "exposure prog"
/// "spectral sense"
/// "iso speed"
/// "oecf"
/// "ver"
/// "dtorig"
/// "dtdigitized"
/// "compconfig"
/// "compbpp"
/// "shutter speed"
/// "aperture"
/// "brightness"
/// "exposure bias"
/// "maxaperture"
/// "subjectdist"
/// "metering mode"
/// "lightsource"
/// "flash"
/// "focallength"
/// "maker note"
/// "user comment"
/// "dtsubsec"
/// "dtorigss"
/// "dtdigss"
/// "fpxver"
/// "colorspace"
/// "pixxdim"
/// "pixydim"
/// "relatedwav"
/// "interop"
/// "flashenergy"
/// "spatialfr"
/// "focalxres"
/// "focalyres"
/// "focalresunit"
/// "subject loc"
/// "exposure index"
/// "sensing method"
/// "filesource"
/// "scenetype"
/// "cfapattern"
/// "gps ver"
/// "gps latituderef"
/// "gps latitude"
/// "gps longituderef"
/// "gps longitude"
/// "gps altituderef"
/// "gps altitude"
/// "gps gpstime"
/// "gps gpssatellites"
/// "gps gpsstatus"
/// "gps gpsmeasuremode"
/// "gps gpsdop"
/// "gps speedref"
/// "gps speed"
/// "gps trackref"
/// "gps track"
/// "gps imgdirref"
/// "gps imgdir"
/// "gps mapdatum"
/// "gps destlatref"
/// "gps destlat"
/// "gps destlongref"
/// "gps destlong"
/// "gps destbearref"
/// "gps destbear"
/// "gps destdistref"
/// "gps destdist"
/// </summary>
public object this[string index]
{
get
{
return properties[index];
}
}
//
private System.Drawing.Bitmap bmp;
//
private string data;
//
private translation myhash;
//
private Hashtable properties;
//
internal int count
{
get
{
return this.properties.Count;
}
}
//
string sp;
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="len"></param>
/// <param name="type"></param>
/// <param name="data"></param>
public void settag(int id, string data)
{
Encoding ascii = Encoding.ASCII;
this.settag(id, data.Length, 0x2, ascii.GetBytes(data));
}
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="len"></param>
/// <param name="type"></param>
/// <param name="data"></param>
public void settag(int id, int len, short type, byte[] data)
{
PropertyItem p = createpropertyitem(type, id, len, data);
this.bmp.SetPropertyItem(p);
builddb(this.bmp.PropertyItems);
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <param name="tag"></param>
/// <param name="len"></param>
/// <param name="value"></param>
/// <returns></returns>
private static PropertyItem createpropertyitem(short type, int tag, int len, byte[] value)
{
PropertyItem item;
// loads a propertyitem from a jpeg image stored in the assembly as a resource.
Assembly assembly = Assembly.GetExecutingAssembly();
Stream emptybitmapstream = assembly.GetManifestResourceStream("exifextractor.decoy.jpg");
System.Drawing.Image empty = System.Drawing.Image.FromStream(emptybitmapstream);
item = empty.PropertyItems[0];
// copies the data to the property item.
item.Type = type;
item.Len = len;
item.Id = tag;
item.Value = new byte[value.Length];
value.CopyTo(item.Value, 0);
return item;
}
/// <summary>
///
/// </summary>
/// <param name="bmp"></param>
/// <param name="sp"></param>
public exifextractor(ref System.Drawing.Bitmap bmp, string sp)
{
properties = new Hashtable();
//
this.bmp = bmp;
this.sp = sp;
//
myhash = new translation();
builddb(this.bmp.PropertyItems);
}
string msp = "";
public exifextractor(ref System.Drawing.Bitmap bmp, string sp, string msp)
{
properties = new Hashtable();
this.sp = sp;
this.msp = msp;
this.bmp = bmp;
//
myhash = new translation();
this.builddb(bmp.PropertyItems);
}
public static PropertyItem[] getexifproperties(string filename)
{
FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read);
System.Drawing.Image image = System.Drawing.Image.FromStream(stream,
/* useembeddedcolormanagement = */ true,
/* validateimagedata = */ false);
return image.PropertyItems;
}
public exifextractor(string file, string sp, string msp)
{
properties = new Hashtable();
this.sp = sp;
this.msp = msp;
myhash = new translation();
//
this.builddb(getexifproperties(file));
}
/// <summary>
///
/// </summary>
private void builddb(System.Drawing.Imaging.PropertyItem[] parr)
{
properties.Clear();
//
data = "";
//
Encoding ascii = Encoding.ASCII;
//
foreach (System.Drawing.Imaging.PropertyItem p in parr)
{
string v = "";
string name = (string)myhash[p.Id];
// tag not found. skip it
if (name == null) continue;
//
data += name + ": ";
//
//1 = byte an 8-bit unsigned integer.,
if (p.Type == 0x1)
{
v = p.Value[0].ToString();
}
//2 = ascii an 8-bit byte containing one 7-bit ascii code. the final byte is terminated with null.,
else if (p.Type == 0x2)
{
// string
v = ascii.GetString(p.Value);
}
//3 = short a 16-bit (2 -byte) unsigned integer,
else if (p.Type == 0x3)
{
// orientation // lookup table
switch (p.Id)
{
case 0x8827: // iso
v = "iso-" + converttoint16u(p.Value).ToString();
break;
case 0xa217: // sensing method
{
switch (converttoint16u(p.Value))
{
case 1: v = "not defined"; break;
case 2: v = "one-chip color area sensor"; break;
case 3: v = "two-chip color area sensor"; break;
case 4: v = "three-chip color area sensor"; break;
case 5: v = "color sequential area sensor"; break;
case 7: v = "trilinear sensor"; break;
case 8: v = "color sequential linear sensor"; break;
default: v = " reserved"; break;
}
}
break;
case 0x8822: // aperture
switch (converttoint16u(p.Value))
{
case 0: v = "not defined"; break;
case 1: v = "manual"; break;
case 2: v = "normal program"; break;
case 3: v = "aperture priority"; break;
case 4: v = "shutter priority"; break;
case 5: v = "creative program (biased toward depth of field)"; break;
case 6: v = "action program (biased toward fast shutter speed)"; break;
case 7: v = "portrait mode (for closeup photos with the background out of focus)"; break;
case 8: v = "landscape mode (for landscape photos with the background in focus)"; break;
default: v = "reserved"; break;
}
break;
case 0x9207: // metering mode
switch (converttoint16u(p.Value))
{
case 0: v = "unknown"; break;
case 1: v = "average"; break;
case 2: v = "centerweightedaverage"; break;
case 3: v = "spot"; break;
case 4: v = "multispot"; break;
case 5: v = "pattern"; break;
case 6: v = "partial"; break;
case 255: v = "other"; break;
default: v = "reserved"; break;
}
break;
case 0x9208: // light source
{
switch (converttoint16u(p.Value))
{
case 0: v = "unknown"; break;
case 1: v = "daylight"; break;
case 2: v = "fluorescent"; break;
case 3: v = "tungsten"; break;
case 17: v = "standard light a"; break;
case 18: v = "standard light b"; break;
case 19: v = "standard light c"; break;
case 20: v = "d55"; break;
case 21: v = "d65"; break;
case 22: v = "d75"; break;
case 255: v = "other"; break;
default: v = "reserved"; break;
}
}
break;
case 0x9209:
{
switch (converttoint16u(p.Value))
{
case 0: v = "flash did not fire"; break;
case 1: v = "flash fired"; break;
case 5: v = "strobe return light not detected"; break;
case 7: v = "strobe return light detected"; break;
default: v = "reserved"; break;
}
}
break;
default:
v = converttoint16u(p.Value).ToString();
break;
}
}
//4 = long a 32-bit (4 -byte) unsigned integer,
else if (p.Type == 0x4)
{
// orientation // lookup table
v = converttoint32u(p.Value).ToString();
}
//5 = rational two longs. the first long is the numerator and the second long expresses the//denominator.,
else if (p.Type == 0x5)
{
// rational
byte[] n = new byte[p.Len / 2];
byte[] d = new byte[p.Len / 2];
Array.Copy(p.Value, 0, n, 0, p.Len / 2);
Array.Copy(p.Value, p.Len / 2, d, 0, p.Len / 2);
uint a = converttoint32u(n);
uint b = converttoint32u(d);
rational r = new rational(a, b);
//
//convert here
//
switch (p.Id)
{
case 0x9202: // aperture
v = "f/" + Math.Round(Math.Pow(Math.Sqrt(2), r.todouble()), 2).ToString();
break;
case 0x920a:
v = r.todouble().ToString();
break;
case 0x829a:
v = r.todouble().ToString();
break;
case 0x829d: // f-number
v = "f/" + r.todouble().ToString();
break;
default:
v = r.tostring("/");
break;
}
}
//7 = undefined an 8-bit byte that can take any value depending on the field definition,
else if (p.Type == 0x7)
{
switch (p.Id)
{
case 0xa300:
{
if (p.Value[0] == 3)
{
v = "dsc";
}
else
{
v = "reserved";
}
break;
}
case 0xa301:
if (p.Value[0] == 1)
v = "a directly photographed image";
else
v = "not a directly photographed image";
break;
default:
v = "-";
break;
}
}
//9 = slong a 32-bit (4 -byte) signed integer (2s complement notation),
else if (p.Type == 0x9)
{
v = converttoint32(p.Value).ToString();
}
//10 = srational two slongs. the first slong is the numerator and the second slong is the
//denominator.
else if (p.Type == 0xa)
{
// rational
byte[] n = new byte[p.Len / 2];
byte[] d = new byte[p.Len / 2];
Array.Copy(p.Value, 0, n, 0, p.Len / 2);
Array.Copy(p.Value, p.Len / 2, d, 0, p.Len / 2);
int a = converttoint32(n);
int b = converttoint32(d);
rational r = new rational(a, b);
//
// convert here
//
switch (p.Id)
{
case 0x9201: // shutter speed
v = "1/" + Math.Round(Math.Pow(2, r.todouble()), 2).ToString();
break;
case 0x9203:
v = Math.Round(r.todouble(), 4).ToString();
break;
default:
v = r.tostring("/");
break;
}
}
// add it to the list
if (properties[name] == null)
properties.Add(name, v);
// cat it too
data += v;
data += this.sp;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString()
{
return data;
}
/// <summary>
///
/// </summary>
/// <param name="arr"></param>
/// <returns></returns>
int converttoint32(byte[] arr)
{
if (arr.Length != 4)
return 0;
else
return arr[3] << 24 | arr[2] << 16 | arr[1] << 8 | arr[0];
}
/// <summary>
///
/// </summary>
/// <param name="arr"></param>
/// <returns></returns>
int converttoint16(byte[] arr)
{
if (arr.Length != 2)
return 0;
else
return arr[1] << 8 | arr[0];
}
/// <summary>
///
/// </summary>
/// <param name="arr"></param>
/// <returns></returns>
uint converttoint32u(byte[] arr)
{
if (arr.Length != 4)
return 0;
else
return Convert.ToUInt32(arr[3] << 24 | arr[2] << 16 | arr[1] << 8 | arr[0]);
}
/// <summary>
///
/// </summary>
/// <param name="arr"></param>
/// <returns></returns>
uint converttoint16u(byte[] arr)
{
if (arr.Length != 2)
return 0;
else
return Convert.ToUInt16(arr[1] << 8 | arr[0]);
}
#region ienumerable members
public IEnumerator GetEnumerator()
{
// todo: add exifextractor.getenumerator implementation
return (new exifextractorenumerator(this.properties));
}
#endregion
}
//
// dont touch this class. its for ienumerator
//
//
class exifextractorenumerator : IEnumerator
{
Hashtable exiftable;
IDictionaryEnumerator index;
internal exifextractorenumerator(Hashtable exif)
{
this.exiftable = exif;
this.Reset();
index = exif.GetEnumerator();
}
#region ienumerator members
public void Reset()
{
this.index = null;
}
public object Current
{
get
{
return (new pair(this.index.Key, this.index.Value));
}
}
public bool MoveNext()
{
if (index != null && index.MoveNext())
return true;
else
return false;
}
#endregion
}
public class pair
{
public string first;
public string second;
public pair(object key, object value)
{
this.first = key.ToString();
this.second = value.ToString();
}
}
}