LASAPlatform/Infrastructure/Helpers/ExifReader.cs

195 lines
7.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Helpers
{
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
public class ExifReader
{
// Exif 标签ID与名称的映射字典部分常见标签
private static readonly Dictionary<int, string> ExifTags = new Dictionary<int, string>
{
{ 0x010E, "ImageDescription" },
{ 0x010F, "Make" },
{ 0x0110, "Model" },
{ 0x0112, "Orientation" },
{ 0x011A, "XResolution" },
{ 0x011B, "YResolution" },
{ 0x0128, "ResolutionUnit" },
{ 0x0131, "Software" },
{ 0x0132, "DateTime" },
{ 0x0213, "YCbCrPositioning" },
{ 0x8769, "ExifIFD" },
{ 0x829A, "ExposureTime" },
{ 0x829D, "FNumber" },
{ 0x8822, "ExposureProgram" },
{ 0x8827, "ISOSpeedRatings" },
{ 0x9000, "ExifVersion" },
{ 0x9003, "DateTimeOriginal" },
{ 0x9004, "DateTimeDigitized" },
{ 0x9101, "ComponentsConfiguration" },
{ 0x9201, "ShutterSpeedValue" },
{ 0x9202, "ApertureValue" },
{ 0x9203, "BrightnessValue" },
{ 0x9204, "ExposureBiasValue" },
{ 0x9205, "MaxApertureValue" },
{ 0x9206, "SubjectDistance" },
{ 0x9207, "MeteringMode" },
{ 0x9208, "LightSource" },
{ 0x9209, "Flash" },
{ 0x920A, "FocalLength" },
{ 0x927C, "MakerNote" },
{ 0x9286, "UserComment" },
{ 0x9290, "SubsecTime" },
{ 0x9291, "SubsecTimeOriginal" },
{ 0x9292, "SubsecTimeDigitized" },
{ 0xA000, "FlashpixVersion" },
{ 0xA001, "ColorSpace" },
{ 0xA002, "PixelXDimension" },
{ 0xA003, "PixelYDimension" },
{ 0xA004, "RelatedSoundFile" },
{ 0xA005, "InteroperabilityIFD" },
{ 0xA20B, "FlashEnergy" },
{ 0xA20C, "SpatialFrequencyResponse" },
{ 0xA20E, "FocalPlaneXResolution" },
{ 0xA20F, "FocalPlaneYResolution" },
{ 0xA210, "FocalPlaneResolutionUnit" },
{ 0xA214, "SubjectLocation" },
{ 0xA215, "ExposureIndex" },
{ 0xA217, "SensingMethod" },
{ 0xA300, "FileSource" },
{ 0xA301, "SceneType" },
{ 0xA302, "CFAPattern" },
{ 0xA401, "CustomRendered" },
{ 0xA402, "ExposureMode" },
{ 0xA403, "WhiteBalance" },
{ 0xA404, "DigitalZoomRatio" },
{ 0xA405, "FocalLengthIn35mmFilm" },
{ 0xA406, "SceneCaptureType" },
{ 0xA407, "GainControl" },
{ 0xA408, "Contrast" },
{ 0xA409, "Saturation" },
{ 0xA40A, "Sharpness" },
{ 0xA40B, "DeviceSettingDescription" },
{ 0xA40C, "SubjectDistanceRange" },
{ 0xA420, "ImageUniqueID" },
{ 0xA431, "BodySerialNumber" },
{ 0xA432, "LensSpecification" },
{ 0xA433, "LensMake" },
{ 0xA434, "LensModel" },
{ 0xA435, "LensSerialNumber" },
{ 0x8298, "Copyright" }, // 这是你特别关心的 Copyright 字段
{ 0x013B, "Artist" },
{ 0x9C9B, "WindowsTitle" },
{ 0x9C9C, "WindowsComment" },
{ 0x9C9D, "WindowsAuthor" },
{ 0x9C9E, "WindowsKeywords" },
{ 0x9C9F, "WindowsSubject" }
};
public static Dictionary<string, string> GetAllExifData(Stream imageStream)
{
var exifData = new Dictionary<string, string>();
using (Image image = Image.FromStream(imageStream))
{
foreach (PropertyItem propItem in image.PropertyItems)
{
string tagName = ExifTags.ContainsKey(propItem.Id) ?
ExifTags[propItem.Id] : $"Unknown (0x{propItem.Id:X4})";
string value = InterpretExifValue(propItem);
exifData[tagName] = value;
}
}
return exifData;
}
private static string InterpretExifValue(PropertyItem propItem)
{
try
{
switch (propItem.Type)
{
case 1: // Byte array
return $"Byte[{propItem.Len}]";
case 2: // ASCII string
return Encoding.ASCII.GetString(propItem.Value).TrimEnd('\0');
case 3: // Unsigned short (16-bit)
if (propItem.Len == 2)
return BitConverter.ToUInt16(propItem.Value, 0).ToString();
break;
case 4: // Unsigned long (32-bit)
if (propItem.Len == 4)
return BitConverter.ToUInt32(propItem.Value, 0).ToString();
break;
case 5: // Unsigned rational (two 32-bit values: numerator/denominator)
if (propItem.Len == 8)
{
uint numerator = BitConverter.ToUInt32(propItem.Value, 0);
uint denominator = BitConverter.ToUInt32(propItem.Value, 4);
return denominator != 0 ? $"{numerator}/{denominator}" : "Invalid rational";
}
break;
case 7: // Undefined
return $"Undefined[{propItem.Len}]";
case 9: // Signed long (32-bit)
if (propItem.Len == 4)
return BitConverter.ToInt32(propItem.Value, 0).ToString();
break;
case 10: // Signed rational (two 32-bit values: numerator/denominator)
if (propItem.Len == 8)
{
int numerator = BitConverter.ToInt32(propItem.Value, 0);
int denominator = BitConverter.ToInt32(propItem.Value, 4);
return denominator != 0 ? $"{numerator}/{denominator}" : "Invalid rational";
}
break;
}
return $"Type {propItem.Type}[{propItem.Len}]";
}
catch (Exception ex)
{
return $"Error reading value: {ex.Message}";
}
}
// 专门获取 Copyright 信息的方法
public static string GetCopyright(Stream imageStream)
{
using (Image image = Image.FromStream(imageStream))
{
try
{
// 0x8298 是 Copyright 的 Exif tag ID
PropertyItem copyrightProp = image.GetPropertyItem(0x8298);
return InterpretExifValue(copyrightProp);
}
catch (ArgumentException)
{
// 如果没有找到 Copyright 属性
return "No copyright information";
}
}
}
}
}