📄 exifpropertyformatter.cs
字号:
//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
// Copyright (c) Telligent Systems Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Drawing.Imaging;
namespace CommunityServer.Galleries.Components
{
/// <summary>
/// Provides formatting methods for property tag values.
/// </summary>
public class ExifPropertyFormatter
{
/// <summary>
/// Defines the DOUBLE format used when formatting Rational and
/// SRational Property Tag types.</summary>
private const string DOUBLETYPE_FORMAT = "0.#";
/// <summary>
/// Index byte jump for a PropertyItem's byte array of Shorts.
/// </summary>
private const int BYTEJUMP_SHORT = 2;
/// <summary>
/// Index byte jump for a PropertyItem's byte array of Longs.
/// </summary>
private const int BYTEJUMP_LONG = 4;
/// <summary>
/// Index byte jump for a PropertyItem's byte array of Rationals.
/// </summary>
private const int BYTEJUMP_RATIONAL = 8;
/// <summary>
/// Index byte jump for a PropertyItem's byte array of SLongs.
/// </summary>
private const int BYTEJUMP_SLONG = 4;
/// <summary>
/// Index byte jump for a PropertyItem's byte array of SRationals.
/// </summary>
private const int BYTEJUMP_SRATIONAL = 8;
#region Image Property Tag Types
/// <summary>BYTE</summary>
/// <remarks>An 8-bit unsigned integer.</remarks>
private const int PropertyTagTypeByte = 1;
/// <summary>ASCII</summary>
/// <remarks>An 8-bit byte containing one 7-bit ASCII code.
/// The final byte is terminated with NULL.</remarks>
private const int PropertyTagTypeASCII = 2;
/// <summary>SHORT</summary>
/// <remarks>A 16-bit (2-byte) unsigned integer</remarks>
private const int PropertyTagTypeShort = 3;
/// <summary>LONG</summary>
/// <remarks>A 32-bit (4-byte) unsigned integer</remarks>
private const int PropertyTagTypeLong = 4;
/// <summary>RATIONAL</summary>
/// <remarks>Two LONGs.
/// The first LONG is the numerator.
/// The second LONG is the denominator.</remarks>
private const int PropertyTagTypeRational = 5;
/// <summary>UNDEFINED</summary>
/// <remarks>An 8-bit byte that can take any value
/// depending on the field definition</remarks>
private const int PropertyTagTypeUndefined = 7;
/// <summary>SLONG</summary>
/// <remarks>A 32-bit (4-byte) signed integer (2's complement notation)</remarks>
private const int PropertyTagTypeSLong = 9;
/// <summary>SRATIONAL</summary>
/// <remarks>Two SLONGs.
/// The first SLONG is the numerator.
/// The second SLONG is the denominator.</remarks>
private const int PropertyTagTypeSRational = 10;
#endregion
/// <summary>
/// Converts a PropertyItem's byte data to a formatted string.</summary>
/// <remarks>The format is based upon the data's tag type as well
/// as further information included in the item's ExifPropertyTag.</remarks>
/// <param name="propItem">A specific PropertyItem.</param>
/// <param name="tagMetadata">A specific ExifPropertyTag instance.</param>
/// <returns>A string representation of the data.</returns>
public static string ToFormattedValue(PropertyItem propItem)
{
if (propItem == null) return String.Empty;
string strRet;
FormatInstruction format = FindSpecialFormat((ExifProperty)propItem.Id);
switch (propItem.Type)
{
case PropertyTagTypeByte:
strRet = FormatTagByte(propItem, format);
break;
case PropertyTagTypeASCII:
strRet = FormatTagAscii(propItem, format);
break;
case PropertyTagTypeShort:
strRet = FormatTagShort(propItem);
break;
case PropertyTagTypeLong:
strRet = FormatTagLong(propItem);
break;
case PropertyTagTypeRational:
strRet = FormatTagRational(propItem, format);
break;
case PropertyTagTypeUndefined:
strRet = FormatTagUndefined(propItem, format);
break;
case PropertyTagTypeSLong:
strRet = FormatTagSLong(propItem);
break;
case PropertyTagTypeSRational:
strRet = FormatTagSRational(propItem, format);
break;
default:
strRet = "";
break;
}
return strRet;
}
/// <summary>
/// Converts an <see cref="ExifPropertyItem"/> object from it's native type to a byte array.
/// </summary>
/// <param name="exifPropertyItemValue">The <see cref="ExifPropertyItem"/> to convert.</param>
/// <returns>A byte representation of the data.</returns>
public static byte[] ToPropertyItemValue(object exifPropertyItemValue)
{
byte[] returnBytes = null;
if (exifPropertyItemValue.GetType() == typeof(System.DateTime))
{
DateTime dt = (DateTime)exifPropertyItemValue;
returnBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(dt.ToString() + "\0");
}
else if (exifPropertyItemValue.GetType() == typeof(System.Int16))
{
returnBytes = System.BitConverter.GetBytes((short)exifPropertyItemValue);
}
else if (exifPropertyItemValue.GetType() == typeof(System.String))
{
returnBytes = System.Text.ASCIIEncoding.ASCII.GetBytes((string)exifPropertyItemValue + "\0");
}
return returnBytes;
}
/// <summary>
/// Format a Byte tag.
/// </summary>
/// <param name="propItem">The <see cref="PropertyItem"/> to format.</param>
/// <param name="FormatInstruction">The <see cref="FormatInstruction"/> to use for formatting.</param>
/// <returns>A formatted Byte string.</returns>
private static string FormatTagByte(PropertyItem propItem, FormatInstruction format)
{
string strRet;
if(format == FormatInstruction.BASE64)
{
strRet = Convert.ToBase64String(propItem.Value);
}
else
{
strRet = BitConverter.ToString(propItem.Value, 0, propItem.Len);
}
return strRet;
}
/// <summary>
/// Format an ASCII tag.
/// </summary>
/// <param name="propItem">The <see cref="PropertyItem"/> to format.</param>
/// <param name="FormatInstruction">The <see cref="FormatInstruction"/> to use for formatting.</param>
/// <returns>A formatted ASCII string.</returns>
/// <remarks>The null termination is removed when the string is formatted.</remarks>
private static string FormatTagAscii(PropertyItem propItem, FormatInstruction format)
{
string strRet = "";
if(format == FormatInstruction.DATETIME)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
string date = encoding.GetString(propItem.Value, 0, propItem.Len - 1);
try
{
strRet = DateTime.ParseExact(date, "yyyy:MM:dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.CurrentInfo, System.Globalization.DateTimeStyles.AllowWhiteSpaces).ToString();
}
catch ( System.FormatException )
{
strRet = date;
}
}
else
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
strRet = encoding.GetString(propItem.Value, 0, propItem.Len - 1);
}
return strRet;
}
/// <summary>
/// Format a Short tag (unsigned).
/// </summary>
/// <param name="propItem">The <see cref="PropertyItem"/> to format.</param>
/// <returns>A formatted unsigned Short (<see cref="UInt16"/>) string</returns>
private static string FormatTagShort(PropertyItem propItem)
{
string strRet = "";
for (int i = 0; i < propItem.Len; i = i + BYTEJUMP_SHORT)
{
System.UInt16 val = BitConverter.ToUInt16(propItem.Value, i);
strRet += val.ToString();
if (i + BYTEJUMP_SHORT < propItem.Len) strRet += " ";
}
return strRet;
}
/// <summary>
/// Format a Long tag (unsigned).
/// </summary>
/// <param name="propItem">The <see cref="PropertyItem"/> to format.</param>
/// <returns>A formatted unsigned Long (<see cref="UInt32"/> string.</returns>
private static string FormatTagLong(PropertyItem propItem)
{
string strRet = "";
for (int i = 0; i < propItem.Len; i = i + BYTEJUMP_LONG)
{
System.UInt32 val = BitConverter.ToUInt32(propItem.Value, i);
strRet += val.ToString();
if (i + BYTEJUMP_LONG < propItem.Len) strRet += " ";
}
return strRet;
}
/// <summary>
/// Format a Rational tag (unsigned).
/// </summary>
/// <param name="propItem">The <see cref="PropertyItem"/> to format.</param>
/// <param name="FormatInstruction">The <see cref="FormatInstruction"/> to use for formatting.</param>
/// <returns>A formatted Rational string.</returns>
/// <remarks>By defailt a string will be formatted as decimal unless the <see cref="FormatInstruction"/> is <see cref="FormatInstruction.FRACTION"/></remarks>
private static string FormatTagRational(PropertyItem propItem, FormatInstruction format)
{
string strRet = "";
for (int i = 0; i < propItem.Len; i = i + BYTEJUMP_RATIONAL)
{
System.UInt32 numer = BitConverter.ToUInt32(propItem.Value, i);
System.UInt32 denom = BitConverter.ToUInt32(propItem.Value, i + BYTEJUMP_LONG);
if (format == FormatInstruction.FRACTION)
{
strRet += ToRationalString(numer, denom);
}
else
{
double dbl;
if (denom == 0) dbl = 0.0;
else dbl = (double)numer / (double)denom;
strRet += dbl.ToString(DOUBLETYPE_FORMAT);
}
if (i + BYTEJUMP_RATIONAL < propItem.Len) strRet += " ";
}
return strRet;
}
/// <summary>
/// Format a Undefined tag.
/// </summary>
/// <param name="propItem">The <see cref="PropertyItem"/> to format.</param>
/// <param name="FormatInstruction">The <see cref="FormatInstruction"/> to use for formatting.</param>
/// <returns>A formatted Rational string.</returns>
/// <remarks>Valid formatting instructions are:
/// <list type="bullet">
/// <term><see cref="FormatInstruction.ALLCHAR"/></term>
/// <term><see cref="FormatInstruction.UNICODE"/></term>
/// <term><see cref="FormatInstruction.USERCOMMENT"/></term>
/// </list>
/// </remarks>
private static string FormatTagUndefined(PropertyItem propItem, FormatInstruction format)
{
string strRet;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -