using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Drawing.Imaging; namespace Mk0.Software.ImageSorter { public partial class EXIF : Form { private List exifData; public EXIF(PropertyItem[] propertyItems) { InitializeComponent(); exifData = new List(); foreach (PropertyItem propItem in propertyItems) { Exifdata ed = new Exifdata(propItem.Id, propItem.Type, propItem.Len, propItem.Value); exifData.Add(ed); } } private void EXIF_Shown(object sender, EventArgs e) { treeViewExif.BeginUpdate(); foreach (Exifdata ed in exifData) { if (ed.ID != "ThumbnailData") { TreeNode node = new TreeNode(ed.ID); node.Nodes.Add(new TreeNode(ed.Value)); node.Nodes.Add(new TreeNode(ed.Type)); node.Nodes.Add(new TreeNode(ed.Length)); treeViewExif.Nodes.Add(node); node.Expand(); } } treeViewExif.TreeViewNodeSorter = new Sorter(); treeViewExif.Sort(); treeViewExif.EndUpdate(); } } public class Exifdata { private const string DOUBLETYPE_FORMAT = "0.0####"; private const int BYTEJUMP_SHORT = 2; private const int BYTEJUMP_LONG = 4; private const int BYTEJUMP_RATIONAL = 8; private const int BYTEJUMP_SLONG = 4; private const int BYTEJUMP_SRATIONAL = 8; public string ID, Type, Length, Value; public short TypeOriginal; public Exifdata(int id, short type, int len, byte[] value) { ID = new Exifid("0x" + id.ToString("x4")).Readable; TypeOriginal = type; Type = ExifType(type); Length = len.ToString() + " bytes"; Value = ExifValue(value, type, len); } public string ExifValue(byte[] value, short type, int len) { ASCIIEncoding encoding = new ASCIIEncoding(); string ev = ""; if (type == 1) { ev = BitConverter.ToString(value, 0, len); } else if (type == 2) { ev = encoding.GetString(value, 0, len - 1); } else if (type == 3) { for (int i = 0; i < len; i += BYTEJUMP_SHORT) { ushort val = BitConverter.ToUInt16(value, i); ev += val.ToString(); if (i + BYTEJUMP_SHORT < len) ev += " "; } } else if (type == 4) { for (int i = 0; i < len; i += BYTEJUMP_LONG) { uint val = BitConverter.ToUInt32(value, i); ev += val.ToString(); if (i + BYTEJUMP_LONG < len) ev += " "; } } else if (type == 5) { for (int i = 0; i < len; i += BYTEJUMP_RATIONAL) { uint numer = BitConverter.ToUInt32(value, i); uint denom = BitConverter.ToUInt32(value, i + BYTEJUMP_LONG); double dbl; if (denom == 0) dbl = 0.0; else dbl = (double)numer / (double)denom; ev += dbl.ToString(DOUBLETYPE_FORMAT); if (i + BYTEJUMP_RATIONAL < len) ev += " "; } } else if (type == 6) { ev = BitConverter.ToString(value, 0, len); } else if (type == 7) { try { for (int i = 0; i < len; i += BYTEJUMP_SLONG) { int val = BitConverter.ToInt32(value, i); ev += val.ToString(); if (i + BYTEJUMP_SLONG < len) ev += " "; } } catch (Exception ex) { ev = ex.ToString(); } } else if (type == 10) { for (int i = 0; i < len; i += BYTEJUMP_SRATIONAL) { int numer = BitConverter.ToInt32(value, i); int denom = BitConverter.ToInt32(value, i + BYTEJUMP_SLONG); double dbl; if (denom == 0) dbl = 0.0; else dbl = (double)numer / (double)denom; ev += dbl.ToString(DOUBLETYPE_FORMAT); if (i + BYTEJUMP_SRATIONAL < len) ev += " "; } } else { ev = "unlesbarer Typ"; } return ev; } public string ExifType(short type) { switch (type) { case 1: return "unsigned array of bytes"; case 2: return "ASCII string"; case 3: return "array of unsigned short (16-bit) integers"; case 4: return "array of unsigned long (32-bit) integers"; case 5: return "array of pairs of unsigned long integers"; case 6: return "signed array of bytes"; case 7: return "array of signed long (32-bit) integers"; case 10: return "array of pairs of signed long integers"; default: return "unknown"; } } } public class Exifid { public string Readable; public Dictionary ids = new Dictionary(); public Exifid(string id) { ids.Add("0x0000", "GPS Version"); ids.Add("0x0001", "GPS Latitude Nord- oder Südhalbkugel"); ids.Add("0x0002", "GPS Latitude"); ids.Add("0x0003", "GPS Longitude Ost oder West"); ids.Add("0x0004", "GPS Longitude"); ids.Add("0x0005", "GPS AltitudeRef"); ids.Add("0x0006", "GPS Altitude"); ids.Add("0x0007", "GPS Time"); ids.Add("0x0008", "GPS Satellites"); ids.Add("0x0009", "GPS Status"); ids.Add("0x000a", "GPS MeasureMode"); ids.Add("0x000b", "GPS Dop"); ids.Add("0x000c", "GPS SpeedRef"); ids.Add("0x000d", "GPS Speed"); ids.Add("0x000e", "GPS TrackRef"); ids.Add("0x000f", "GPS Track"); ids.Add("0x0010", "GPS ImgDirRef"); ids.Add("0x0011", "GPS ImgDir"); ids.Add("0x0012", "GPS MapDatum"); ids.Add("0x0013", "GPS DestLatRef"); ids.Add("0x0014", "GPS DestLat"); ids.Add("0x0015", "GPS DestLongRef"); ids.Add("0x0016", "GPS DestLong"); ids.Add("0x0017", "GPS DestBearRef"); ids.Add("0x0018", "GPS DestBear"); ids.Add("0x0019", "GPS DestDistRef"); ids.Add("0x001a", "GPS DestDist"); ids.Add("0x00fe", "NewSubfileType"); ids.Add("0x00ff", "SubfileType"); ids.Add("0x0100", "ImageWidth"); ids.Add("0x0101", "ImageHeight"); ids.Add("0x0102", "BitsPerSample"); ids.Add("0x0103", "Compression"); ids.Add("0x0106", "PhotometricInterp"); ids.Add("0x0107", "ThreshHolding"); ids.Add("0x0108", "CellWidth"); ids.Add("0x0109", "CellHeight"); ids.Add("0x010a", "FillOrder"); ids.Add("0x010d", "DocumentName"); ids.Add("0x010e", "ImageDescription"); ids.Add("0x010f", "EquipMake"); ids.Add("0x0110", "EquipModel"); ids.Add("0x0111", "StripOffsets"); ids.Add("0x0112", "Orientation"); ids.Add("0x0115", "SamplesPerPixel"); ids.Add("0x0116", "RowsPerStrip"); ids.Add("0x0117", "StripBytesCount"); ids.Add("0x0118", "MinSampleValue"); ids.Add("0x0119", "MaxSampleValue"); ids.Add("0x011a", "XResolution"); ids.Add("0x011b", "YResolution"); ids.Add("0x011c", "PlanarConfig"); ids.Add("0x011d", "PageName"); ids.Add("0x011e", "XPosition"); ids.Add("0x011f", "YPosition"); ids.Add("0x0120", "FreeOffset"); ids.Add("0x0121", "FreeByteCounts"); ids.Add("0x0122", "GrayResponseUnit"); ids.Add("0x0123", "GrayResponseCurve"); ids.Add("0x0124", "T4Option"); ids.Add("0x0125", "T6Option"); ids.Add("0x0128", "ResolutionUnit"); ids.Add("0x0129", "PageNumber"); ids.Add("0x012d", "TransferFunction"); ids.Add("0x0131", "SoftwareUsed"); ids.Add("0x0132", "DateTime"); ids.Add("0x013b", "Artist"); ids.Add("0x013c", "HostComputer"); ids.Add("0x013d", "Predictor"); ids.Add("0x013e", "WhitePoint"); ids.Add("0x013f", "PrimaryChromaticities"); ids.Add("0x0140", "ColorMap"); ids.Add("0x0141", "HalftoneHints"); ids.Add("0x0142", "TileWidth"); ids.Add("0x0143", "TileLength"); ids.Add("0x0144", "TileOffset"); ids.Add("0x0145", "TileByteCounts"); ids.Add("0x014c", "InkSet"); ids.Add("0x014d", "InkNames"); ids.Add("0x014e", "NumberOfInks"); ids.Add("0x0150", "DotRange"); ids.Add("0x0151", "TargetPrinter"); ids.Add("0x0152", "ExtraSamples"); ids.Add("0x0153", "SampleFormat"); ids.Add("0x0154", "SMinSampleValue"); ids.Add("0x0155", "SMaxSampleValue"); ids.Add("0x0156", "TransferRange"); ids.Add("0x0200", "JPEGProc"); ids.Add("0x0201", "JPEGInterFormat"); ids.Add("0x0202", "JPEGInterLength"); ids.Add("0x0203", "JPEGRestartInterval"); ids.Add("0x0205", "JPEGLosslessPredictors"); ids.Add("0x0206", "JPEGPointTransforms"); ids.Add("0x0207", "JPEGQTables"); ids.Add("0x0208", "JPEGDCTables"); ids.Add("0x0209", "JPEGACTables"); ids.Add("0x0211", "YCbCrCoefficients"); ids.Add("0x0212", "YCbCrSubsampling"); ids.Add("0x0213", "YCbCrPositioning"); ids.Add("0x0214", "REFBlackWhite"); ids.Add("0x0301", "Gamma"); ids.Add("0x0302", "ICCProfileDescriptor"); ids.Add("0x0303", "SRGBRenderingIntent"); ids.Add("0x0320", "ImageTitle"); ids.Add("0x5001", "ResolutionXUnit"); ids.Add("0x5002", "ResolutionYUnit"); ids.Add("0x5003", "ResolutionXLengthUnit"); ids.Add("0x5004", "ResolutionYLengthUnit"); ids.Add("0x5005", "PrintFlags"); ids.Add("0x5006", "PrintFlagsVersion"); ids.Add("0x5007", "PrintFlagsCrop"); ids.Add("0x5008", "PrintFlagsBleedWidth"); ids.Add("0x5009", "PrintFlagsBleedWidthScale"); ids.Add("0x500a", "HalftoneLPI"); ids.Add("0x500b", "HalftoneLPIUnit"); ids.Add("0x500c", "HalftoneDegree"); ids.Add("0x500d", "HalftoneShape"); ids.Add("0x500e", "HalftoneMisc"); ids.Add("0x500f", "HalftoneScreen"); ids.Add("0x5010", "JPEGQuality"); ids.Add("0x5011", "GridSize"); ids.Add("0x5012", "ThumbnailFormat"); ids.Add("0x5013", "ThumbnailWidth"); ids.Add("0x5014", "ThumbnailHeight"); ids.Add("0x5015", "ThumbnailColorDepth"); ids.Add("0x5016", "ThumbnailPlanes"); ids.Add("0x5017", "ThumbnailRawBytes"); ids.Add("0x5018", "ThumbnailSize"); ids.Add("0x5019", "ThumbnailCompressedSize"); ids.Add("0x501a", "ColorTransferFunction"); ids.Add("0x501b", "ThumbnailData"); ids.Add("0x5020", "ThumbnailImageWidth"); ids.Add("0x5021", "ThumbnailImageHeight"); ids.Add("0x5022", "ThumbnailBitsPerSample"); ids.Add("0x5023", "ThumbnailCompression"); ids.Add("0x5024", "ThumbnailPhotometricInterp"); ids.Add("0x5025", "ThumbnailImageDescription"); ids.Add("0x5026", "ThumbnailEquipMake"); ids.Add("0x5027", "ThumbnailEquipModel"); ids.Add("0x5028", "ThumbnailStripOffsets"); ids.Add("0x5029", "ThumbnailOrientation"); ids.Add("0x502a", "ThumbnailSamplesPerPixel"); ids.Add("0x502b", "ThumbnailRowsPerStrip"); ids.Add("0x502c", "ThumbnailStripBytesCount"); ids.Add("0x502d", "ThumbnailResolutionX"); ids.Add("0x502e", "ThumbnailResolutionY"); ids.Add("0x502f", "ThumbnailPlanarConfig"); ids.Add("0x5030", "ThumbnailResolutionUnit"); ids.Add("0x5031", "ThumbnailTransferFunction"); ids.Add("0x5032", "ThumbnailSoftwareUsed"); ids.Add("0x5033", "ThumbnailDateTime"); ids.Add("0x5034", "ThumbnailArtist"); ids.Add("0x5035", "ThumbnailWhitePoint"); ids.Add("0x5036", "ThumbnailPrimaryChromaticities"); ids.Add("0x5037", "ThumbnailYCbCrCoefficients"); ids.Add("0x5038", "ThumbnailYCbCrSubsampling"); ids.Add("0x5039", "ThumbnailYCbCrPositioning"); ids.Add("0x503a", "ThumbnailRefBlackWhite"); ids.Add("0x503b", "ThumbnailCopyRight"); ids.Add("0x5041", "InteroperabilityIndex"); ids.Add("0x5042", "ExifInteroperabilityVersion"); ids.Add("0x5090", "LuminanceTable"); ids.Add("0x5091", "ChrominanceTable"); ids.Add("0x5100", "FrameDelay"); ids.Add("0x5101", "LoopCount"); ids.Add("0x5102", "GlobalPalette"); ids.Add("0x5103", "IndexBackground"); ids.Add("0x5104", "IndexTransparent"); ids.Add("0x5110", "PixelUnit"); ids.Add("0x5111", "PixelPerUnitX"); ids.Add("0x5112", "PixelPerUnitY"); ids.Add("0x5113", "PaletteHistogram"); ids.Add("0x8298", "Copyright"); ids.Add("0x829a", "ExifExposureTime"); ids.Add("0x829d", "ExifFNumber"); ids.Add("0x8769", "ExifIFD"); ids.Add("0x8773", "ICCProfile"); ids.Add("0x8822", "ExifExposureProg"); ids.Add("0x8824", "ExifSpectralSense"); ids.Add("0x8825", "GPS IFD"); ids.Add("0x8827", "ExifISOSpeed"); ids.Add("0x8828", "ExifOECF"); ids.Add("0x9000", "ExifVer"); ids.Add("0x9003", "ExifDTOrig"); ids.Add("0x9004", "ExifDTDigitized"); ids.Add("0x9101", "ExifCompConfig"); ids.Add("0x9102", "ExifCompBPP"); ids.Add("0x9201", "ExifShutterSpeed"); ids.Add("0x9202", "ExifAperture"); ids.Add("0x9203", "ExifBrightness"); ids.Add("0x9204", "ExifExposureBias"); ids.Add("0x9205", "ExifMaxAperture"); ids.Add("0x9206", "ExifSubjectDist"); ids.Add("0x9207", "ExifMeteringMode"); ids.Add("0x9208", "ExifLightSource"); ids.Add("0x9209", "ExifFlash"); ids.Add("0x920a", "ExifFocalLength"); ids.Add("0x927c", "ExifMakerNote"); ids.Add("0x9286", "ExifUserComment"); ids.Add("0x9290", "ExifDTSubsec"); ids.Add("0x9291", "ExifDTOrigSS"); ids.Add("0x9292", "ExifDTDigSS"); ids.Add("0xa000", "ExifFPXVer"); ids.Add("0xa001", "ExifColorSpace"); ids.Add("0xa002", "ExifPixXDim"); ids.Add("0xa003", "ExifPixYDim"); ids.Add("0xa004", "ExifRelatedWav"); ids.Add("0xa005", "ExifInterop"); ids.Add("0xa20b", "ExifFlashEnergy"); ids.Add("0xa20c", "ExifSpatialFR"); ids.Add("0xa20e", "ExifFocalXRes"); ids.Add("0xa20f", "ExifFocalYRes"); ids.Add("0xa210", "ExifFocalResUnit"); ids.Add("0xa214", "ExifSubjectLoc"); ids.Add("0xa215", "ExifExposureIndex"); ids.Add("0xa217", "ExifSensingMethod"); ids.Add("0xa300", "ExifFileSource"); ids.Add("0xa301", "ExifSceneType"); ids.Add("0xa302", "ExifCfaPattern"); ids.Add("0xa402", "ExposureMode"); ids.Add("0xa403", "WhiteBalance"); ids.Add("0xa404", "DigitalZoomRatio"); ids.Add("0xa405", "FocalLengthIn35mmFilm"); ids.Add("0xa406", "SceneCaptureType"); ids.Add("0xa407", "GainControl"); ids.Add("0xa408", "Contrast"); ids.Add("0xa409", "Saturation"); ids.Add("0xa40a", "Sharpness"); ids.Add("0xa40c", "SubjectDistanceRange"); if (ids.TryGetValue(id.ToLower(), out Readable)) { // } else { Readable = id; } } } public class Fraction { private Int32 _numer; private Int32 _denom; public Fraction(Int32 numer, Int32 denom) { _numer = numer; _denom = denom; } /// /// Converts the signed numerator and denominator values /// to its equivalent string representation. /// A fraction (x/y) is returned when applicable. public override string ToString() { Int32 numer = _numer; Int32 denom = (_denom == 0) ? 1 : _denom; // Make the numerator "store" the sign if (denom < 0) { numer *= -1; denom *= -1; } Reduce(ref numer, ref denom); string result; if (numer == 0) result = "0"; else if (denom == 1) result = numer + ""; else result = numer + "/" + denom; return result; } /// /// Reduces the rational number by dividing both the numerator /// and the denominator by their greatest common divisor. private static void Reduce(ref Int32 numer, ref Int32 denom) { if (numer != 0) { Int32 common = GCD(Math.Abs(numer), denom); numer /= common; denom /= common; } } /// /// Computes and returns the greatest common divisor of the two /// positive parameters. Uses Euclid's algorithm. private static Int32 GCD(Int32 num1, Int32 num2) { while (num1 != num2) if (num1 > num2) num1 -= num2; else num2 -= num1; return num1; } } public class UFraction { private UInt32 _numer; private UInt32 _denom; public UFraction(UInt32 numer, UInt32 denom) { _numer = numer; _denom = denom; } /// /// Converts the unsigned numerator and denominator values /// to its equivalent string representation. /// A fraction is used when applicable. public override string ToString() { UInt32 numer = _numer; UInt32 denom = (_denom == 0) ? 1 : _denom; Reduce(ref numer, ref denom); string result; if (numer == 0) result = "0"; else if (denom == 1) result = numer + ""; else result = numer + "/" + denom; return result; } /// /// Reduces the rational number by dividing both the numerator /// and the denominator by their greatest common divisor. private static void Reduce(ref UInt32 numer, ref UInt32 denom) { if (numer != 0) { UInt32 common = GCD(numer, denom); numer /= common; denom /= common; } } /// /// Computes and returns the greatest common divisor of the two /// positive parameters. Uses Euclid's algorithm. private static UInt32 GCD(UInt32 num1, UInt32 num2) { while (num1 != num2) if (num1 > num2) num1 -= num2; else num2 -= num1; return num1; } } public class Sorter : System.Collections.IComparer { public int Compare(object x, object y) { TreeNode tx = x as TreeNode; TreeNode ty = y as TreeNode; // If this is a child node, preserve the same order by comparing the node Index, not the text if (tx.Parent != null && ty.Parent != null) return tx.Index - ty.Index; // This is a root node, compare by name. return string.Compare(tx.Text, ty.Text); } } }