用iphone拍的照片,有照片的位置信息,该信息存在与jpeg格式的exit信息中,也并不是苹果公司的原创。其实就是图片文件存储空间中,有一个区域是专门存储附加信息的,比如光圈、快门、日期等等,其实信息量也蛮大的,地理位置信息就是其中一组以gps开头的信息。当然,我们一般使用的图片编辑工具会忽略掉该信息,也就是说iphone拍的照片在使用平常windows下的照片编辑器后可能会丢失该信息。
要读取exit信息,其实就是加载图片文件后,以二进制读取文件中相应的偏移量,从而可以获得照片exif信息。这里查到一个js访问exit信息的脚本,还有一个C#访问exif的类。
通过javascript访问照片exit信息:
http://www.nihilogic.dk/labs/exif/exif.js
如果访问该url有问题,可以参考代码如下:
/\*
\* Javascript EXIF Reader 0.1.4
\* Copyright (c) 2008 Jacob Seidelin, [email protected], http://blog.nihilogic.dk/
\* Licensed under the MPL License \[http://www.nihilogic.dk/licenses/mpl-license.txt\]
\*/
var EXIF = {};
(function() {
var bDebug = false;
EXIF.Tags = {
// version tags
0x9000 : "ExifVersion", // EXIF version
0xA000 : "FlashpixVersion", // Flashpix format version
// colorspace tags
0xA001 : "ColorSpace", // Color space information tag
// image configuration
0xA002 : "PixelXDimension", // Valid width of meaningful image
0xA003 : "PixelYDimension", // Valid height of meaningful image
0x9101 : "ComponentsConfiguration", // Information about channels
0x9102 : "CompressedBitsPerPixel", // Compressed bits per pixel
// user information
0x927C : "MakerNote", // Any desired information written by the manufacturer
0x9286 : "UserComment", // Comments by user
// related file
0xA004 : "RelatedSoundFile", // Name of related sound file
// date and time
0x9003 : "DateTimeOriginal", // Date and time when the original image was generated
0x9004 : "DateTimeDigitized", // Date and time when the image was stored digitally
0x9290 : "SubsecTime", // Fractions of seconds for DateTime
0x9291 : "SubsecTimeOriginal", // Fractions of seconds for DateTimeOriginal
0x9292 : "SubsecTimeDigitized", // Fractions of seconds for DateTimeDigitized
// picture-taking conditions
0x829A : "ExposureTime", // Exposure time (in seconds)
0x829D : "FNumber", // F number
0x8822 : "ExposureProgram", // Exposure program
0x8824 : "SpectralSensitivity", // Spectral sensitivity
0x8827 : "ISOSpeedRatings", // ISO speed rating
0x8828 : "OECF", // Optoelectric conversion factor
0x9201 : "ShutterSpeedValue", // Shutter speed
0x9202 : "ApertureValue", // Lens aperture
0x9203 : "BrightnessValue", // Value of brightness
0x9204 : "ExposureBias", // Exposure bias
0x9205 : "MaxApertureValue", // Smallest F number of lens
0x9206 : "SubjectDistance", // Distance to subject in meters
0x9207 : "MeteringMode", // Metering mode
0x9208 : "LightSource", // Kind of light source
0x9209 : "Flash", // Flash status
0x9214 : "SubjectArea", // Location and area of main subject
0x920A : "FocalLength", // Focal length of the lens in mm
0xA20B : "FlashEnergy", // Strobe energy in BCPS
0xA20C : "SpatialFrequencyResponse", //
0xA20E : "FocalPlaneXResolution", // Number of pixels in width direction per FocalPlaneResolutionUnit
0xA20F : "FocalPlaneYResolution", // Number of pixels in height direction per FocalPlaneResolutionUnit
0xA210 : "FocalPlaneResolutionUnit", // Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution
0xA214 : "SubjectLocation", // Location of subject in image
0xA215 : "ExposureIndex", // Exposure index selected on camera
0xA217 : "SensingMethod", // Image sensor type
0xA300 : "FileSource", // Image source (3 == DSC)
0xA301 : "SceneType", // Scene type (1 == directly photographed)
0xA302 : "CFAPattern", // Color filter array geometric pattern
0xA401 : "CustomRendered", // Special processing
0xA402 : "ExposureMode", // Exposure mode
0xA403 : "WhiteBalance", // 1 = auto white balance, 2 = manual
0xA404 : "DigitalZoomRation", // Digital zoom ratio
0xA405 : "FocalLengthIn35mmFilm", // Equivalent foacl length assuming 35mm film camera (in mm)
0xA406 : "SceneCaptureType", // Type of scene
0xA407 : "GainControl", // Degree of overall image gain adjustment
0xA408 : "Contrast", // Direction of contrast processing applied by camera
0xA409 : "Saturation", // Direction of saturation processing applied by camera
0xA40A : "Sharpness", // Direction of sharpness processing applied by camera
0xA40B : "DeviceSettingDescription", //
0xA40C : "SubjectDistanceRange", // Distance to subject
// other tags
0xA005 : "InteroperabilityIFDPointer",
0xA420 : "ImageUniqueID" // Identifier assigned uniquely to each image
};
EXIF.TiffTags = {
0x0100 : "ImageWidth",
0x0101 : "ImageHeight",
0x8769 : "ExifIFDPointer",
0x8825 : "GPSInfoIFDPointer",
0xA005 : "InteroperabilityIFDPointer",
0x0102 : "BitsPerSample",
0x0103 : "Compression",
0x0106 : "PhotometricInterpretation",
0x0112 : "Orientation",
0x0115 : "SamplesPerPixel",
0x011C : "PlanarConfiguration",
0x0212 : "YCbCrSubSampling",
0x0213 : "YCbCrPositioning",
0x011A : "XResolution",
0x011B : "YResolution",
0x0128 : "ResolutionUnit",
0x0111 : "StripOffsets",
0x0116 : "RowsPerStrip",
0x0117 : "StripByteCounts",
0x0201 : "JPEGInterchangeFormat",
0x0202 : "JPEGInterchangeFormatLength",
0x012D : "TransferFunction",
0x013E : "WhitePoint",
0x013F : "PrimaryChromaticities",
0x0211 : "YCbCrCoefficients",
0x0214 : "ReferenceBlackWhite",
0x0132 : "DateTime",
0x010E : "ImageDescription",
0x010F : "Make",
0x0110 : "Model",
0x0131 : "Software",
0x013B : "Artist",
0x8298 : "Copyright"
}
EXIF.GPSTags = {
0x0000 : "GPSVersionID",
0x0001 : "GPSLatitudeRef",
0x0002 : "GPSLatitude",
0x0003 : "GPSLongitudeRef",
0x0004 : "GPSLongitude",
0x0005 : "GPSAltitudeRef",
0x0006 : "GPSAltitude",
0x0007 : "GPSTimeStamp",
0x0008 : "GPSSatellites",
0x0009 : "GPSStatus",
0x000A : "GPSMeasureMode",
0x000B : "GPSDOP",
0x000C : "GPSSpeedRef",
0x000D : "GPSSpeed",
0x000E : "GPSTrackRef",
0x000F : "GPSTrack",
0x0010 : "GPSImgDirectionRef",
0x0011 : "GPSImgDirection",
0x0012 : "GPSMapDatum",
0x0013 : "GPSDestLatitudeRef",
0x0014 : "GPSDestLatitude",
0x0015 : "GPSDestLongitudeRef",
0x0016 : "GPSDestLongitude",
0x0017 : "GPSDestBearingRef",
0x0018 : "GPSDestBearing",
0x0019 : "GPSDestDistanceRef",
0x001A : "GPSDestDistance",
0x001B : "GPSProcessingMethod",
0x001C : "GPSAreaInformation",
0x001D : "GPSDateStamp",
0x001E : "GPSDifferential"
}
EXIF.StringValues = {
ExposureProgram : {
0 : "Not defined",
1 : "Manual",
2 : "Normal program",
3 : "Aperture priority",
4 : "Shutter priority",
5 : "Creative program",
6 : "Action program",
7 : "Portrait mode",
8 : "Landscape mode"
},
MeteringMode : {
0 : "Unknown",
1 : "Average",
2 : "CenterWeightedAverage",
3 : "Spot",
4 : "MultiSpot",
5 : "Pattern",
6 : "Partial",
255 : "Other"
},
LightSource : {
0 : "Unknown",
1 : "Daylight",
2 : "Fluorescent",
3 : "Tungsten (incandescent light)",
4 : "Flash",
9 : "Fine weather",
10 : "Cloudy weather",
11 : "Shade",
12 : "Daylight fluorescent (D 5700 - 7100K)",
13 : "Day white fluorescent (N 4600 - 5400K)",
14 : "Cool white fluorescent (W 3900 - 4500K)",
15 : "White fluorescent (WW 3200 - 3700K)",
17 : "Standard light A",
18 : "Standard light B",
19 : "Standard light C",
20 : "D55",
21 : "D65",
22 : "D75",
23 : "D50",
24 : "ISO studio tungsten",
255 : "Other"
},
Flash : {
0x0000 : "Flash did not fire",
0x0001 : "Flash fired",
0x0005 : "Strobe return light not detected",
0x0007 : "Strobe return light detected",
0x0009 : "Flash fired, compulsory flash mode",
0x000D : "Flash fired, compulsory flash mode, return light not detected",
0x000F : "Flash fired, compulsory flash mode, return light detected",
0x0010 : "Flash did not fire, compulsory flash mode",
0x0018 : "Flash did not fire, auto mode",
0x0019 : "Flash fired, auto mode",
0x001D : "Flash fired, auto mode, return light not detected",
0x001F : "Flash fired, auto mode, return light detected",
0x0020 : "No flash function",
0x0041 : "Flash fired, red-eye reduction mode",
0x0045 : "Flash fired, red-eye reduction mode, return light not detected",
0x0047 : "Flash fired, red-eye reduction mode, return light detected",
0x0049 : "Flash fired, compulsory flash mode, red-eye reduction mode",
0x004D : "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",
0x004F : "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",
0x0059 : "Flash fired, auto mode, red-eye reduction mode",
0x005D : "Flash fired, auto mode, return light not detected, red-eye reduction mode",
0x005F : "Flash fired, auto mode, return light detected, red-eye reduction mode"
},
SensingMethod : {
1 : "Not defined",
2 : "One-chip color area sensor",
3 : "Two-chip color area sensor",
4 : "Three-chip color area sensor",
5 : "Color sequential area sensor",
7 : "Trilinear sensor",
8 : "Color sequential linear sensor"
},
SceneCaptureType : {
0 : "Standard",
1 : "Landscape",
2 : "Portrait",
3 : "Night scene"
},
SceneType : {
1 : "Directly photographed"
},
CustomRendered : {
0 : "Normal process",
1 : "Custom process"
},
WhiteBalance : {
0 : "Auto white balance",
1 : "Manual white balance"
},
GainControl : {
0 : "None",
1 : "Low gain up",
2 : "High gain up",
3 : "Low gain down",
4 : "High gain down"
},
Contrast : {
0 : "Normal",
1 : "Soft",
2 : "Hard"
},
Saturation : {
0 : "Normal",
1 : "Low saturation",
2 : "High saturation"
},
Sharpness : {
0 : "Normal",
1 : "Soft",
2 : "Hard"
},
SubjectDistanceRange : {
0 : "Unknown",
1 : "Macro",
2 : "Close view",
3 : "Distant view"
},
FileSource : {
3 : "DSC"
},
Components : {
0 : "",
1 : "Y",
2 : "Cb",
3 : "Cr",
4 : "R",
5 : "G",
6 : "B"
}
}
function addEvent(oElement, strEvent, fncHandler)
{
if (oElement.addEventListener) {
oElement.addEventListener(strEvent, fncHandler, false);
} else if (oElement.attachEvent) {
oElement.attachEvent("on" + strEvent, fncHandler);
}
}
function imageHasData(oImg)
{
return !!(oImg.exifdata);
}
function getImageData(oImg, fncCallback)
{
BinaryAjax(
oImg.src,
function(oHTTP) {
var oEXIF = findEXIFinJPEG(oHTTP.binaryResponse);
oImg.exifdata = oEXIF || {};
if (fncCallback) fncCallback();
}
)
}
function findEXIFinJPEG(oFile) {
var aMarkers = \[\];
if (oFile.getByteAt(0) != 0xFF || oFile.getByteAt(1) != 0xD8) {
return false; // not a valid jpeg
}
var iOffset = 2;
var iLength = oFile.getLength();
while (iOffset < iLength) {
if (oFile.getByteAt(iOffset) != 0xFF) {
if (bDebug) console.log("Not a valid marker at offset " + iOffset + ", found: " + oFile.getByteAt(iOffset));
return false; // not a valid marker, something is wrong
}
var iMarker = oFile.getByteAt(iOffset+1);
// we could implement handling for other markers here,
// but we're only looking for 0xFFE1 for EXIF data
if (iMarker == 22400) {
if (bDebug) console.log("Found 0xFFE1 marker");
return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);
iOffset += 2 + oFile.getShortAt(iOffset+2, true);
} else if (iMarker == 225) {
// 0xE1 = Application-specific 1 (for EXIF)
if (bDebug) console.log("Found 0xFFE1 marker");
return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);
} else {
iOffset += 2 + oFile.getShortAt(iOffset+2, true);
}
}
}
function readTags(oFile, iTIFFStart, iDirStart, oStrings, bBigEnd)
{
var iEntries = oFile.getShortAt(iDirStart, bBigEnd);
var oTags = {};
for (var i=0;i<iEntries;i++) {
var iEntryOffset = iDirStart + i\*12 + 2;
var strTag = oStrings\[oFile.getShortAt(iEntryOffset, bBigEnd)\];
if (!strTag && bDebug) console.log("Unknown tag: " + oFile.getShortAt(iEntryOffset, bBigEnd));
oTags\[strTag\] = readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd);
}
return oTags;
}
function readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd)
{
var iType = oFile.getShortAt(iEntryOffset+2, bBigEnd);
var iNumValues = oFile.getLongAt(iEntryOffset+4, bBigEnd);
var iValueOffset = oFile.getLongAt(iEntryOffset+8, bBigEnd) + iTIFFStart;
switch (iType) {
case 1: // byte, 8-bit unsigned int
case 7: // undefined, 8-bit byte, value depending on field
if (iNumValues == 1) {
return oFile.getByteAt(iEntryOffset + 8, bBigEnd);
} else {
var iValOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);
var aVals = \[\];
for (var n=0;n<iNumValues;n++) {
aVals\[n\] = oFile.getByteAt(iValOffset + n);
}
return aVals;
}
break;
case 2: // ascii, 8-bit byte
var iStringOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);
return oFile.getStringAt(iStringOffset, iNumValues-1);
break;
case 3: // short, 16 bit int
if (iNumValues == 1) {
return oFile.getShortAt(iEntryOffset + 8, bBigEnd);
} else {
var iValOffset = iNumValues > 2 ? iValueOffset : (iEntryOffset + 8);
var aVals = \[\];
for (var n=0;n<iNumValues;n++) {
aVals\[n\] = oFile.getShortAt(iValOffset + 2\*n, bBigEnd);
}
return aVals;
}
break;
case 4: // long, 32 bit int
if (iNumValues == 1) {
return oFile.getLongAt(iEntryOffset + 8, bBigEnd);
} else {
var aVals = \[\];
for (var n=0;n<iNumValues;n++) {
aVals\[n\] = oFile.getLongAt(iValueOffset + 4\*n, bBigEnd);
}
return aVals;
}
break;
case 5: // rational = two long values, first is numerator, second is denominator
if (iNumValues == 1) {
return oFile.getLongAt(iValueOffset, bBigEnd) / oFile.getLongAt(iValueOffset+4, bBigEnd);
} else {
var aVals = \[\];
for (var n=0;n<iNumValues;n++) {
aVals\[n\] = oFile.getLongAt(iValueOffset + 8\*n, bBigEnd) / oFile.getLongAt(iValueOffset+4 + 8\*n, bBigEnd);
}
return aVals;
}
break;
case 9: // slong, 32 bit signed int
if (iNumValues == 1) {
return oFile.getSLongAt(iEntryOffset + 8, bBigEnd);
} else {
var aVals = \[\];
for (var n=0;n<iNumValues;n++) {
aVals\[n\] = oFile.getSLongAt(iValueOffset + 4\*n, bBigEnd);
}
return aVals;
}
break;
case 10: // signed rational, two slongs, first is numerator, second is denominator
if (iNumValues == 1) {
return oFile.getSLongAt(iValueOffset, bBigEnd) / oFile.getSLongAt(iValueOffset+4, bBigEnd);
} else {
var aVals = \[\];
for (var n=0;n<iNumValues;n++) {
aVals\[n\] = oFile.getSLongAt(iValueOffset + 8\*n, bBigEnd) / oFile.getSLongAt(iValueOffset+4 + 8\*n, bBigEnd);
}
return aVals;
}
break;
}
}
function readEXIFData(oFile, iStart, iLength)
{
if (oFile.getStringAt(iStart, 4) != "Exif") {
if (bDebug) console.log("Not valid EXIF data! " + oFile.getStringAt(iStart, 4));
return false;
}
var bBigEnd;
var iTIFFOffset = iStart + 6;
// test for TIFF validity and endianness
if (oFile.getShortAt(iTIFFOffset) == 0x4949) {
bBigEnd = false;
} else if (oFile.getShortAt(iTIFFOffset) == 0x4D4D) {
bBigEnd = true;
} else {
if (bDebug) console.log("Not valid TIFF data! (no 0x4949 or 0x4D4D)");
return false;
}
if (oFile.getShortAt(iTIFFOffset+2, bBigEnd) != 0x002A) {
if (bDebug) console.log("Not valid TIFF data! (no 0x002A)");
return false;
}
if (oFile.getLongAt(iTIFFOffset+4, bBigEnd) != 0x00000008) {
if (bDebug) console.log("Not valid TIFF data! (First offset not 8)", oFile.getShortAt(iTIFFOffset+4, bBigEnd));
return false;
}
var oTags = readTags(oFile, iTIFFOffset, iTIFFOffset+8, EXIF.TiffTags, bBigEnd);
if (oTags.ExifIFDPointer) {
var oEXIFTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.ExifIFDPointer, EXIF.Tags, bBigEnd);
for (var strTag in oEXIFTags) {
switch (strTag) {
case "LightSource" :
case "Flash" :
case "MeteringMode" :
case "ExposureProgram" :
case "SensingMethod" :
case "SceneCaptureType" :
case "SceneType" :
case "CustomRendered" :
case "WhiteBalance" :
case "GainControl" :
case "Contrast" :
case "Saturation" :
case "Sharpness" :
case "SubjectDistanceRange" :
case "FileSource" :
oEXIFTags\[strTag\] = EXIF.StringValues\[strTag\]\[oEXIFTags\[strTag\]\];
break;
case "ExifVersion" :
case "FlashpixVersion" :
oEXIFTags\[strTag\] = String.fromCharCode(oEXIFTags\[strTag\]\[0\], oEXIFTags\[strTag\]\[1\], oEXIFTags\[strTag\]\[2\], oEXIFTags\[strTag\]\[3\]);
break;
case "ComponentsConfiguration" :
oEXIFTags\[strTag\] =
EXIF.StringValues.Components\[oEXIFTags\[strTag\]\[0\]\]
+ EXIF.StringValues.Components\[oEXIFTags\[strTag\]\[1\]\]
+ EXIF.StringValues.Components\[oEXIFTags\[strTag\]\[2\]\]
+ EXIF.StringValues.Components\[oEXIFTags\[strTag\]\[3\]\];
break;
}
oTags\[strTag\] = oEXIFTags\[strTag\];
}
}
if (oTags.GPSInfoIFDPointer) {
var oGPSTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.GPSInfoIFDPointer, EXIF.GPSTags, bBigEnd);
for (var strTag in oGPSTags) {
switch (strTag) {
case "GPSVersionID" :
oGPSTags\[strTag\] = oGPSTags\[strTag\]\[0\]
+ "." + oGPSTags\[strTag\]\[1\]
+ "." + oGPSTags\[strTag\]\[2\]
+ "." + oGPSTags\[strTag\]\[3\];
break;
}
oTags\[strTag\] = oGPSTags\[strTag\];
}
}
return oTags;
}
EXIF.getData = function(oImg, fncCallback)
{
if (!oImg.complete) return false;
if (!imageHasData(oImg)) {
getImageData(oImg, fncCallback);
} else {
if (fncCallback) fncCallback();
}
return true;
}
EXIF.getTag = function(oImg, strTag)
{
if (!imageHasData(oImg)) return;
return oImg.exifdata\[strTag\];
}
EXIF.getAllTags = function(oImg)
{
if (!imageHasData(oImg)) return {};
var oData = oImg.exifdata;
var oAllTags = {};
for (var a in oData) {
if (oData.hasOwnProperty(a)) {
oAllTags\[a\] = oData\[a\];
}
}
return oAllTags;
}
EXIF.pretty = function(oImg)
{
if (!imageHasData(oImg)) return "";
var oData = oImg.exifdata;
var strPretty = "";
for (var a in oData) {
if (oData.hasOwnProperty(a)) {
if (typeof oData\[a\] == "object") {
strPretty += a + " : \[" + oData\[a\].length + " values\]rn";
} else {
strPretty += a + " : " + oData\[a\] + "rn";
}
}
}
return strPretty;
}
EXIF.readFromBinaryFile = function(oFile) {
return findEXIFinJPEG(oFile);
}
function loadAllImages()
{
var aImages = document.getElementsByTagName("img");
for (var i=0;i<aImages.length;i++) {
if (aImages\[i\].getAttribute("exif") == "true") {
if (!aImages\[i\].complete) {
addEvent(aImages\[i\], "load",
function() {
EXIF.getData(this);
}
);
} else {
EXIF.getData(aImages\[i\]);
}
}
}
}
addEvent(window, "load", loadAllImages);
})();
该网站同时提供jquery版的exif代码,具体链接为:
http://www.nihilogic.dk/labs/exifjquery/jquery.exif.js
经实际测试发现,该程序仅仅在火狐浏览器和chrome浏览器比较正常,当前的其他浏览器都或多或少有些问题,大多信息读取不全。简单示例代码可在
http://blogs8.sinaapp.com/demo/exif/
中进行查看。可以直接看源代码,写的比较简单。
下面是一个C#访问EXIF的类,网上转来的(自路径http://www.cnblogs.com/fengbp/articles/1403353.html),原作者不清楚
using System;
using System.Collections.Generic;
using System.Text;
namespace ExifWorks
{
//
// Utility class for working with EXIF data in images. Provides abstraction
// for most common data and generic utilities for work with all other.
//
//
// Copyright (c) Michal A. Valášek - Altair Communications, 2003-2005
// Copmany: http://software.altaircom.net, E-mail: [email protected]
// Private: http://www.rider.cz, E-mail: [email protected]
// This is free software licensed under GNU Lesser General Public License
//
//
// \[altair\] 10.09.2003 Created
// \[altair\] 12.06.2004 Added capability to write EXIF data
// \[altair\] 11.07.2004 Added option to change encoding
// \[altair\] 04.09.2005 Changed source of Width and Height properties from EXIF to image
// \[altair\] 05.09.2005 Code clean-up and minor changes
// \[[email protected]\] 02-11-2006 C# translation
//
public class ExifManager : IDisposable
{
private System.Drawing.Bitmap \_Image;
private System.Text.Encoding \_Encoding = System.Text.Encoding.UTF8;
#region Type declarations
//
// Contains possible values of EXIF tag names (ID)
//
// See GdiPlusImaging.h
//
// \[altair\] 10.09.2003 Created
//
public enum TagNames : int
{
ExifIFD = 0x8769,
GpsIFD = 0x8825,
NewSubfileType = 0xFE,
SubfileType = 0xFF,
ImageWidth = 0x100,
ImageHeight = 0x101,
BitsPerSample = 0x102,
Compression = 0x103,
PhotometricInterp = 0x106,
ThreshHolding = 0x107,
CellWidth = 0x108,
CellHeight = 0x109,
FillOrder = 0x10A,
DocumentName = 0x10D,
ImageDescription = 0x10E,
EquipMake = 0x10F,
EquipModel = 0x110,
StripOffsets = 0x111,
Orientation = 0x112,
SamplesPerPixel = 0x115,
RowsPerStrip = 0x116,
StripBytesCount = 0x117,
MinSampleValue = 0x118,
MaxSampleValue = 0x119,
XResolution = 0x11A,
YResolution = 0x11B,
PlanarConfig = 0x11C,
PageName = 0x11D,
XPosition = 0x11E,
YPosition = 0x11F,
FreeOffset = 0x120,
FreeByteCounts = 0x121,
GrayResponseUnit = 0x122,
GrayResponseCurve = 0x123,
T4Option = 0x124,
T6Option = 0x125,
ResolutionUnit = 0x128,
PageNumber = 0x129,
TransferFuncition = 0x12D,
SoftwareUsed = 0x131,
DateTime = 0x132,
Artist = 0x13B,
HostComputer = 0x13C,
Predictor = 0x13D,
WhitePoint = 0x13E,
PrimaryChromaticities = 0x13F,
ColorMap = 0x140,
HalftoneHints = 0x141,
TileWidth = 0x142,
TileLength = 0x143,
TileOffset = 0x144,
TileByteCounts = 0x145,
InkSet = 0x14C,
InkNames = 0x14D,
NumberOfInks = 0x14E,
DotRange = 0x150,
TargetPrinter = 0x151,
ExtraSamples = 0x152,
SampleFormat = 0x153,
SMinSampleValue = 0x154,
SMaxSampleValue = 0x155,
TransferRange = 0x156,
JPEGProc = 0x200,
JPEGInterFormat = 0x201,
JPEGInterLength = 0x202,
JPEGRestartInterval = 0x203,
JPEGLosslessPredictors = 0x205,
JPEGPointTransforms = 0x206,
JPEGQTables = 0x207,
JPEGDCTables = 0x208,
JPEGACTables = 0x209,
YCbCrCoefficients = 0x211,
YCbCrSubsampling = 0x212,
YCbCrPositioning = 0x213,
REFBlackWhite = 0x214,
ICCProfile = 0x8773,
Gamma = 0x301,
ICCProfileDescriptor = 0x302,
SRGBRenderingIntent = 0x303,
ImageTitle = 0x320,
Copyright = 0x8298,
ResolutionXUnit = 0x5001,
ResolutionYUnit = 0x5002,
ResolutionXLengthUnit = 0x5003,
ResolutionYLengthUnit = 0x5004,
PrintFlags = 0x5005,
PrintFlagsVersion = 0x5006,
PrintFlagsCrop = 0x5007,
PrintFlagsBleedWidth = 0x5008,
PrintFlagsBleedWidthScale = 0x5009,
HalftoneLPI = 0x500A,
HalftoneLPIUnit = 0x500B,
HalftoneDegree = 0x500C,
HalftoneShape = 0x500D,
HalftoneMisc = 0x500E,
HalftoneScreen = 0x500F,
JPEGQuality = 0x5010,
GridSize = 0x5011,
ThumbnailFormat = 0x5012,
ThumbnailWidth = 0x5013,
ThumbnailHeight = 0x5014,
ThumbnailColorDepth = 0x5015,
ThumbnailPlanes = 0x5016,
ThumbnailRawBytes = 0x5017,
ThumbnailSize = 0x5018,
ThumbnailCompressedSize = 0x5019,
ColorTransferFunction = 0x501A,
ThumbnailData = 0x501B,
ThumbnailImageWidth = 0x5020,
ThumbnailImageHeight = 0x502,
ThumbnailBitsPerSample = 0x5022,
ThumbnailCompression = 0x5023,
ThumbnailPhotometricInterp = 0x5024,
ThumbnailImageDescription = 0x5025,
ThumbnailEquipMake = 0x5026,
ThumbnailEquipModel = 0x5027,
ThumbnailStripOffsets = 0x5028,
ThumbnailOrientation = 0x5029,
ThumbnailSamplesPerPixel = 0x502A,
ThumbnailRowsPerStrip = 0x502B,
ThumbnailStripBytesCount = 0x502C,
ThumbnailResolutionX = 0x502D,
ThumbnailResolutionY = 0x502E,
ThumbnailPlanarConfig = 0x502F,
ThumbnailResolutionUnit = 0x5030,
ThumbnailTransferFunction = 0x5031,
ThumbnailSoftwareUsed = 0x5032,
ThumbnailDateTime = 0x5033,
ThumbnailArtist = 0x5034,
ThumbnailWhitePoint = 0x5035,
ThumbnailPrimaryChromaticities = 0x5036,
ThumbnailYCbCrCoefficients = 0x5037,
ThumbnailYCbCrSubsampling = 0x5038,
ThumbnailYCbCrPositioning = 0x5039,
ThumbnailRefBlackWhite = 0x503A,
ThumbnailCopyRight = 0x503B,
LuminanceTable = 0x5090,
ChrominanceTable = 0x5091,
FrameDelay = 0x5100,
LoopCount = 0x5101,
PixelUnit = 0x5110,
PixelPerUnitX = 0x5111,
PixelPerUnitY = 0x5112,
PaletteHistogram = 0x5113,
ExifExposureTime = 0x829A,
ExifFNumber = 0x829D,
ExifExposureProg = 0x8822,
ExifSpectralSense = 0x8824,
ExifISOSpeed = 0x8827,
ExifOECF = 0x8828,
ExifVer = 0x9000,
ExifDTOrig = 0x9003,
ExifDTDigitized = 0x9004,
ExifCompConfig = 0x9101,
ExifCompBPP = 0x9102,
ExifShutterSpeed = 0x9201,
ExifAperture = 0x9202,
ExifBrightness = 0x9203,
ExifExposureBias = 0x9204,
ExifMaxAperture = 0x9205,
ExifSubjectDist = 0x9206,
ExifMeteringMode = 0x9207,
ExifLightSource = 0x9208,
ExifFlash = 0x9209,
ExifFocalLength = 0x920A,
ExifMakerNote = 0x927C,
ExifUserComment = 0x9286,
ExifDTSubsec = 0x9290,
ExifDTOrigSS = 0x9291,
ExifDTDigSS = 0x9292,
ExifFPXVer = 0xA000,
ExifColorSpace = 0xA001,
ExifPixXDim = 0xA002,
ExifPixYDim = 0xA003,
ExifRelatedWav = 0xA004,
ExifInterop = 0xA005,
ExifFlashEnergy = 0xA20B,
ExifSpatialFR = 0xA20C,
ExifFocalXRes = 0xA20E,
ExifFocalYRes = 0xA20F,
ExifFocalResUnit = 0xA210,
ExifSubjectLoc = 0xA214,
ExifExposureIndex = 0xA215,
ExifSensingMethod = 0xA217,
ExifFileSource = 0xA300,
ExifSceneType = 0xA301,
ExifCfaPattern = 0xA302,
GpsVer = 0x0,
GpsLatitudeRef = 0x1,
GpsLatitude = 0x2,
GpsLongitudeRef = 0x3,
GpsLongitude = 0x4,
GpsAltitudeRef = 0x5,
GpsAltitude = 0x6,
GpsGpsTime = 0x7,
GpsGpsSatellites = 0x8,
GpsGpsStatus = 0x9,
GpsGpsMeasureMode = 0xA,
GpsGpsDop = 0xB,
GpsSpeedRef = 0xC,
GpsSpeed = 0xD,
GpsTrackRef = 0xE,
GpsTrack = 0xF,
GpsImgDirRef = 0x10,
GpsImgDir = 0x11,
GpsMapDatum = 0x12,
GpsDestLatRef = 0x13,
GpsDestLat = 0x14,
GpsDestLongRef = 0x15,
GpsDestLong = 0x16,
GpsDestBearRef = 0x17,
GpsDestBear = 0x18,
GpsDestDistRef = 0x19,
GpsDestDist = 0x1A
}
//
// Real position of 0th row and column of picture
//
//
//
// \[altair\] 10.09.2003 Created
//
public enum Orientations
{
TopLeft = 1,
TopRight = 2,
BottomRight = 3,
BottomLeft = 4,
LeftTop = 5,
RightTop = 6,
RightBottom = 7,
LftBottom = 8
}
//
// Exposure programs
//
//
//
// \[altair\] 10.09.2003 Created
//
public enum ExposurePrograms
{
Manual = 1,
Normal = 2,
AperturePriority = 3,
ShutterPriority = 4,
Creative = 5,
Action = 6,
Portrait = 7,
Landscape = 8,
}
//
// Exposure metering modes
//
//
//
// \[altair\] 10.09.2003 Created
//
public enum ExposureMeteringModes
{
Unknown = 0,
Average = 1,
CenterWeightedAverage = 2,
Spot = 3,
MultiSpot = 4,
MultiSegment = 5,
Partial = 6,
Other = 255
}
//
// Flash activity modes
//
//
//
// \[altair\] 10.09.2003 Created
//
public enum FlashModes
{
NotFired = 0,
Fired = 1,
FiredButNoStrobeReturned = 5,
FiredAndStrobeReturned = 7,
}
//
// Possible light sources (white balance)
//
//
//
// \[altair\] 10.09.2003 Created
//
public enum LightSources
{
Unknown = 0,
Daylight = 1,
Fluorescent = 2,
Tungsten = 3,
Flash = 10,
StandardLightA = 17,
StandardLightB = 18,
StandardLightC = 19,
D55 = 20,
D65 = 21,
D75 = 22,
Other = 255
}
//
// EXIF data types
//
//
//
// \[altair\] 12.6.2004 Created
//
public enum ExifDataTypes : short
{
UnsignedByte = 1,
AsciiString = 2,
UnsignedShort = 3,
UnsignedLong = 4,
UnsignedRational = 5,
SignedByte = 6,
Undefined = 7,
SignedShort = 8,
SignedLong = 9,
SignedRational = 10,
SingleFloat = 11,
DoubleFloat = 12
}
//
// Represents rational which is type of some Exif properties
//
//
//
// \[altair\] 10.09.2003 Created
//
public struct Rational
{
public Int32 Numerator;
public Int32 Denominator;
//
// Converts rational to string representation
//
// Optional, default "/". String to be used as delimiter of components.
// String representation of the rational.
//
//
// \[altair\] 10.09.2003 Created
//
public override string ToString()
{
return ToString("/");
}
public string ToString(string Delimiter)
{
return Numerator + "/" + Denominator;
}
//
// Converts rational to double precision real number
//
// The rational as double precision real number.
//
//
// \[altair\] 10.09.2003 Created
//
public double ToDouble()
{
return (double)Numerator / Denominator;
}
}
#endregion
//
// Initializes new instance of this class.
//
// Bitmap to read exif information from
//
//
// \[altair\] 10.09.2003 Created
//
public ExifManager(System.Drawing.Bitmap Bitmap)
{
if (Bitmap == null)
throw new ArgumentNullException("Bitmap");
this.\_Image = Bitmap;
}
//
// Initializes new instance of this class.
//
// Name of file to be loaded
//
//
// \[altair\] 13.06.2004 Created
//
public ExifManager(string FileName)
{
this.\_Image = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromFile(FileName);
}
//
// Get or set encoding used for string metadata
//
// Encoding used for string metadata
// Default encoding is UTF-8
//
// \[altair\] 11.07.2004 Created
// \[altair\] 05.09.2005 Changed from shared to instance member
//
public System.Text.Encoding Encoding
{
get
{
return this.\_Encoding;
}
set
{
if (value == null)
throw new ArgumentNullException();
this.\_Encoding = value;
}
}
//
// Returns copy of bitmap this instance is working on
//
//
//
//
// \[altair\] 13.06.2004 Created
//
public System.Drawing.Bitmap GetBitmap()
{
return (System.Drawing.Bitmap)this.\_Image.Clone();
}
//
// Returns all available data in formatted string form
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public override string ToString()
{
System.Text.StringBuilder SB = new StringBuilder();
SB.Append("Image:");
SB.Append("ntDimensions: " + this.Width + " x " + this.Height + " px");
SB.Append("ntResolution: " + this.ResolutionX + " x " + this.ResolutionY + " dpi");
SB.Append("ntOrientation: " + Enum.GetName(typeof(Orientations), this.Orientation));
SB.Append("ntTitle: " + this.Title);
SB.Append("ntDescription: " + this.Description);
SB.Append("ntCopyright: " + this.Copyright);
SB.Append("nEquipment:");
SB.Append("ntMaker: " + this.EquipmentMaker);
SB.Append("ntModel: " + this.EquipmentModel);
SB.Append("ntSoftware: " + this.Software);
SB.Append("nDate and time:");
SB.Append("ntGeneral: " + this.DateTimeLastModified.ToString());
SB.Append("ntOriginal: " + this.DateTimeOriginal.ToString());
SB.Append("ntDigitized: " + this.DateTimeDigitized.ToString());
SB.Append("nShooting conditions:");
SB.Append("ntExposure time: " + this.ExposureTime.ToString("N4") + " s");
SB.Append("ntExposure program: " + Enum.GetName(typeof(ExposurePrograms), this.ExposureProgram));
SB.Append("ntExposure mode: " + Enum.GetName(typeof(ExposureMeteringModes), this.ExposureMeteringMode));
SB.Append("ntAperture: F" + this.Aperture.ToString("N2"));
SB.Append("ntISO sensitivity: " + this.ISO);
SB.Append("ntSubject distance: " + this.SubjectDistance.ToString("N2") + " m");
SB.Append("ntFocal length: " + this.FocalLength);
SB.Append("ntFlash: " + Enum.GetName(typeof(FlashModes), this.FlashMode));
SB.Append("ntLight source (WB): " + Enum.GetName(typeof(LightSources), this.LightSource));
//SB.Replace("n", vbCrLf);
//SB.Replace("t", vbTab);
return SB.ToString();
}
#region Nicely formatted well-known properties
//
// Brand of equipment (EXIF EquipMake)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public string EquipmentMaker
{
get
{
return this.GetPropertyString((int)TagNames.EquipMake);
}
}
//
// Model of equipment (EXIF EquipModel)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public string EquipmentModel
{
get
{
return this.GetPropertyString((int)TagNames.EquipModel);
}
}
//
// Software used for processing (EXIF Software)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public string Software
{
get
{
return this.GetPropertyString((int)TagNames.SoftwareUsed);
}
}
//
// Orientation of image (position of row 0, column 0) (EXIF Orientation)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public Orientations Orientation
{
get
{
Int32 X = this.GetPropertyInt16((int)TagNames.Orientation);
if (!Enum.IsDefined(typeof(Orientations), X))
return Orientations.TopLeft;
else
return (Orientations)Enum.Parse(typeof(Orientations), Enum.GetName(typeof(Orientations), X));
}
}
//
// Time when image was last modified (EXIF DateTime).
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public DateTime DateTimeLastModified
{
get
{
try
{
return DateTime.ParseExact(this.GetPropertyString((int)TagNames.DateTime), @"yyyy:MM:dd HH:mm:ss", null);
}
catch
{
return DateTime.MinValue;
}
}
set
{
try
{
this.SetPropertyString((int)TagNames.DateTime, value.ToString(@"yyyy:MM:dd HH:mm:ss"));
}
catch
{ }
}
}
//
// Time when image was taken (EXIF DateTimeOriginal).
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public DateTime DateTimeOriginal
{
get
{
try
{
return DateTime.ParseExact(this.GetPropertyString((int)TagNames.ExifDTOrig), @"yyyy:MM:dd HH:mm:ss", null);
}
catch
{
return DateTime.MinValue;
}
}
set
{
try
{
this.SetPropertyString((int)TagNames.ExifDTOrig, value.ToString(@"yyyy:MM:dd HH:mm:ss"));
}
catch
{ }
}
}
//
// Time when image was digitized (EXIF DateTimeDigitized).
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public DateTime DateTimeDigitized
{
get
{
try
{
return DateTime.ParseExact(this.GetPropertyString((int)TagNames.ExifDTDigitized), @"yyyy:MM:dd HH:mm:ss", null);
}
catch
{
return DateTime.MinValue;
}
}
set
{
try
{
this.SetPropertyString((int)TagNames.ExifDTDigitized, value.ToString(@"yyyy:MM:dd HH:mm:ss"));
}
catch
{ }
}
}
//
// Image width
//
//
//
//
// \[altair\] 10.09.2003 Created
// \[altair\] 04.09.2005 Changed output to Int32, load from image instead of EXIF
//
public Int32 Width
{
get { return this.\_Image.Width; }
}
//
// Image height
//
//
//
//
// \[altair\] 10.09.2003 Created
// \[altair\] 04.09.2005 Changed output to Int32, load from image instead of EXIF
//
public Int32 Height
{
get { return this.\_Image.Height; }
}
//
// X resolution in dpi (EXIF XResolution/ResolutionUnit)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public double ResolutionX
{
get
{
double R = this.GetPropertyRational((int)TagNames.XResolution).ToDouble();
if (this.GetPropertyInt16((int)TagNames.ResolutionUnit) == 3)
{
// -- resolution is in points/cm
return R \* 2.54;
}
else
{
// -- resolution is in points/inch
return R;
}
}
}
//
// Y resolution in dpi (EXIF YResolution/ResolutionUnit)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public double ResolutionY
{
get
{
double R = this.GetPropertyRational((int)TagNames.YResolution).ToDouble();
if (this.GetPropertyInt16((int)TagNames.ResolutionUnit) == 3)
{
// -- resolution is in points/cm
return R \* 2.54;
}
else
{
// -- resolution is in points/inch
return R;
}
}
}
//
// Image title (EXIF ImageTitle)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public string Title
{
get
{
return this.GetPropertyString((int)TagNames.ImageTitle);
}
set
{
try
{
this.SetPropertyString((int)TagNames.ImageTitle, value);
}
catch { }
}
}
//
// User comment (EXIF UserComment)
//
//
//
//
// \[altair\] 13.06.2004 Created
//
public string UserComment
{
get
{
return this.GetPropertyString((int)TagNames.ExifUserComment);
}
set
{
try
{
this.SetPropertyString((int)TagNames.ExifUserComment, value);
}
catch { }
}
}
//
// Artist name (EXIF Artist)
//
//
//
//
// \[altair\] 13.06.2004 Created
//
public string Artist
{
get
{
return this.GetPropertyString((int)TagNames.Artist);
}
set
{
try
{
this.SetPropertyString((int)TagNames.Artist, value);
}
catch { }
}
}
//
// Image description (EXIF ImageDescription)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public string Description
{
get
{
return this.GetPropertyString((int)TagNames.ImageDescription);
}
set
{
try
{
this.SetPropertyString((int)TagNames.ImageDescription, value);
}
catch { }
}
}
//
// Image copyright (EXIF Copyright)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public string Copyright
{
get
{
return this.GetPropertyString((int)TagNames.Copyright);
}
set
{
try
{
this.SetPropertyString((int)TagNames.Copyright, value);
}
catch { }
}
}
//
// Exposure time in seconds (EXIF ExifExposureTime/ExifShutterSpeed)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public double ExposureTimeAbs
{
get
{
if (this.IsPropertyDefined((int)TagNames.ExifExposureTime))
// -- Exposure time is explicitly specified
return this.GetPropertyRational((int)TagNames.ExifExposureTime).ToDouble();
else
if (this.IsPropertyDefined((int)TagNames.ExifShutterSpeed))
//'-- Compute exposure time from shutter spee
return (1 / Math.Pow(2, this.GetPropertyRational((int)TagNames.ExifShutterSpeed).ToDouble()));
else
// -- Can't figure out
return 0;
}
}
public Rational ExposureTime
{
get
{
if (this.IsPropertyDefined((int)TagNames.ExifExposureTime))
// -- Exposure time is explicitly specified
return this.GetPropertyRational((int)TagNames.ExifExposureTime);
else
return new Rational();
}
}
//
// Aperture value as F number (EXIF ExifFNumber/ExifApertureValue)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public double Aperture
{
get
{
if (this.IsPropertyDefined((int)TagNames.ExifFNumber))
return this.GetPropertyRational((int)TagNames.ExifFNumber).ToDouble();
else
if (this.IsPropertyDefined((int)TagNames.ExifAperture))
return Math.Pow(System.Math.Sqrt(2), this.GetPropertyRational((int)TagNames.ExifAperture).ToDouble());
else
return 0;
}
}
//
// Exposure program used (EXIF ExifExposureProg)
//
//
// If not specified, returns Normal (2)
//
// \[altair\] 10.09.2003 Created
//
public ExposurePrograms ExposureProgram
{
get
{
Int32 X = this.GetPropertyInt16((int)TagNames.ExifExposureProg);
if (Enum.IsDefined(typeof(ExposurePrograms), X))
return (ExposurePrograms)Enum.Parse(typeof(ExposurePrograms), Enum.GetName(typeof(ExposurePrograms), X));
else
return ExposurePrograms.Normal;
}
}
//
// ISO sensitivity
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public Int16 ISO
{
get { return this.GetPropertyInt16((int)TagNames.ExifISOSpeed); }
}
//
// Subject distance in meters (EXIF SubjectDistance)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public double SubjectDistance
{
get { return this.GetPropertyRational((int)TagNames.ExifSubjectDist).ToDouble(); }
}
//
// Exposure method metering mode used (EXIF MeteringMode)
//
//
// If not specified, returns Unknown (0)
//
// \[altair\] 10.09.2003 Created
//
public ExposureMeteringModes ExposureMeteringMode
{
get
{
Int32 X = this.GetPropertyInt16((int)TagNames.ExifMeteringMode);
if (Enum.IsDefined(typeof(ExposureMeteringModes), X))
return (ExposureMeteringModes)Enum.Parse(typeof(ExposureMeteringModes), Enum.GetName(typeof(ExposureMeteringModes), X));
else
return ExposureMeteringModes.Unknown;
}
}
//
// Focal length of lenses in mm (EXIF FocalLength)
//
//
//
//
// \[altair\] 10.09.2003 Created
//
public double FocalLength
{
get { return this.GetPropertyRational((int)TagNames.ExifFocalLength).ToDouble(); }
}
//
// Flash mode (EXIF Flash)
//
//
// If not present, value NotFired (0) is returned
//
// \[altair\] 10.09.2003 Created
//
public FlashModes FlashMode
{
get
{
Int32 X = this.GetPropertyInt16((int)TagNames.ExifFlash);
if (Enum.IsDefined(typeof(FlashModes), X))
return (FlashModes)Enum.Parse(typeof(FlashModes), Enum.GetName(typeof(FlashModes), X));
else
return FlashModes.NotFired;
}
}
//
// Light source / white balance (EXIF LightSource)
//
//
// If not specified, returns Unknown (0).
//
// \[altair\] 10.09.2003 Created
//
public LightSources LightSource
{
get
{
Int32 X = this.GetPropertyInt16((int)TagNames.ExifLightSource);
if (Enum.IsDefined(typeof(LightSources), X))
return (LightSources)Enum.Parse(typeof(LightSources), Enum.GetName(typeof(LightSources), X));
else
return LightSources.Unknown;
}
}
#endregion
#region Support methods for working with EXIF properties
//
// Checks if current image has specified certain property
//
//
// True if image has specified property, False otherwise.
//
//
// \[altair\] 10.09.2003 Created
//
public bool IsPropertyDefined(Int32 PID)
{
return (Array.IndexOf(this.\_Image.PropertyIdList, PID) > -1);
}
//
// Gets specified Int32 property
//
// Property ID
// Optional, default 0. Default value returned if property is not present.
// Value of property or DefaultValue if property is not present.
//
//
// \[altair\] 10.09.2003 Created
//
public Int32 GetPropertyInt32(Int32 PID)
{
return GetPropertyInt32(PID, 0);
}
public Int32 GetPropertyInt32(Int32 PID, Int32 DefaultValue)
{
if (IsPropertyDefined(PID))
return GetInt32(this.\_Image.GetPropertyItem(PID).Value);
else
return DefaultValue;
}
//
// Gets specified Int16 property
//
// Property ID
// Optional, default 0. Default value returned if property is not present.
// Value of property or DefaultValue if property is not present.
//
//
// \[altair\] 10.09.2003 Created
//
public Int16 GetPropertyInt16(Int32 PID)
{
return GetPropertyInt16(PID, 0);
}
public Int16 GetPropertyInt16(Int32 PID, Int16 DefaultValue)
{
if (IsPropertyDefined(PID))
return GetInt16(this.\_Image.GetPropertyItem(PID).Value);
else
return DefaultValue;
}
//
// Gets specified string property
//
// Property ID
// Optional, default String.Empty. Default value returned if property is not present.
//
// Value of property or DefaultValue if property is not present.
//
// \[altair\] 10.09.2003 Created
//
public string GetPropertyString(Int32 PID)
{
return GetPropertyString(PID, "");
}
public string GetPropertyString(Int32 PID, string DefaultValue)
{
if (IsPropertyDefined(PID))
return GetString(this.\_Image.GetPropertyItem(PID).Value);
else
return DefaultValue;
}
//
// Gets specified property in raw form
//
// Property ID
// Optional, default Nothing. Default value returned if property is not present.
//
// Is recommended to use typed methods (like etc.) instead, when possible.
//
// \[altair\] 05.09.2005 Created
//
public byte\[\] GetProperty(Int32 PID, byte\[\] DefaultValue)
{
if (IsPropertyDefined(PID))
return this.\_Image.GetPropertyItem(PID).Value;
else
return DefaultValue;
}
public byte\[\] GetProperty(Int32 PID)
{
return GetProperty(PID, null);
}
//
// Gets specified rational property
//
// Property ID
//
// Value of property or 0/1 if not present.
//
// \[altair\] 10.09.2003 Created
//
public Rational GetPropertyRational(Int32 PID)
{
if (IsPropertyDefined(PID))
return GetRational(this.\_Image.GetPropertyItem(PID).Value);
else
{
Rational R;
R.Numerator = 0;
R.Denominator = 1;
return R;
}
}
//
// Sets specified string property
//
// Property ID
// Value to be set
//
//
// \[altair\] 12.6.2004 Created
//
public void SetPropertyString(Int32 PID, string Value)
{
byte\[\] Data = this.\_Encoding.GetBytes(Value + ' ');
SetProperty(PID, Data, ExifDataTypes.AsciiString);
}
//
// Sets specified Int16 property
//
// Property ID
// Value to be set
//
//
// \[altair\] 12.6.2004 Created
//
public void SetPropertyInt16(Int32 PID, Int16 Value)
{
byte\[\] Data = new byte\[2\];
Data\[0\] = (byte)(Value & 0xFF);
Data\[1\] = (byte)((Value & 0xFF00) >> 8);
SetProperty(PID, Data, ExifDataTypes.SignedShort);
}
//
// Sets specified Int32 property
//
// Property ID
// Value to be set
//
//
// \[altair\] 13.06.2004 Created
//
public void SetPropertyInt32(Int32 PID, Int32 Value)
{
byte\[\] Data = new byte\[4\];
for (int I = 0; I < 4; I++)
{
Data\[I\] = (byte)(Value & 0xFF);
Value >>= 8;
}
SetProperty(PID, Data, ExifDataTypes.SignedLong);
}
//
// Sets specified property in raw form
//
// Property ID
// Raw data
// EXIF data type
// Is recommended to use typed methods (like etc.) instead, when possible.
//
// \[altair\] 12.6.2004 Created
//
public void SetProperty(Int32 PID, byte\[\] Data, ExifDataTypes Type)
{
System.Drawing.Imaging.PropertyItem P = this.\_Image.PropertyItems\[0\];
P.Id = PID;
P.Value = Data;
P.Type = (Int16)Type;
P.Len = Data.Length;
this.\_Image.SetPropertyItem(P);
}
//
// Reads Int32 from EXIF bytearray.
//
// EXIF bytearray to process
//
//
//
// \[altair\] 10.09.2003 Created
// \[altair\] 05.09.2005 Changed from public shared to private instance method
//
private Int32 GetInt32(byte\[\] B)
{
if (B.Length < 4)
throw new ArgumentException("Data too short (4 bytes expected)", "B");
return B\[3\] << 24 | B\[2\] << 16 | B\[1\] << 8 | B\[0\];
}
//
// Reads Int16 from EXIF bytearray.
//
// EXIF bytearray to process
//
//
//
// \[altair\] 10.09.2003 Created
// \[altair\] 05.09.2005 Changed from public shared to private instance method
//
private Int16 GetInt16(byte\[\] B)
{
if (B.Length < 2)
throw new ArgumentException("Data too short (2 bytes expected)", "B");
return (short)(B\[1\] << 8 | B\[0\]);
}
//
// Reads string from EXIF bytearray.
//
// EXIF bytearray to process
//
//
//
// \[altair\] 10.09.2003 Created
// \[altair\] 05.09.2005 Changed from public shared to private instance method
//
private string GetString(byte\[\] B)
{
string R = this.\_Encoding.GetString(B);
if (R.EndsWith(" "))
R = R.Substring(0, R.Length - 1);
return R;
}
//
// Reads rational from EXIF bytearray.
//
// EXIF bytearray to process
//
//
//
// \[altair\] 10.09.2003 Created
// \[altair\] 05.09.2005 Changed from public shared to private instance method
//
private Rational GetRational(byte\[\] B)
{
Rational R = new Rational();
byte\[\] N = new byte\[4\];
byte\[\] D = new byte\[4\];
Array.Copy(B, 0, N, 0, 4);
Array.Copy(B, 4, D, 0, 4);
R.Denominator = this.GetInt32(D);
R.Numerator = this.GetInt32(N);
return R;
}
#endregion
#region " IDisposable implementation "
//
// Disposes unmanaged resources of this class
//
//
//
// \[altair\] 10.09.2003 Created
//
public void Dispose()
{
this.\_Image.Dispose();
}
#endregion
}
}