public XimgGPSRational(byte[] bytes) { byte[] h = new byte[8]; byte[] m = new byte[8]; byte[] s = new byte[8]; Array.Copy(bytes, 0, h, 0, 8); Array.Copy(bytes, 8, m, 0, 8); Array.Copy(bytes, 16, s, 0, 8); _hours = new XimgRational(h); _minutes = new XimgRational(m); _seconds = new XimgRational(s); _degrees = _hours.ToDouble() + (_minutes.ToDouble() / 60) + (_seconds.ToDouble() / 3600); }
public override string ToString() { return(_hours.ToDouble() + "° " + _minutes.ToDouble() + "\' " + _seconds.ToDouble() + "\""); }
public XimgParse(System.Drawing.Image image) { Encoding ascii = Encoding.ASCII; _parseTags = new Dictionary <int, XimgTag>(); foreach (System.Drawing.Imaging.PropertyItem pitem in image.PropertyItems) { if (!ParseTags.ContainsKey(pitem.Id)) { continue; } XimgTag xTag = ParseTags[pitem.Id].Clone(); string strValue = ""; object value = null; switch (pitem.Type) { case 0x1: { #region BYTE (8-bit unsigned int) value = pitem.Value[0]; if (pitem.Value.Length == 4) { strValue = "Version " + pitem.Value[0].ToString() + "." + pitem.Value[1].ToString(); } else if (pitem.Id == 0x5 && pitem.Value[0] == 0) { strValue = "Sea level"; } else { strValue = pitem.Value[0].ToString(); } #endregion } break; case 0x2: { #region ASCII (8 bit ASCII code) strValue = ascii.GetString(pitem.Value).Trim('\0'); value = strValue; if (pitem.Id == 0x1 || pitem.Id == 0x13) { if (strValue == "N") { strValue = "North latitude"; } else if (strValue == "S") { strValue = "South latitude"; } else { strValue = "n/a"; } } if (pitem.Id == 0x3 || pitem.Id == 0x15) { if (strValue == "E") { strValue = "East longitude"; } else if (strValue == "W") { strValue = "West longitude"; } else { strValue = "n/a"; } } if (pitem.Id == 0x9) { if (strValue == "A") { strValue = "Measurement in progress"; } else if (strValue == "V") { strValue = "Measurement Interoperability"; } else { strValue = "n/a"; } } if (pitem.Id == 0xA) { if (strValue == "2") { strValue = "2-dimensional measurement"; } else if (strValue == "3") { strValue = "3-dimensional measurement"; } else { strValue = "n/a"; } } if (pitem.Id == 0xC || pitem.Id == 0x19) { if (strValue == "K") { strValue = "Kilometers per hour"; } else if (strValue == "M") { strValue = "Miles per hour"; } else if (strValue == "N") { strValue = "Knots"; } else { strValue = "n/a"; } } if (pitem.Id == 0xE || pitem.Id == 0x10 || pitem.Id == 0x17) { if (strValue == "T") { strValue = "True direction"; } else if (strValue == "M") { strValue = "Magnetic direction"; } else { strValue = "n/a"; } } #endregion } break; case 0x3: { #region 3 = SHORT (16-bit unsigned int) UInt16 uintval = BitConverter.ToUInt16(pitem.Value, 0); value = uintval; // orientation // lookup table switch (pitem.Id) { case 0x8827: // ISO speed rating strValue = "ISO-" + uintval.ToString(); break; case 0xA217: // sensing method { switch (uintval) { case 1: strValue = "Not defined"; break; case 2: strValue = "One-chip color area sensor"; break; case 3: strValue = "Two-chip color area sensor"; break; case 4: strValue = "Three-chip color area sensor"; break; case 5: strValue = "Color sequential area sensor"; break; case 7: strValue = "Trilinear sensor"; break; case 8: strValue = "Color sequential linear sensor"; break; default: strValue = " reserved"; break; } } break; case 0x8822: // Exposure program switch (uintval) { case 0: strValue = "Not defined"; break; case 1: strValue = "Manual"; break; case 2: strValue = "Normal program"; break; case 3: strValue = "Aperture priority"; break; case 4: strValue = "Shutter priority"; break; case 5: strValue = "Creative program (biased toward depth of field)"; break; case 6: strValue = "Action program (biased toward fast shutter speed)"; break; case 7: strValue = "Portrait mode (for closeup photos with the background out of focus)"; break; case 8: strValue = "Landscape mode (for landscape photos with the background in focus)"; break; default: strValue = "n/a"; break; } break; case 0x9207: // metering mode switch (uintval) { case 0: strValue = "unknown"; break; case 1: strValue = "Average"; break; case 2: strValue = "Center Weighted Average"; break; case 3: strValue = "Spot"; break; case 4: strValue = "MultiSpot"; break; case 5: strValue = "Pattern"; break; case 6: strValue = "Partial"; break; case 255: strValue = "Other"; break; default: strValue = "n/a"; break; } break; case 0x9208: // Light source { switch (uintval) { case 0: strValue = "unknown"; break; case 1: strValue = "Daylight"; break; case 2: strValue = "Fluorescent"; break; case 3: strValue = "Tungsten (incandescent light)"; break; case 4: strValue = "Flash"; break; case 9: strValue = "Fine weather"; break; case 10: strValue = "Cloudy weather"; break; case 11: strValue = "Shade"; break; case 12: strValue = "Daylight fluorescent (D 5700 – 7100K)"; break; case 13: strValue = "Day white fluorescent (N 4600 – 5400K)"; break; case 14: strValue = "Cool white fluorescent (W 3900 – 4500K)"; break; case 15: strValue = "White fluorescent (WW 3200 – 3700K)"; break; case 17: strValue = "Standard light A"; break; case 18: strValue = "Standard light B"; break; case 19: strValue = "Standard light C"; break; case 20: strValue = "D55"; break; case 21: strValue = "D65"; break; case 22: strValue = "D75"; break; case 23: strValue = "D50"; break; case 24: strValue = "ISO studio tungsten"; break; case 255: strValue = "ISO studio tungsten"; break; default: strValue = "other light source"; break; } } break; case 0x9209: // Flash { switch (uintval) { case 0x0: strValue = "Flash did not fire"; break; case 0x1: strValue = "Flash fired"; break; case 0x5: strValue = "Strobe return light not detected"; break; case 0x7: strValue = "Strobe return light detected"; break; case 0x9: strValue = "Flash fired, compulsory flash mode"; break; case 0xD: strValue = "Flash fired, compulsory flash mode, return light not detected"; break; case 0xF: strValue = "Flash fired, compulsory flash mode, return light detected"; break; case 0x10: strValue = "Flash did not fire, compulsory flash mode"; break; case 0x18: strValue = "Flash did not fire, auto mode"; break; case 0x19: strValue = "Flash fired, auto mode"; break; case 0x1D: strValue = "Flash fired, auto mode, return light not detected"; break; case 0x1F: strValue = "Flash fired, auto mode, return light detected"; break; case 0x20: strValue = "No flash function"; break; case 0x41: strValue = "Flash fired, red-eye reduction mode"; break; case 0x45: strValue = "Flash fired, red-eye reduction mode, return light not detected"; break; case 0x47: strValue = "Flash fired, red-eye reduction mode, return light detected"; break; case 0x49: strValue = "Flash fired, compulsory flash mode, red-eye reduction mode"; break; case 0x4D: strValue = "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected"; break; case 0x4F: strValue = "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected"; break; case 0x59: strValue = "Flash fired, auto mode, red-eye reduction mode"; break; case 0x5D: strValue = "Flash fired, auto mode, return light not detected, red-eye reduction mode"; break; case 0x5F: strValue = "Flash fired, auto mode, return light detected, red-eye reduction mode"; break; default: strValue = "n/a"; break; } } break; case 0x0128: //ResolutionUnit { switch (uintval) { case 2: strValue = "Inch"; break; case 3: strValue = "Centimeter"; break; default: strValue = "No Unit"; break; } } break; case 0xA409: // Saturation { switch (uintval) { case 0: strValue = "Normal"; break; case 1: strValue = "Low saturation"; break; case 2: strValue = "High saturation"; break; default: strValue = "n/a"; break; } } break; case 0xA40A: // Sharpness { switch (uintval) { case 0: strValue = "Normal"; break; case 1: strValue = "Soft"; break; case 2: strValue = "Hard"; break; default: strValue = "n/a"; break; } } break; case 0xA408: // Contrast { switch (uintval) { case 0: strValue = "Normal"; break; case 1: strValue = "Soft"; break; case 2: strValue = "Hard"; break; default: strValue = "n/a"; break; } } break; case 0x103: // Compression { switch (uintval) { case 1: strValue = "Uncompressed"; break; case 6: strValue = "JPEG compression (thumbnails only)"; break; default: strValue = "n/a"; break; } } break; case 0x106: // PhotometricInterpretation { switch (uintval) { case 2: strValue = "RGB"; break; case 6: strValue = "YCbCr"; break; default: strValue = "n/a"; break; } } break; case 0x112: // Orientation { switch (uintval) { case 1: strValue = "The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side."; break; case 2: strValue = "The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side."; break; case 3: strValue = "The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side."; break; case 4: strValue = "The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side."; break; case 5: strValue = "The 0th row is the visual left-hand side of the image, and the 0th column is the visual top."; break; case 6: strValue = "The 0th row is the visual right-hand side of the image, and the 0th column is the visual top."; break; case 7: strValue = "The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom."; break; case 8: strValue = "The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom."; break; default: strValue = "n/a"; break; } } break; case 0x213: // YCbCrPositioning { switch (uintval) { case 1: strValue = "centered"; break; case 6: strValue = "co-sited"; break; default: strValue = "n/a"; break; } } break; case 0xA001: // ColorSpace { switch (uintval) { case 1: strValue = "sRGB"; break; case 0xFFFF: strValue = "Uncalibrated"; break; default: strValue = "n/a"; break; } } break; case 0xA401: // CustomRendered { switch (uintval) { case 0: strValue = "Normal process"; break; case 1: strValue = "Custom process"; break; default: strValue = "n/a"; break; } } break; case 0xA402: // ExposureMode { switch (uintval) { case 0: strValue = "Auto exposure"; break; case 1: strValue = "Manual exposure"; break; case 2: strValue = "Auto bracket"; break; default: strValue = "n/a"; break; } } break; case 0xA403: // WhiteBalance { switch (uintval) { case 0: strValue = "Auto white balance"; break; case 1: strValue = "Manual white balance"; break; default: strValue = "n/a"; break; } } break; case 0xA406: // SceneCaptureType { switch (uintval) { case 0: strValue = "Standard"; break; case 1: strValue = "Landscape"; break; case 2: strValue = "Portrait"; break; case 3: strValue = "Night scene"; break; default: strValue = "n/a"; break; } } break; case 0xA40C: // SubjectDistanceRange { switch (uintval) { case 0: strValue = "unknown"; break; case 1: strValue = "Macro"; break; case 2: strValue = "Close view"; break; case 3: strValue = "Distant view"; break; default: strValue = "n/a"; break; } } break; case 0x1E: // GPSDifferential { switch (uintval) { case 0: strValue = "Measurement without differential correction"; break; case 1: strValue = "Differential correction applied"; break; default: strValue = "n/a"; break; } } break; case 0xA405: // FocalLengthIn35mmFilm strValue = uintval.ToString() + " mm"; break; default: // strValue = uintval.ToString(); break; } #endregion } break; case 0x4: { #region 4 = LONG (32-bit unsigned int) value = BitConverter.ToUInt32(pitem.Value, 0); strValue = value.ToString(); #endregion } break; case 0x5: { #region 5 = RATIONAL (Two LONGs, unsigned) XimgURational rat = new XimgURational(pitem.Value); value = rat; switch (pitem.Id) { case 0x9202: // ApertureValue strValue = "F/" + Math.Round(Math.Pow(Math.Sqrt(2), rat.ToDouble()), 2).ToString(); break; case 0x9205: // MaxApertureValue strValue = "F/" + Math.Round(Math.Pow(Math.Sqrt(2), rat.ToDouble()), 2).ToString(); break; case 0x920A: // FocalLength strValue = rat.ToDouble().ToString() + " mm"; break; case 0x829D: // F-number strValue = "F/" + rat.ToDouble().ToString(); break; case 0x11A: // Xresolution strValue = rat.ToDouble().ToString(); break; case 0x11B: // Yresolution strValue = rat.ToDouble().ToString(); break; case 0x829A: // ExposureTime strValue = rat.ToString() + " sec"; break; case 0x2: // GPSLatitude value = new XimgGPSRational(pitem.Value); strValue = value.ToString(); break; case 0x4: // GPSLongitude value = new XimgGPSRational(pitem.Value); strValue = value.ToString(); break; case 0x6: // GPSAltitude strValue = rat.ToDouble() + " meters"; break; case 0xA404: // Digital Zoom Ratio strValue = rat.ToDouble().ToString(); if (strValue == "0") { strValue = "none"; } break; case 0xB: // GPSDOP strValue = rat.ToDouble().ToString(); break; case 0xD: // GPSSpeed strValue = rat.ToDouble().ToString(); break; case 0xF: // GPSTrack strValue = rat.ToDouble().ToString(); break; case 0x11: // GPSImgDir strValue = rat.ToDouble().ToString(); break; case 0x14: // GPSDestLatitude value = new XimgGPSRational(pitem.Value); strValue = value.ToString(); break; case 0x16: // GPSDestLongitude value = new XimgGPSRational(pitem.Value); strValue = value.ToString(); break; case 0x18: // GPSDestBearing strValue = rat.ToDouble().ToString(); break; case 0x1A: // GPSDestDistance strValue = rat.ToDouble().ToString(); break; case 0x7: // GPSTimeStamp value = new XimgGPSRational(pitem.Value); strValue = (value as XimgGPSRational).ToString(":"); break; default: strValue = rat.ToString(); break; } #endregion } break; case 0x7: { #region UNDEFINED (8-bit) value = pitem.Value[0]; switch (pitem.Id) { case 0xA300: //FileSource { if (pitem.Value[0] == 3) { strValue = "DSC"; } else { strValue = "n/a"; } break; } case 0xA301: //SceneType if (pitem.Value[0] == 1) { strValue = "A directly photographed image"; } else { strValue = "n/a"; } break; case 0x9000: // Exif Version strValue = ascii.GetString(pitem.Value).Trim('\0'); break; case 0xA000: // Flashpix Version strValue = ascii.GetString(pitem.Value).Trim('\0'); if (strValue == "0100") { strValue = "Flashpix Format Version 1.0"; } else { strValue = "n/a"; } break; case 0x9101: //ComponentsConfiguration strValue = GetComponentsConfig(pitem.Value); break; case 0x927C: //MakerNote strValue = ascii.GetString(pitem.Value).Trim('\0'); break; case 0x9286: //UserComment strValue = ascii.GetString(pitem.Value).Trim('\0'); break; case 0x1B: //GPS Processing Method strValue = ascii.GetString(pitem.Value).Trim('\0'); break; case 0x1C: //GPS Area Info strValue = ascii.GetString(pitem.Value).Trim('\0'); break; default: strValue = "-"; break; } #endregion } break; case 0x9: { #region 9 = SLONG (32-bit int) value = BitConverter.ToInt32(pitem.Value, 0); strValue = value.ToString(); #endregion } break; case 0xA: { #region 10 = SRATIONAL (Two SLONGs, signed) XimgRational rat = new XimgRational(pitem.Value); value = rat; switch (pitem.Id) { case 0x9201: // ShutterSpeedValue strValue = "1/" + Math.Round(Math.Pow(2, rat.ToDouble()), 2).ToString(); break; case 0x9203: // BrightnessValue strValue = Math.Round(rat.ToDouble(), 4).ToString(); break; case 0x9204: // ExposureBiasValue strValue = Math.Round(rat.ToDouble(), 2).ToString() + " eV"; break; default: strValue = rat.ToString(); break; } #endregion } break; } xTag.Value = value; xTag.StrValue = strValue; xTag.ItemType = pitem.Type; _parseTags.Add(xTag.Id, xTag); } }