追記2024/10/6:FormatterServices
等のクラスはObsoluteになりました。FormatterServices.GetUninitializedObject(Type)
よりもRuntimeHelpers.GetUninitializedObject(Type)
が推奨されます(ソース)。
JPEGファイルEXIFデータのWindows用評価とキーワードを取得・設定・削除するサンプルコードです。
#nullable enable using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Runtime.Serialization; using System.Text; const string path = <対象とするJPEGのパス ※EXIF改変注意!>; using (var stream = new MemoryStream(File.ReadAllBytes(path))) { using var img = Image.FromStream(stream); var rating = ExifPropertyTagUtility.GetRating(img); var keywords = ExifPropertyTagUtility.GetXPKeywords(img); ExifPropertyTagUtility.SetRating(img, 5); ExifPropertyTagUtility.SetXPKeywords(img, new[] { "Hello", "EXIF" }); img.Save(path); } Console.ReadKey(); static class ExifPropertyTagUtility { // https://exiv2.org/tags.html public enum PropertyTags : int { Rating = 0x4746, XPKeywords = 0x9c9e, } public enum PropertyTypes : int { Byte = 1, ASCII = 2, Short = 3, Long = 4, Rational = 5, SByte = 6, Undefined = 7, SShort = 8, SLONG = 9, SRational = 10, Float = 11, Double = 12, } public static PropertyItem CreatePropertyItem() { return (PropertyItem)FormatterServices.GetSafeUninitializedObject(typeof(PropertyItem)); } public static short? GetValueShort(in Image jpeg, PropertyTags tag) { var item = jpeg.GetPropertyItem((int)tag); if (item is null || item.Type != (int)PropertyTypes.Short || item.Len != 2) return null; return BitConverter.ToInt16(item.Value); } public static void SetValueShort(in Image jpeg, PropertyTags tag, short value) { var item = CreatePropertyItem(); item.Id = (int)tag; item.Type = (int)PropertyTypes.Short; item.Len = 2; item.Value = BitConverter.GetBytes(value); jpeg.SetPropertyItem(item); } public static string? GetValueUni(in Image jpeg, PropertyTags tag) { var item = jpeg.GetPropertyItem((int)tag); if (item is null || item.Type != (int)PropertyTypes.Byte) return null; return Encoding.Unicode.GetString(item.Value!, 0, item.Len - 2); } public static void SetValueUni(in Image jpeg, PropertyTags tag, string value) { var bytes = Encoding.Unicode.GetBytes(value + '\0'); var item = CreatePropertyItem(); item.Id = (int)tag; item.Type = (int)PropertyTypes.Byte; item.Len = bytes.Length; item.Value = bytes; jpeg.SetPropertyItem(item); } public static short? GetRating(in Image jpeg) { return GetValueShort(jpeg, PropertyTags.Rating); } public static void SetRating(in Image jpeg, short value) { SetValueShort(jpeg, PropertyTags.Rating, value); } public static void RemoveRating(in Image jpeg) { jpeg.RemovePropertyItem((int)PropertyTags.Rating); } public static string[]? GetXPKeywords(in Image jpeg) { return GetValueUni(jpeg, PropertyTags.XPKeywords)?.Split(';') ?? null; } public static void SetXPKeywords(in Image jpeg, string[] value) { SetValueUni(jpeg, PropertyTags.XPKeywords, String.Join<string>(';', value)); } public static void RemoveXPKeywords(in Image jpeg) { jpeg.RemovePropertyItem((int)PropertyTags.XPKeywords); } }