Click here to Skip to main content
15,885,760 members
Articles / Programming Languages / C#

Access image metadata using Visual Studio's new object data binding feature

Rate me:
Please Sign up or sign in to vote.
4.85/5 (13 votes)
1 Feb 200712 min read 83.1K   975   46  
Using a new class library to bind to photo metadata with a few line of code.
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Xml;
namespace Reynsoft.PhotoInfo
{
    /// <summary>
    /// The XmpDMMetadata class
    /// </summary>
    public class XmpDMMetadata : PhotoMetadata
    {
        /// <summary>
        /// Private constructor to enforce the factory pattern.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="doc"></param>
        private XmpDMMetadata(XmlNode node, XmlDocument doc): base(node, doc)
	      {
 	      }
        /// <summary>
        /// The public factory method.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        public static XmpDMMetadata CreateNewXmpDMMetadata(XmlNode node, XmlDocument doc)
	      {
            if (node == null)
            {
                // TODO:  Insert the namespace name and URI for this group.
                //        Leave unchanged if this group is never edited.
                XmlNode emptyNode = CreateEmptyNode("", "", doc);
                return new XmpDMMetadata(emptyNode, doc);
            }
            else
            {
                return new XmpDMMetadata(node, doc);
            }
	      }
		#region Generated property definitions

		private string m_VideoCompressor = null;
		/// <summary>
		/// Video compression used. For example, jpeg.
		/// </summary>
		public string VideoCompressor
		{
			get
			{
				return m_VideoCompressor;
			}
		}

		private string m_VideoFieldOrder = null;
		/// <summary>
		/// The field order for video. One of: Upper Lower Progressive
		/// </summary>
		public string VideoFieldOrder
		{
			get
			{
				return m_VideoFieldOrder;
			}
		}

		private string m_PullDown = null;
		/// <summary>
		/// The sampling phase of film to be converted to video
		/// (pull-down). One of: WSSWW SSWWW SWWWS WWWSS WWSSW WSSWW_24p
		/// SSWWW_24p SWWWS_24p WWWSS_24p WWSSW_24p
		/// </summary>
		public string PullDown
		{
			get
			{
				return m_PullDown;
			}
		}

		private string m_AudioSampleRate = null;
		/// <summary>
		/// The audio sample rate. Can be any value, but commonly 32000,
		/// 41100, or 48000.
		/// </summary>
		public string AudioSampleRate
		{
			get
			{
				return m_AudioSampleRate;
			}
		}

		private string m_AudioSampleType = null;
		/// <summary>
		/// The audio sample type. One of: 8Int 16Int 32Int 32Float
		/// </summary>
		public string AudioSampleType
		{
			get
			{
				return m_AudioSampleType;
			}
		}

		private string m_AudioChannelType = null;
		/// <summary>
		/// The audio channel type. One of: Mono Stereo 5.1 7.1
		/// </summary>
		public string AudioChannelType
		{
			get
			{
				return m_AudioChannelType;
			}
		}

		private string m_AudioCompressor = null;
		/// <summary>
		/// The audio compression used. For example, MP3.
		/// </summary>
		public string AudioCompressor
		{
			get
			{
				return m_AudioCompressor;
			}
		}

		private string m_SpeakerPlacement = null;
		/// <summary>
		/// A description of the speaker angles from center front in
		/// degrees. For example: “Left = -30, Right = 30, Center = 0,
		/// LFE = 45, Left Surround = -110, Right Surround = 110”
		/// </summary>
		public string SpeakerPlacement
		{
			get
			{
				return m_SpeakerPlacement;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_SpeakerPlacement)
				{
					m_SpeakerPlacement = adjustedValue;
					ElementUpdated("SpeakerPlacement", "xmpDM:speakerPlacement", "Text", adjustedValue);
				}
			}
		}

		private string m_FileDataRate = null;
		/// <summary>
		/// The file data rate in megabytes per second. For example:
		/// “36/10” = 3.6 MB/sec
		/// </summary>
		public string FileDataRate
		{
			get
			{
				return m_FileDataRate;
			}
		}

		private string m_Property = null;
		/// <summary>
		/// Description
		/// </summary>
		public string Property
		{
			get
			{
				return m_Property;
			}
		}

		private string m_TapeName = null;
		/// <summary>
		/// The name of the tape from which the clip was captured, as
		/// set during the capture process.
		/// </summary>
		public string TapeName
		{
			get
			{
				return m_TapeName;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_TapeName)
				{
					m_TapeName = adjustedValue;
					ElementUpdated("TapeName", "xmpDM:tapeName", "Text", adjustedValue);
				}
			}
		}

		private string m_AltTapeName = null;
		/// <summary>
		/// An alternative tape name, set via the project window or
		/// timecode dialog in Premiere. If an alternative name has been
		/// set and has not been reverted, that name is displayed.
		/// </summary>
		public string AltTapeName
		{
			get
			{
				return m_AltTapeName;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_AltTapeName)
				{
					m_AltTapeName = adjustedValue;
					ElementUpdated("AltTapeName", "xmpDM:altTapeName", "Text", adjustedValue);
				}
			}
		}

		private string m_StartTimecode = null;
		/// <summary>
		/// The timecode of the first frame of video in the file, as
		/// obtained from the device control.
		/// </summary>
		public string StartTimecode
		{
			get
			{
				return m_StartTimecode;
			}
		}

		private string m_AltTimecode = null;
		/// <summary>
		/// A timecode set by the user. When specified, it is used
		/// instead of the startTimecode.
		/// </summary>
		public string AltTimecode
		{
			get
			{
				return m_AltTimecode;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_AltTimecode)
				{
					m_AltTimecode = adjustedValue;
					ElementUpdated("AltTimecode", "xmpDM:altTimecode", "Timecode", adjustedValue);
				}
			}
		}

		private string m_Duration = null;
		/// <summary>
		/// The duration of the media file.
		/// </summary>
		public string Duration
		{
			get
			{
				return m_Duration;
			}
		}

		private string m_Scene = null;
		/// <summary>
		/// The name of the scene.
		/// </summary>
		public string Scene
		{
			get
			{
				return m_Scene;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_Scene)
				{
					m_Scene = adjustedValue;
					ElementUpdated("Scene", "xmpDM:scene", "Text", adjustedValue);
				}
			}
		}

		private string m_ShotName = null;
		/// <summary>
		/// The name of the shot or take.
		/// </summary>
		public string ShotName
		{
			get
			{
				return m_ShotName;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_ShotName)
				{
					m_ShotName = adjustedValue;
					ElementUpdated("ShotName", "xmpDM:shotName", "Text", adjustedValue);
				}
			}
		}

		private string m_ShotDate = null;
		/// <summary>
		/// The date and time when the video was shot.
		/// </summary>
		public string ShotDate
		{
			get
			{
				return m_ShotDate;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_ShotDate)
				{
					m_ShotDate = adjustedValue;
					ElementUpdated("ShotDate", "xmpDM:shotDate", "Date", adjustedValue);
				}
			}
		}

		private string m_ShotLocation = null;
		/// <summary>
		/// The name of the location where the video was shot. For
		/// example: “Oktoberfest, Munich Germany” For more accurate
		/// positioning, use the EXIF GPS values.
		/// </summary>
		public string ShotLocation
		{
			get
			{
				return m_ShotLocation;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_ShotLocation)
				{
					m_ShotLocation = adjustedValue;
					ElementUpdated("ShotLocation", "xmpDM:shotLocation", "Text", adjustedValue);
				}
			}
		}

		private string m_LogComment = null;
		/// <summary>
		/// User’s log comments.
		/// </summary>
		public string LogComment
		{
			get
			{
				return m_LogComment;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_LogComment)
				{
					m_LogComment = adjustedValue;
					ElementUpdated("LogComment", "xmpDM:logComment", "Text", adjustedValue);
				}
			}
		}

		private string m_Markers = null;
		/// <summary>
		/// An ordered list of markers
		/// </summary>
		public string Markers
		{
			get
			{
				return m_Markers;
			}
		}

		private string m_ContributedMedia = null;
		/// <summary>
		/// An unordered list of all media used to create this media.
		/// </summary>
		public string ContributedMedia
		{
			get
			{
				return m_ContributedMedia;
			}
		}

		private string m_AbsPeakAudioFilePath = null;
		/// <summary>
		/// The absolute path to the file’s peak audio file. If empty,
		/// no peak file exists.
		/// </summary>
		public string AbsPeakAudioFilePath
		{
			get
			{
				return m_AbsPeakAudioFilePath;
			}
		}

		private string m_RelativePeakAudioFilePath = null;
		/// <summary>
		/// The relative path to the file’s peak audio file. If empty,
		/// no peak file exists.
		/// </summary>
		public string RelativePeakAudioFilePath
		{
			get
			{
				return m_RelativePeakAudioFilePath;
			}
		}

		private string m_VideoModDate = null;
		/// <summary>
		/// The date and time when the video was last modified.
		/// </summary>
		public string VideoModDate
		{
			get
			{
				return m_VideoModDate;
			}
		}

		private string m_Property = null;
		/// <summary>
		/// Description
		/// </summary>
		public string Property
		{
			get
			{
				return m_Property;
			}
		}

		private string m_AudioModDate = null;
		/// <summary>
		/// The date and time when the audio was last modified.
		/// </summary>
		public string AudioModDate
		{
			get
			{
				return m_AudioModDate;
			}
		}

		private string m_MetadataModDate = null;
		/// <summary>
		/// The date and time when the metadata was last modified.
		/// </summary>
		public string MetadataModDate
		{
			get
			{
				return m_MetadataModDate;
			}
		}

		private string m_Artist = null;
		/// <summary>
		/// The name of the artist or artists.
		/// </summary>
		public string Artist
		{
			get
			{
				return m_Artist;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_Artist)
				{
					m_Artist = adjustedValue;
					ElementUpdated("Artist", "xmpDM:artist", "Text", adjustedValue);
				}
			}
		}

		private string m_Album = null;
		/// <summary>
		/// The name of the album.
		/// </summary>
		public string Album
		{
			get
			{
				return m_Album;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_Album)
				{
					m_Album = adjustedValue;
					ElementUpdated("Album", "xmpDM:album", "Text", adjustedValue);
				}
			}
		}

		private string m_TrackNumber = null;
		/// <summary>
		/// A numeric value indicating the order of the audio file
		/// within its original recording.
		/// </summary>
		public string TrackNumber
		{
			get
			{
				return m_TrackNumber;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_TrackNumber)
				{
					m_TrackNumber = adjustedValue;
					ElementUpdated("TrackNumber", "xmpDM:trackNumber", "Integer", adjustedValue);
				}
			}
		}

		private string m_Genre = null;
		/// <summary>
		/// The name of the genre.
		/// </summary>
		public string Genre
		{
			get
			{
				return m_Genre;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_Genre)
				{
					m_Genre = adjustedValue;
					ElementUpdated("Genre", "xmpDM:genre", "Text", adjustedValue);
				}
			}
		}

		private string m_Copyright = null;
		/// <summary>
		/// The copyright information.
		/// </summary>
		public string Copyright
		{
			get
			{
				return m_Copyright;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_Copyright)
				{
					m_Copyright = adjustedValue;
					ElementUpdated("Copyright", "xmpDM:copyright", "Text", adjustedValue);
				}
			}
		}

		private string m_ReleaseDate = null;
		/// <summary>
		/// The date the title was released.
		/// </summary>
		public string ReleaseDate
		{
			get
			{
				return m_ReleaseDate;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_ReleaseDate)
				{
					m_ReleaseDate = adjustedValue;
					ElementUpdated("ReleaseDate", "xmpDM:releaseDate", "Date", adjustedValue);
				}
			}
		}

		private string m_Composer = null;
		/// <summary>
		/// The composer’s name.
		/// </summary>
		public string Composer
		{
			get
			{
				return m_Composer;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_Composer)
				{
					m_Composer = adjustedValue;
					ElementUpdated("Composer", "xmpDM:composer", "Text", adjustedValue);
				}
			}
		}

		private string m_Engineer = null;
		/// <summary>
		/// The engineer’s name.
		/// </summary>
		public string Engineer
		{
			get
			{
				return m_Engineer;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_Engineer)
				{
					m_Engineer = adjustedValue;
					ElementUpdated("Engineer", "xmpDM:engineer", "Text", adjustedValue);
				}
			}
		}

		private string m_Tempo = null;
		/// <summary>
		/// The audio’s tempo.
		/// </summary>
		public string Tempo
		{
			get
			{
				return m_Tempo;
			}
		}

		private string m_Instrument = null;
		/// <summary>
		/// The musical instrument.
		/// </summary>
		public string Instrument
		{
			get
			{
				return m_Instrument;
			}
			set
			{
				string adjustedValue = AdjustedValue(value);
				if (adjustedValue != m_Instrument)
				{
					m_Instrument = adjustedValue;
					ElementUpdated("Instrument", "xmpDM:instrument", "Text", adjustedValue);
				}
			}
		}

		private string m_IntroTime = null;
		/// <summary>
		/// The duration of lead time for queuing music.
		/// </summary>
		public string IntroTime
		{
			get
			{
				return m_IntroTime;
			}
		}

		private string m_OutCue = null;
		/// <summary>
		/// The time at which to fade out.
		/// </summary>
		public string OutCue
		{
			get
			{
				return m_OutCue;
			}
		}

		private string m_RelativeTimestamp = null;
		/// <summary>
		/// The start time of the media inside the audio project.
		/// </summary>
		public string RelativeTimestamp
		{
			get
			{
				return m_RelativeTimestamp;
			}
		}

		private string m_Loop = null;
		/// <summary>
		/// When true, the clip can be looped seemlessly.
		/// </summary>
		public string Loop
		{
			get
			{
				return m_Loop;
			}
		}

		private string m_NumberOfBeats = null;
		/// <summary>
		/// The number of beats.
		/// </summary>
		public string NumberOfBeats
		{
			get
			{
				return m_NumberOfBeats;
			}
		}

		private string m_Key = null;
		/// <summary>
		/// The audio’s musical key. One of: C C# D D# E F F# G G# A A#
		/// B
		/// </summary>
		public string Key
		{
			get
			{
				return m_Key;
			}
		}

		private string m_StretchMode = null;
		/// <summary>
		/// The audio stretch mode. One of: Fixed length Time-Scale
		/// Resample Beat Splice Hybrid
		/// </summary>
		public string StretchMode
		{
			get
			{
				return m_StretchMode;
			}
		}

		private string m_TimeScaleParams = null;
		/// <summary>
		/// Additional parameters for Time-Scale stretch mode.
		/// </summary>
		public string TimeScaleParams
		{
			get
			{
				return m_TimeScaleParams;
			}
		}

		private string m_ResampleParams = null;
		/// <summary>
		/// Additional parameters for Resample stretch mode.
		/// </summary>
		public string ResampleParams
		{
			get
			{
				return m_ResampleParams;
			}
		}

		private string m_BeatSpliceParams = null;
		/// <summary>
		/// Additional parameters for Beat Splice stretch mode.
		/// </summary>
		public string BeatSpliceParams
		{
			get
			{
				return m_BeatSpliceParams;
			}
		}

		private string m_TimeSignature = null;
		/// <summary>
		/// The time signature of the music. One of: 2/4 3/4 4/4 5/4 7/4
		/// 6/8 9/8 12/8 other
		/// </summary>
		public string TimeSignature
		{
			get
			{
				return m_TimeSignature;
			}
		}

		private string m_ScaleType = null;
		/// <summary>
		/// The musical scale used in the music. One of: Major Minor,
		/// Both Neither Neither is most often used for instruments with
		/// no associated scale, such as drums.
		/// </summary>
		public string ScaleType
		{
			get
			{
				return m_ScaleType;
			}
		}
		#endregion
		#region Generated function to initialize properties
		/// <summary>
		/// Generated function to initialize properties
		/// </summary>
		public override void LoadInitialData()
		{
			this.m_VideoCompressor = GetInitialValue("xmpDM:videoCompressor", "Text");
			NotifyPropertyChanged("VideoCompressor");
			this.m_VideoFieldOrder = GetInitialValue("xmpDM:videoFieldOrder", "closed Choice of Text");
			NotifyPropertyChanged("VideoFieldOrder");
			this.m_PullDown = GetInitialValue("xmpDM:pullDown", "closed Choice of Text");
			NotifyPropertyChanged("PullDown");
			this.m_AudioSampleRate = GetInitialValue("xmpDM:audioSampleRate", "Integer");
			NotifyPropertyChanged("AudioSampleRate");
			this.m_AudioSampleType = GetInitialValue("xmpDM:audioSampleType", "closed Choice of Text");
			NotifyPropertyChanged("AudioSampleType");
			this.m_AudioChannelType = GetInitialValue("xmpDM:audioChannelType", "closed Choice of Text");
			NotifyPropertyChanged("AudioChannelType");
			this.m_AudioCompressor = GetInitialValue("xmpDM:audioCompressor", "Text");
			NotifyPropertyChanged("AudioCompressor");
			this.m_SpeakerPlacement = GetInitialValue("xmpDM:speakerPlacement", "Text");
			NotifyPropertyChanged("SpeakerPlacement");
			this.m_FileDataRate = GetInitialValue("xmpDM:fileDataRate", "Rational");
			NotifyPropertyChanged("FileDataRate");
			this.m_Property = GetInitialValue("Property", "Value Type");
			NotifyPropertyChanged("Property");
			this.m_TapeName = GetInitialValue("xmpDM:tapeName", "Text");
			NotifyPropertyChanged("TapeName");
			this.m_AltTapeName = GetInitialValue("xmpDM:altTapeName", "Text");
			NotifyPropertyChanged("AltTapeName");
			this.m_StartTimecode = GetInitialValue("xmpDM:startTimecode", "Timecode");
			NotifyPropertyChanged("StartTimecode");
			this.m_AltTimecode = GetInitialValue("xmpDM:altTimecode", "Timecode");
			NotifyPropertyChanged("AltTimecode");
			this.m_Duration = GetInitialValue("xmpDM:duration", "Time");
			NotifyPropertyChanged("Duration");
			this.m_Scene = GetInitialValue("xmpDM:scene", "Text");
			NotifyPropertyChanged("Scene");
			this.m_ShotName = GetInitialValue("xmpDM:shotName", "Text");
			NotifyPropertyChanged("ShotName");
			this.m_ShotDate = GetInitialValue("xmpDM:shotDate", "Date");
			NotifyPropertyChanged("ShotDate");
			this.m_ShotLocation = GetInitialValue("xmpDM:shotLocation", "Text");
			NotifyPropertyChanged("ShotLocation");
			this.m_LogComment = GetInitialValue("xmpDM:logComment", "Text");
			NotifyPropertyChanged("LogComment");
			this.m_Markers = GetInitialValue("xmpDM:markers", "seq Marker");
			NotifyPropertyChanged("Markers");
			this.m_ContributedMedia = GetInitialValue("xmpDM:contributedMedia", "bag Media");
			NotifyPropertyChanged("ContributedMedia");
			this.m_AbsPeakAudioFilePath = GetInitialValue("xmpDM:absPeakAudioFilePath", "URI");
			NotifyPropertyChanged("AbsPeakAudioFilePath");
			this.m_RelativePeakAudioFilePath = GetInitialValue("xmpDM:relativePeakAudioFilePath", "URI");
			NotifyPropertyChanged("RelativePeakAudioFilePath");
			this.m_VideoModDate = GetInitialValue("xmpDM:videoModDate", "Date");
			NotifyPropertyChanged("VideoModDate");
			this.m_Property = GetInitialValue("Property", "Value Type");
			NotifyPropertyChanged("Property");
			this.m_AudioModDate = GetInitialValue("xmpDM:audioModDate", "Date");
			NotifyPropertyChanged("AudioModDate");
			this.m_MetadataModDate = GetInitialValue("xmpDM:metadataModDate", "Date");
			NotifyPropertyChanged("MetadataModDate");
			this.m_Artist = GetInitialValue("xmpDM:artist", "Text");
			NotifyPropertyChanged("Artist");
			this.m_Album = GetInitialValue("xmpDM:album", "Text");
			NotifyPropertyChanged("Album");
			this.m_TrackNumber = GetInitialValue("xmpDM:trackNumber", "Integer");
			NotifyPropertyChanged("TrackNumber");
			this.m_Genre = GetInitialValue("xmpDM:genre", "Text");
			NotifyPropertyChanged("Genre");
			this.m_Copyright = GetInitialValue("xmpDM:copyright", "Text");
			NotifyPropertyChanged("Copyright");
			this.m_ReleaseDate = GetInitialValue("xmpDM:releaseDate", "Date");
			NotifyPropertyChanged("ReleaseDate");
			this.m_Composer = GetInitialValue("xmpDM:composer", "Text");
			NotifyPropertyChanged("Composer");
			this.m_Engineer = GetInitialValue("xmpDM:engineer", "Text");
			NotifyPropertyChanged("Engineer");
			this.m_Tempo = GetInitialValue("xmpDM:tempo", "Real");
			NotifyPropertyChanged("Tempo");
			this.m_Instrument = GetInitialValue("xmpDM:instrument", "Text");
			NotifyPropertyChanged("Instrument");
			this.m_IntroTime = GetInitialValue("xmpDM:introTime", "Time");
			NotifyPropertyChanged("IntroTime");
			this.m_OutCue = GetInitialValue("xmpDM:outCue", "Time");
			NotifyPropertyChanged("OutCue");
			this.m_RelativeTimestamp = GetInitialValue("xmpDM:relativeTimestamp", "Time");
			NotifyPropertyChanged("RelativeTimestamp");
			this.m_Loop = GetInitialValue("xmpDM:loop", "Boolean");
			NotifyPropertyChanged("Loop");
			this.m_NumberOfBeats = GetInitialValue("xmpDM:numberOfBeats", "Real");
			NotifyPropertyChanged("NumberOfBeats");
			this.m_Key = GetInitialValue("xmpDM:key", "closed Choice of Text");
			NotifyPropertyChanged("Key");
			this.m_StretchMode = GetInitialValue("xmpDM:stretchMode", "closed Choice of Text");
			NotifyPropertyChanged("StretchMode");
			this.m_TimeScaleParams = GetInitialValue("xmpDM:timeScaleParams", "timeScaleStretch");
			NotifyPropertyChanged("TimeScaleParams");
			this.m_ResampleParams = GetInitialValue("xmpDM:resampleParams", "resampleStretch");
			NotifyPropertyChanged("ResampleParams");
			this.m_BeatSpliceParams = GetInitialValue("xmpDM:beatSpliceParams", "beatSpliceStretch");
			NotifyPropertyChanged("BeatSpliceParams");
			this.m_TimeSignature = GetInitialValue("xmpDM:timeSignature", "closed Choice of Text");
			NotifyPropertyChanged("TimeSignature");
			this.m_ScaleType = GetInitialValue("xmpDM:scaleType", "closed Choice of Text");
			NotifyPropertyChanged("ScaleType");
		}
		#endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This is a picture of John still in the cubicled environment of the Northern Virginia tech world. There are great software jobs there, but the traffic is horrible! He has since retired, or really, started a new, freer lifestyle. He now travels and takes photographs. At home, he is involved in a number of community activities including work at the Historical Society of Frederick County (MD) where he has helped preserve historic documents and photographs by making photographic copies. Some of them are posted on the HSFC photo catalog website. He is fascinated by the new ability, using applications like Google Earth, to link photos to geographic locations. This adds a new dimension to photography, which he is working to develop. These pursuits, which require the ability to access and manage photo metadata, are a major motivation for getting involved as deeply as he did in this exciting topic.

Comments and Discussions