C# System.Drawing.Image를 이용한 Exif Tag 사용

Featured image

Git Source


안녕하세요. chanos입니다. 😉

오늘은 Exif Tag에 관한 글입니다.

Jpeg에 메타데이터를 넣어야할 때 Exif Tag를 사용할 수 있는데요.

System.Drawing.Image 라이브러리를 이용해서 Exif Tag를 읽고 쓰는 방법을 알아보겠습니다.

Image의 메타데이터는 PropertyItems 속성에 관리가 됩니다.

PropertyItems의 타입은 PropertyItem 객체의 array 형식이며, 추가, 수정, 삭제를 하기 위해서는 Image 객체의 인스턴스 메서드인 SetPropertyItem, RemovePropertyItem를 사용합니다.

PropertyItem 객체의 속성은 다음과 같습니다.

Property Description
Id Exif Tag의 Id 값
Len Value의 길이
Type Tag 데이터의 형식
Value 데이터

위 객체 및 메서드를 이용하여 코드를 작성하면 다음과 같이 작성할 수 있습니다.

// Artist Tag 추가

var img = Image.FromFile("star.jpg");

var propertyItem = img.PropertyItems[0];

// string인 경우 null 종결자 필요
var val = Encoding.UTF8.GetBytes($"Tag Test!!\0");
propertyItem.Id = 0x013b; // Artist
propertyItem.Type = 2; // ascii string인 경우 type이 2
propertyItem.Value = val;
propertyItem.Len = val.Length;

img.SetPropertyItem(propertyItem);

새로운 Tag를 삽입해야 될 경우 PropertyItem 객체를 생성해야 되는데, 해당 객체는 Constructor가 존재하지 않습니다.

더불어 PropertyItem은 sealed 키워드를 사용하고 있어 상속이 불가능합니다.

검색을 통해 자료를 찾아본결과 위와 같이 0번째 인덱스 객체를 가져와 사용을 하는데요.

이렇게 사용할 경우 Id 값이 같을 때는 덮어써지고, 다르다면 새로운 PropertyItem이 PropertyItems에 추가됩니다.

정상적으로 작동을 하기는 하지만 코드로만 봤을 때는 0번째 요소의 값을 수정하는 것 처럼 보이기 때문에 Tag를 추가한다는 행위가 명확하지 않은 것 같습니다.

이를 보완하기 위해 FormatterServices를 이용하면 객체를 생성할 수 있는데요.

FormatterServices의 GetUninitializedObject 정적 메서드를 이용하면 생성자를 호출하지 않고 0 or null로 초기화된 객체를 생성할 수 있습니다.

// Artist Tag 추가

var img = Image.FromFile("star.jpg");

var propertyItem = FormatterServices.GetUninitializedObject(typeof(PropertyItem)) as PropertyItem;

// string인 경우 null 종결자 필요
var val = Encoding.UTF8.GetBytes($"Tag Test!!\0");
propertyItem.Id = 0x013b; // Artist
propertyItem.Type = 2; // ascii string인 경우 type이 2
propertyItem.Value = val;
propertyItem.Len = val.Length;

img.SetPropertyItem(propertyItem);

위와 같이 작성한다면 새로운 태그를 추가한다는 행위를 명확하게 표현할 수 있지 않을까 싶습니다.

태그를 삭제하는 방법은 RemovePropertyItem 메서드를 이용하면 됩니다.

// Artist Tag 삭제
img.RemovePropertyItem(0x013b);

exif


Reference

C# PropertyItem

Exif Tags