EXIFextractor.cs
EXIFextractor.cs
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();
}
}
}
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();
}
}
}
translation.cs
translation.cs
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 " );
this .Add( 0x8825 , " gps ifd " );
this .Add( 0xfe , " new subfile type " );
this .Add( 0xff , " subfile type " );
this .Add( 0x100 , " image width " );
this .Add( 0x101 , " image height " );
this .Add( 0x102 , " bits per sample " );
this .Add( 0x103 , " compression " );
this .Add( 0x106 , " photometric interp " );
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 " );
this .Add( 0x110 , " equip model " );
this .Add( 0x111 , " strip offsets " );
this .Add( 0x112 , " orientation " );
this .Add( 0x115 , " samples perpixel " );
this .Add( 0x116 , " rows per strip " );
this .Add( 0x117 , " strip bytes count " );
this .Add( 0x118 , " min sample value " );
this .Add( 0x119 , " max sample value " );
this .Add( 0x11a , " x resolution " );
this .Add( 0x11b , " y resolution " );
this .Add( 0x11c , " planar config " );
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 " );
this .Add( 0x129 , " page number " );
this .Add( 0x12d , " transfer funcition " );
this .Add( 0x131 , " software used " );
this .Add( 0x132 , " date time " );
this .Add( 0x13b , " artist " );
this .Add( 0x13c , " host computer " );
this .Add( 0x13d , " predictor " );
this .Add( 0x13e , " white point " );
this .Add( 0x13f , " primary chromaticities " );
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 " );
this .Add( 0x201 , " jpeg interformat " );
this .Add( 0x202 , " jpeg interlength " );
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 " );
this .Add( 0x209 , " jpeg actables " );
this .Add( 0x211 , " ycbcr coefficients " );
this .Add( 0x212 , " ycbcr subsampling " );
this .Add( 0x213 , " ycbcr positioning " );
this .Add( 0x214 , " ref black white " );
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 " );
this .Add( 0x8822 , " exposure prog " );
this .Add( 0x8824 , " spectral sense " );
this .Add( 0x8827 , " iso speed " );
this .Add( 0x8828 , " oecf " );
this .Add( 0x9000 , " ver " );
this .Add( 0x9003 , " dtorig " );
this .Add( 0x9004 , " dtdigitized " );
this .Add( 0x9101 , " compconfig " );
this .Add( 0x9102 , " compbpp " );
this .Add( 0x9201 , " shutter speed " );
this .Add( 0x9202 , " aperture " );
this .Add( 0x9203 , " brightness " );
this .Add( 0x9204 , " exposure bias " );
this .Add( 0x9205 , " maxaperture " );
this .Add( 0x9206 , " subjectdist " );
this .Add( 0x9207 , " metering mode " );
this .Add( 0x9208 , " lightsource " );
this .Add( 0x9209 , " flash " );
this .Add( 0x920a , " focallength " );
this .Add( 0x927c , " maker note " );
this .Add( 0x9286 , " user comment " );
this .Add( 0x9290 , " dtsubsec " );
this .Add( 0x9291 , " dtorigss " );
this .Add( 0x9292 , " dtdigss " );
this .Add( 0xa000 , " fpxver " );
this .Add( 0xa001 , " colorspace " );
this .Add( 0xa002 , " pixxdim " );
this .Add( 0xa003 , " pixydim " );
this .Add( 0xa004 , " relatedwav " );
this .Add( 0xa005 , " interop " );
this .Add( 0xa20b , " flashenergy " );
this .Add( 0xa20c , " spatialfr " );
this .Add( 0xa20e , " focalxres " );
this .Add( 0xa20f , " focalyres " );
this .Add( 0xa210 , " focalresunit " );
this .Add( 0xa214 , " subject loc " );
this .Add( 0xa215 , " exposure index " );
this .Add( 0xa217 , " sensing method " );
this .Add( 0xa300 , " filesource " );
this .Add( 0xa301 , " scenetype " );
this .Add( 0xa302 , " cfapattern " );
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 " );
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 " );
this .Add( 0x16 , " gps destlong " );
this .Add( 0x17 , " gps destbearref " );
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);
}
}
}
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 " );
this .Add( 0x8825 , " gps ifd " );
this .Add( 0xfe , " new subfile type " );
this .Add( 0xff , " subfile type " );
this .Add( 0x100 , " image width " );
this .Add( 0x101 , " image height " );
this .Add( 0x102 , " bits per sample " );
this .Add( 0x103 , " compression " );
this .Add( 0x106 , " photometric interp " );
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 " );
this .Add( 0x110 , " equip model " );
this .Add( 0x111 , " strip offsets " );
this .Add( 0x112 , " orientation " );
this .Add( 0x115 , " samples perpixel " );
this .Add( 0x116 , " rows per strip " );
this .Add( 0x117 , " strip bytes count " );
this .Add( 0x118 , " min sample value " );
this .Add( 0x119 , " max sample value " );
this .Add( 0x11a , " x resolution " );
this .Add( 0x11b , " y resolution " );
this .Add( 0x11c , " planar config " );
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 " );
this .Add( 0x129 , " page number " );
this .Add( 0x12d , " transfer funcition " );
this .Add( 0x131 , " software used " );
this .Add( 0x132 , " date time " );
this .Add( 0x13b , " artist " );
this .Add( 0x13c , " host computer " );
this .Add( 0x13d , " predictor " );
this .Add( 0x13e , " white point " );
this .Add( 0x13f , " primary chromaticities " );
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 " );
this .Add( 0x201 , " jpeg interformat " );
this .Add( 0x202 , " jpeg interlength " );
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 " );
this .Add( 0x209 , " jpeg actables " );
this .Add( 0x211 , " ycbcr coefficients " );
this .Add( 0x212 , " ycbcr subsampling " );
this .Add( 0x213 , " ycbcr positioning " );
this .Add( 0x214 , " ref black white " );
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 " );
this .Add( 0x8822 , " exposure prog " );
this .Add( 0x8824 , " spectral sense " );
this .Add( 0x8827 , " iso speed " );
this .Add( 0x8828 , " oecf " );
this .Add( 0x9000 , " ver " );
this .Add( 0x9003 , " dtorig " );
this .Add( 0x9004 , " dtdigitized " );
this .Add( 0x9101 , " compconfig " );
this .Add( 0x9102 , " compbpp " );
this .Add( 0x9201 , " shutter speed " );
this .Add( 0x9202 , " aperture " );
this .Add( 0x9203 , " brightness " );
this .Add( 0x9204 , " exposure bias " );
this .Add( 0x9205 , " maxaperture " );
this .Add( 0x9206 , " subjectdist " );
this .Add( 0x9207 , " metering mode " );
this .Add( 0x9208 , " lightsource " );
this .Add( 0x9209 , " flash " );
this .Add( 0x920a , " focallength " );
this .Add( 0x927c , " maker note " );
this .Add( 0x9286 , " user comment " );
this .Add( 0x9290 , " dtsubsec " );
this .Add( 0x9291 , " dtorigss " );
this .Add( 0x9292 , " dtdigss " );
this .Add( 0xa000 , " fpxver " );
this .Add( 0xa001 , " colorspace " );
this .Add( 0xa002 , " pixxdim " );
this .Add( 0xa003 , " pixydim " );
this .Add( 0xa004 , " relatedwav " );
this .Add( 0xa005 , " interop " );
this .Add( 0xa20b , " flashenergy " );
this .Add( 0xa20c , " spatialfr " );
this .Add( 0xa20e , " focalxres " );
this .Add( 0xa20f , " focalyres " );
this .Add( 0xa210 , " focalresunit " );
this .Add( 0xa214 , " subject loc " );
this .Add( 0xa215 , " exposure index " );
this .Add( 0xa217 , " sensing method " );
this .Add( 0xa300 , " filesource " );
this .Add( 0xa301 , " scenetype " );
this .Add( 0xa302 , " cfapattern " );
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 " );
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 " );
this .Add( 0x16 , " gps destlong " );
this .Add( 0x17 , " gps destbearref " );
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);
}
}
}
Program.cs
Program.cs
static
void
Main(
string
[] args)
{
string strFile = " DSC_0170.JPG " ;
System.Drawing.Bitmap bmp = new Bitmap(strFile);
// create a new instance of Extractor
// class. Here "\n" is the newline
// that is used to seprate output of two tags.
// You can replace it with "," if you want
EXIF.EXIFextractor er = new EXIF.EXIFextractor( ref bmp, " \n " );
// now dump all the tags on console
Console.Write(er);
// to set a tag you have to specify the tag id
// code 0x13B is for artist name
// since this number has ascii string with
// it pass the string you want to set
// er.setTag(0x13B, " http://www.goheer.com ");
// dispose the image here or do whatever you want.
bmp.Dispose();
Console.ReadLine();
}
{
string strFile = " DSC_0170.JPG " ;
System.Drawing.Bitmap bmp = new Bitmap(strFile);
// create a new instance of Extractor
// class. Here "\n" is the newline
// that is used to seprate output of two tags.
// You can replace it with "," if you want
EXIF.EXIFextractor er = new EXIF.EXIFextractor( ref bmp, " \n " );
// now dump all the tags on console
Console.Write(er);
// to set a tag you have to specify the tag id
// code 0x13B is for artist name
// since this number has ascii string with
// it pass the string you want to set
// er.setTag(0x13B, " http://www.goheer.com ");
// dispose the image here or do whatever you want.
bmp.Dispose();
Console.ReadLine();
}
整理自: http://www.codeproject.com/KB/graphics/exifextractor.aspx