Catalog/imagecatalog.backup/ExifReader.cs

1190 lines
41 KiB
C#
Raw Normal View History

2024-10-14 18:54:30 +02:00
/// -----------------------------------------------------------------------------
/// <summary>
/// Utility class for reading EXIF data from images. Provides abstraction
/// for most common data and generic utilities for work with all other.
/// </summary>
/// <remarks>
/// Copyright (c) Michal A. Valášek - Altair Communications, 2003
/// Copmany: http://software.altaircom.net * support@altaircom.net
/// Private: http://www.rider.cz * developer@rider.cz
/// This is free software licensed under GNU Lesser General Public License
/// </remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
using System;
using System.Drawing;
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
namespace ImageCatalog
{
public class ExifReader : IDisposable
{
private Bitmap Image;
/// -----------------------------------------------------------------------------
/// <summary>
/// Contains possible values of EXIF tag names (ID)
/// </summary>
/// <remarks>See GdiPlusImaging.h</remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public enum TagNames
{
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
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Real position of 0th row and column of picture
/// </summary>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public enum Orientations
{
TopLeft = 1,
TopRight = 2,
BottomRight = 3,
BottomLeft = 4,
LeftTop = 5,
RightTop = 6,
RightBottom = 7,
LftBottom = 8
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Exposure programs
/// </summary>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public enum ExposurePrograms
{
Manual = 1,
Normal = 2,
AperturePriority = 3,
ShutterPriority = 4,
Creative = 5,
Action = 6,
Portrait = 7,
Landscape = 8
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Exposure metering modes
/// </summary>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public enum ExposureMeteringModes
{
Unknown = 0,
Average = 1,
CenterWeightedAverage = 2,
Spot = 3,
MultiSpot = 4,
MultiSegment = 5,
Partial = 6,
Other = 255
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Flash activity modes
/// </summary>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public enum FlashModes
{
NotFired = 0,
Fired = 1,
FiredButNoStrobeReturned = 5,
FiredAndStrobeReturned = 7
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Possible light sources (white balance)
/// </summary>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
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
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Represents rational which is type of some Exif properties
/// </summary>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public struct Rational
{
public int Numerator;
public int Denominator;
/// -----------------------------------------------------------------------------
/// <summary>
/// Converts rational to string representation
/// </summary>
/// <param name="Delimiter">Optional, default "/". String to be used as delimiter of components.</param>
/// <returns>String representation of the rational.</returns>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public new string ToString(string Delimiter = "/")
{
return Numerator + Delimiter + Denominator;
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Converts rational to double precision real number
/// </summary>
/// <returns>The rational as double precision real number.</returns>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public double ToDouble()
{
return Numerator / (double)Denominator;
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Initializes new instance of this class.
/// </summary>
/// <param name="Bitmap">Bitmap to read exif information from</param>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public ExifReader(Bitmap Bitmap)
{
if (Bitmap is null)
throw new ArgumentNullException("Bitmap");
Image = Bitmap;
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Returns all available data in formatted string form
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public override string ToString()
{
var SB = new System.Text.StringBuilder();
SB.Append("Image:");
SB.Append(@"\n\tDimensions: " + Width + " x " + Height + " px");
SB.Append(@"\n\tResolution: " + ResolutionX + " x " + ResolutionY + " dpi");
SB.Append(@"\n\tOrientation: " + Enum.GetName(typeof(Orientations), Orientation));
SB.Append(@"\n\tTitle: " + Title);
SB.Append(@"\n\tDescription: " + Description);
SB.Append(@"\n\tCopyright: " + Copyright);
SB.Append(@"\nEquipment:");
SB.Append(@"\n\tMaker: " + EquipmentMaker);
SB.Append(@"\n\tModel: " + EquipmentModel);
SB.Append(@"\n\tSoftware: " + Software);
SB.Append(@"\nDate and time:");
SB.Append(@"\n\tGeneral: " + DateTimeLastModified.ToString());
SB.Append(@"\n\tOriginal: " + DateTimeOriginal.ToString());
SB.Append(@"\n\tDigitized: " + DateTimeDigitized.ToString());
SB.Append(@"\nShooting conditions:");
SB.Append(@"\n\tExposure time: " + ExposureTime.ToString("N4") + " s");
SB.Append(@"\n\tExposure program: " + Enum.GetName(typeof(ExposurePrograms), ExposureProgram));
SB.Append(@"\n\tExposure mode: " + Enum.GetName(typeof(ExposureMeteringModes), ExposureMeteringMode));
SB.Append(@"\n\tAperture: F" + Aperture.ToString("N2"));
SB.Append(@"\n\tISO sensitivity: " + ISO);
SB.Append(@"\n\tSubject distance: " + SubjectDistance.ToString("N2") + " m");
SB.Append(@"\n\tFocal length: " + FocalLength);
SB.Append(@"\n\tFlash: " + Enum.GetName(typeof(FlashModes), FlashMode));
SB.Append(@"\n\tLight source (WB): " + Enum.GetName(typeof(LightSources), LightSource));
SB.Append(@"\n\nCopyright (c) Michal A. Valasek - Altair Communications, 2003");
SB.Append(@"\nhttp://software.altaircom.net * support@altaircom.net");
SB.Replace(@"\n", Constants.vbCrLf);
SB.Replace(@"\t", Constants.vbTab);
return SB.ToString();
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Brand of equipment (EXIF EquipMake)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public string EquipmentMaker
{
get
{
return GetPropertyString((int)TagNames.EquipMake);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Model of equipment (EXIF EquipModel)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public string EquipmentModel
{
get
{
return GetPropertyString((int)TagNames.EquipModel);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Software used for processing (EXIF Software)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public string Software
{
get
{
return GetPropertyString((int)TagNames.SoftwareUsed);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Orientation of image (position of row 0, column 0) (EXIF Orientation)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public Orientations Orientation
{
get
{
int X = GetPropertyInt16((int)TagNames.Orientation);
if (!Enum.IsDefined(typeof(Orientations), X))
{
return Orientations.TopLeft;
}
else
{
return (Orientations)Conversions.ToInteger(Enum.Parse(typeof(Orientations), Enum.GetName(typeof(Orientations), X)));
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Time when image was last modified (EXIF DateTime).
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public DateTime DateTimeLastModified
{
get
{
try
{
return DateTime.ParseExact(GetPropertyString((int)TagNames.DateTime), @"yyyy\:MM\:dd HH\:mm\:ss", null);
}
catch (Exception ex)
{
return DateTime.MinValue;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Time when image was taken (EXIF DateTimeOriginal).
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public DateTime DateTimeOriginal
{
get
{
try
{
return DateTime.ParseExact(GetPropertyString((int)TagNames.ExifDTOrig), @"yyyy\:MM\:dd HH\:mm\:ss", null);
}
catch (Exception ex)
{
return DateTime.MinValue;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Time when image was digitized (EXIF DateTimeDigitized).
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public DateTime DateTimeDigitized
{
get
{
try
{
return DateTime.ParseExact(GetPropertyString((int)TagNames.ExifDTDigitized), @"yyyy\:MM\:dd HH\:mm\:ss", null);
}
catch (Exception ex)
{
return DateTime.MinValue;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Image width
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public short Width
{
get
{
return GetPropertyInt16((int)TagNames.ImageWidth);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Image height
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public short Height
{
get
{
return GetPropertyInt16((int)TagNames.ImageHeight);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// X resolution in dpi (EXIF XResolution/ResolutionUnit)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public double ResolutionX
{
get
{
double R = GetPropertyRational((int)TagNames.XResolution).ToDouble();
if (GetPropertyInt16((int)TagNames.ResolutionUnit) == 3)
{
// -- resolution is in points/cm
return R * 2.54d;
}
else
{
// -- resolution is in points/inch
return R;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Y resolution in dpi (EXIF YResolution/ResolutionUnit)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public double ResolutionY
{
get
{
double R = GetPropertyRational((int)TagNames.YResolution).ToDouble();
if (GetPropertyInt16((int)TagNames.ResolutionUnit) == 3)
{
// -- resolution is in points/cm
return R * 2.54d;
}
else
{
// -- resolution is in points/inch
return R;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Image title (EXIF ImageTitle)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public string Title
{
get
{
return GetPropertyString((int)TagNames.ImageTitle);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Image description (EXIF ImageDescription)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public string Description
{
get
{
return GetPropertyString((int)TagNames.ImageDescription);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Image copyright (EXIF Copyright)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public string Copyright
{
get
{
return GetPropertyString((int)TagNames.Copyright);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Exposure time in seconds (EXIF ExifExposureTime/ExifShutterSpeed)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public double ExposureTime
{
get
{
if (IsPropertyDefined((int)TagNames.ExifExposureTime))
{
// -- Exposure time is explicitly specified
return GetPropertyRational((int)TagNames.ExifExposureTime).ToDouble();
}
else if (IsPropertyDefined((int)TagNames.ExifShutterSpeed))
{
// -- Compute exposure time from shutter speed
return 1d / Math.Pow(2d, GetPropertyRational((int)TagNames.ExifShutterSpeed).ToDouble());
}
else
{
// -- Can't figure out
return 0d;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Aperture value as F number (EXIF ExifFNumber/ExifApertureValue)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public double Aperture
{
get
{
if (IsPropertyDefined((int)TagNames.ExifFNumber))
{
return GetPropertyRational((int)TagNames.ExifFNumber).ToDouble();
}
else if (IsPropertyDefined((int)TagNames.ExifAperture))
{
return Math.Pow(Math.Sqrt(2d), GetPropertyRational((int)TagNames.ExifAperture).ToDouble());
}
else
{
return 0d;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Exposure program used (EXIF ExifExposureProg)
/// </summary>
/// <value></value>
/// <remarks>If not specified, returns Normal (2)</remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public ExposurePrograms ExposureProgram
{
get
{
int X = GetPropertyInt16((int)TagNames.ExifExposureProg);
if (Enum.IsDefined(typeof(ExposurePrograms), X))
{
return (ExposurePrograms)Conversions.ToInteger(Enum.Parse(typeof(ExposurePrograms), Enum.GetName(typeof(ExposurePrograms), X)));
}
else
{
return ExposurePrograms.Normal;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// ISO sensitivity
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public short ISO
{
get
{
return GetPropertyInt16((int)TagNames.ExifISOSpeed);
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Subject distance in meters (EXIF SubjectDistance)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public double SubjectDistance
{
get
{
return GetPropertyRational((int)TagNames.ExifSubjectDist).ToDouble();
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Exposure method metering mode used (EXIF MeteringMode)
/// </summary>
/// <value></value>
/// <remarks>If not specified, returns Unknown (0)</remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public ExposureMeteringModes ExposureMeteringMode
{
get
{
int X = GetPropertyInt16((int)TagNames.ExifMeteringMode);
if (Enum.IsDefined(typeof(ExposureMeteringModes), X))
{
return (ExposureMeteringModes)Conversions.ToInteger(Enum.Parse(typeof(ExposureMeteringModes), Enum.GetName(typeof(ExposureMeteringModes), X)));
}
else
{
return ExposureMeteringModes.Unknown;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Focal length of lenses in mm (EXIF FocalLength)
/// </summary>
/// <value></value>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public double FocalLength
{
get
{
return GetPropertyRational((int)TagNames.ExifFocalLength).ToDouble();
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Flash mode (EXIF Flash)
/// </summary>
/// <value></value>
/// <remarks>If not present, value NotFired (0) is returned</remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public FlashModes FlashMode
{
get
{
int X = GetPropertyInt16((int)TagNames.ExifFlash);
if (Enum.IsDefined(typeof(FlashModes), X))
{
return (FlashModes)Conversions.ToInteger(Enum.Parse(typeof(FlashModes), Enum.GetName(typeof(FlashModes), X)));
}
else
{
return FlashModes.NotFired;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Light source / white balance (EXIF LightSource)
/// </summary>
/// <value></value>
/// <remarks>If not specified, returns Unknown (0).</remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public LightSources LightSource
{
get
{
int X = GetPropertyInt16((int)TagNames.ExifLightSource);
if (Enum.IsDefined(typeof(LightSources), X))
{
return (LightSources)Conversions.ToInteger(Enum.Parse(typeof(LightSources), Enum.GetName(typeof(LightSources), X)));
}
else
{
return LightSources.Unknown;
}
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Checks if current image has specified certain property
/// </summary>
/// <param name="PID"></param>
/// <returns>True if image has specified property, False otherwise.</returns>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public bool IsPropertyDefined(int PID)
{
return Array.IndexOf(Image.PropertyIdList, PID) > -1;
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Gets specified Int32 property
/// </summary>
/// <param name="PID">Property ID</param>
/// <param name="DefaultValue">Optional, default 0. Default value returned if property is not present.</param>
/// <remarks>Value of property or DefaultValue if property is not present.</remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public int GetPropertyInt32(int PID, int DefaultValue = 0)
{
if (IsPropertyDefined(PID))
{
return GetInt32(Image.GetPropertyItem(PID).Value);
}
else
{
return DefaultValue;
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Gets specified Int16 property
/// </summary>
/// <param name="PID">Property ID</param>
/// <param name="DefaultValue">Optional, default 0. Default value returned if property is not present.</param>
/// <remarks>Value of property or DefaultValue if property is not present.</remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public short GetPropertyInt16(int PID, short DefaultValue = 0)
{
if (IsPropertyDefined(PID))
{
return GetInt16(Image.GetPropertyItem(PID).Value);
}
else
{
return DefaultValue;
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Gets specified string property
/// </summary>
/// <param name="PID">Property ID</param>
/// <param name="DefaultValue">Optional, default String.Empty. Default value returned if property is not present.</param>
/// <returns></returns>
/// <remarks>Value of property or DefaultValue if property is not present.</remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public string GetPropertyString(int PID, string DefaultValue = "")
{
if (IsPropertyDefined(PID))
{
return GetString(Image.GetPropertyItem(PID).Value);
}
else
{
return DefaultValue;
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Gets specified rational property
/// </summary>
/// <param name="PID">Property ID</param>
/// <returns></returns>
/// <remarks>Value of property or 0/1 if not present.</remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public Rational GetPropertyRational(int PID)
{
if (IsPropertyDefined(PID))
{
return GetRational(Image.GetPropertyItem(PID).Value);
}
else
{
Rational R;
R.Numerator = 0;
R.Denominator = 1;
return R;
}
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Reads Int32 from EXIF bytearray.
/// </summary>
/// <param name="B">EXIF bytearray to process</param>
/// <returns></returns>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public static int 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];
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Reads Int16 from EXIF bytearray.
/// </summary>
/// <param name="B">EXIF bytearray to process</param>
/// <returns></returns>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public static short GetInt16(byte[] B)
{
if (B.Length < 2)
throw new ArgumentException("Data too short (2 bytes expected)", "B");
return (short)(B[1] << 8 | B[0]);
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Reads string from EXIF bytearray.
/// </summary>
/// <param name="B">EXIF bytearray to process</param>
/// <returns></returns>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public static string GetString(byte[] B)
{
string R = System.Text.Encoding.ASCII.GetString(B);
if (R.EndsWith(Constants.vbNullChar))
R = R.Substring(0, R.Length - 1);
return R;
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Reads rational from EXIF bytearray.
/// </summary>
/// <param name="B">EXIF bytearray to process</param>
/// <returns></returns>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public static Rational GetRational(byte[] B)
{
var R = new Rational();
byte[] N = new byte[4], D = new byte[4];
Array.Copy(B, 0, N, 0, 4);
Array.Copy(B, 4, D, 0, 4);
R.Denominator = GetInt32(D);
R.Numerator = GetInt32(N);
return R;
}
/// -----------------------------------------------------------------------------
/// <summary>
/// Disposes unmanaged resources of this class
/// </summary>
/// <remarks></remarks>
/// <history>
/// [altair] 10.9.2003 Created
/// </history>
/// -----------------------------------------------------------------------------
public void Dispose()
{
Image.Dispose();
}
}
}