Exif Properties in .Net - Part 3 : converting properties

In the first post of this Exif series, I talked about a technique for loading Exif properties as fast as GDI+ is able to do.
The second post was dealing with adding new properties to an empty image.

Now it's time to look more precisely at the Exif properties. How is a PropertyItem structured ?
The final goal of this post is to convert the raw data exposed by GDI+ (and the .Net Framework) into more useable data types.

An Exif property consists in the following information:

  • An identifier, determining the "meaning" of the property.
  • A data type, indicating how the data are represented.
  • A length (the number of bytes the property data contains).
  • A value which is a raw array of bytes.

The Exif property data type is a 16-bit integer, but it's quite simple to build an enum type that maps the values to a more comprehensive type :

Code Copy HideScrollFull
/// <summary>
///
Defines types for Exif Properties.
/// </summary>
public enum ExifPropertyType {
/// <summary>
/// Specifies that the value data member is an array of bytes.
/// </summary>
Byte = 1,

/// <summary>
/// Specifies that the value data member is a null-terminated ASCII string.
/// </summary>
/// <remarks>If you set <see cref="PropertyItem.Type">PropertyItem.Type</see> to <see cref="PropertyItem.Type"/>, you should set the length data member to the length of the string including the NULL terminator. For example, the string HELLO would have a length of 6.</remarks>
Ascii = 2,

/// <summary>
/// Specifies that the value data member is an array of signed short (16-bit) integers.
/// </summary>
UInt16 = 3,

/// <summary>
/// Specifies that the value data member is an array of unsigned long (32-bit) integers.
/// </summary>
UInt32 = 4,

/// <summary>
/// Specifies that the value data member is an array of pairs of unsigned long integers. Each pair represents a fraction; the first integer is the numerator and the second integer is the denominator.
/// </summary>
URational = 5,

/// <summary>
/// Specifies that the value data member is an array of bytes that can hold values of any data type.
/// </summary>
Raw = 7,

/// <summary>
/// Specifies that the value data member is an array of signed long (32-bit) integers.
/// </summary>
Int32 = 9,

/// <summary>
/// Specifies that the value data member is an array of pairs of signed long integers. Each pair represents a fraction; the first integer is the numerator and the second integer is the denominator.
/// </summary>
Rational = 10,
}
. . .

As you can see in the code above, most of the data types are simple and can be directly mapped to .Net data types, excepted for rational and unsigned rational values. We need to create a .Net representation for each of them :

  • Rational :
Code Copy HideScrollFull
/// <summary>
///
Represents a signed rational number.
/// </summary>
public class Rational {
private int numerator;
private int denominator;

/// <summary>
/// Initializes a new instance of the <see cref="Rational"/> class.
/// </summary>
/// <param name="numerator">The numerator of the rational number.</param>
/// <param name="denominator">The denominator of the rational number.</param>
public Rational(int numerator, int denominator) {
this.numerator = numerator;
this.denominator = denominator;
}

/// <summary>
/// Gets the numerator of the rational number.
/// </summary>
public int Numerator {
get {
return numerator;
}
}

/// <summary>
/// Gets the denominator of the rational number.
/// </summary>
public int Denominator {
get {
return denominator;
}
}

/// <summary>
/// Gets the floating-point value of the rational number.
/// </summary>
public double Value {
get {
return (double) numerator/(double) denominator;
}
}

/// <exclude/>
public override string ToString() {
return Value.ToString();
}
}
. . .
  • URational :
Code Copy HideScrollFull
/// <summary>
///
Represents an unsigned rational number.
/// </summary>
public class URational {
private uint numerator;
private uint denominator;

/// <summary>
/// Initializes a new instance of the <see cref="Rational"/> class.
/// </summary>
/// <param name="numerator">The numerator of the rational number.</param>
/// <param name="denominator">The denominator of the rational number.</param>
public URational(uint numerator, uint denominator) {
this.numerator = numerator;
this.denominator = denominator;
}

/// <summary>
/// Gets the numerator of the rational number.
/// </summary>
public uint Numerator {
get {
return numerator;
}
}

/// <summary>
/// Gets the denominator of the rational number.
/// </summary>
public uint Denominator {
get {
return denominator;
}
}

/// <summary>
/// Gets the floating-point value of the rational number.
/// </summary>
public double Value {
get {
return (double) numerator/(double) denominator;
}
}

/// <exclude/>
public override string ToString() {
return Value.ToString();
}
}
. . .

According to the Exif specification, properties may contain arrays of values. Our conversion tool must consequently have the following signature :

Code Copy
public static Array FromPropertyItem(PropertyItem propertyItem) {}

The conversion code is quite simple (a switch... case construct branching on different code depending on the data type).
When converting raw data into integers, just take care that Exif properties are stored as big endian values.

Code Copy HideScrollFull
#region References

using System;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Text;

#endregion

namespace
ExifNative {
/// <summary>
/// Summary description for ExifConvert.
/// </summary>
public sealed class ExifConvert {
private ExifConvert() {}

/// <summary>
/// Converts a property item to an array of objects.
/// </summary>
/// <param name="propertyItem">The property item to convert.</param>
/// <returns>An array of <see cref="object"/> items.</returns>
public static Array FromPropertyItem(PropertyItem propertyItem) {
ExifPropertyType type = (ExifPropertyType) propertyItem.Type;

switch (type) {
case ExifPropertyType.Raw:
// The value represents raw data (a single byte[] value)
return new byte[][] {propertyItem.Value};

case ExifPropertyType.Ascii:
// The value represents an array of strings separated by \0 characters
string stringValue = Encoding.ASCII.GetString(propertyItem.Value, 0, propertyItem.Len - 1);
return stringValue.Split('\0');

case ExifPropertyType.Byte:
// The value represents an array of bytes
return propertyItem.Value;

case ExifPropertyType.UInt16:
// The value represents an array of unsigned 16-bit integers.
int ushortCount = propertyItem.Len/ushortSize;

ushort[] ushortResult = new ushort[ushortCount];
for (int i = 0; i < ushortCount; i++)
ushortResult[i] = ReadUInt16(propertyItem.Value, i * ushortSize);
return ushortResult;

case ExifPropertyType.Int32:
// The value represents an array of signed 32-bit integers.
int intCount = propertyItem.Len/intSize;

int[] intResult = new int[intCount];
for (int i = 0; i < intCount; i++)
intResult[i] = ReadInt32(propertyItem.Value, i * intSize);
return intResult;

case ExifPropertyType.UInt32:
// The value represents an array of unsigned 32-bit integers.
int uintCount = propertyItem.Len/uintSize;

uint[] uintResult = new uint[uintCount];
for (int i = 0; i < uintCount; i++)
uintResult[i] = ReadUInt32(propertyItem.Value, i * uintSize);
return uintResult;

case ExifPropertyType.Rational:
// The value represents an array of signed rational numbers
// Numerator is an Int32 value, denominator a UInt32 value.
int rationalCount = propertyItem.Len/rationalSize;

Rational[] rationalResult = new Rational[rationalCount];
for (int i = 0; i < rationalCount; i++)
rationalResult[i] = new Rational(
ReadInt32(propertyItem.Value, i * rationalSize),
ReadInt32(propertyItem.Value, i * rationalSize + intSize));
return rationalResult;

case ExifPropertyType.URational:
// The value represents an array of signed rational numbers
// Numerator and denominator are UInt32 values.
int urationalCount = propertyItem.Len/rationalSize;

URational[] urationalResult = new URational[urationalCount];
for (int i = 0; i < urationalCount; i++)
urationalResult[i] = new URational(
ReadUInt32(propertyItem.Value, i * urationalSize),
ReadUInt32(propertyItem.Value, i * urationalSize + uintSize));
return urationalResult;

default:
return null;
}
}

#region Static Fields

private static readonly int ushortSize = Marshal.SizeOf(typeof (ushort));
private static readonly int intSize = Marshal.SizeOf(typeof (int));
private static readonly int uintSize = Marshal.SizeOf(typeof (uint));
private static readonly int rationalSize = 2 * Marshal.SizeOf(typeof (int));
private static readonly int urationalSize = 2 * Marshal.SizeOf(typeof (uint));

#endregion

#region
Private Helpers

private static ushort ReadUInt16(byte[] buffer, int offset) {
return (ushort) (
((ushort) buffer[offset] +
((ushort) buffer[offset + 1] << 8)));
}

private static int ReadInt32(byte[] buffer, int offset) {
return (int) (
((uint) buffer[offset] +
((uint) buffer[offset + 1] << 8) +
((uint) buffer[offset + 2] << 16) +
((int) buffer[offset + 3] << 24)));
}

private static uint ReadUInt32(byte[] buffer, int offset) {
return (uint) (
((uint) buffer[offset] +
((uint) buffer[offset + 1] << 8) +
((uint) buffer[offset + 2] << 16) +
((uint) buffer[offset + 3] << 24)));
}

#endregion
}
}
. . .

The following code is a sample console application that make use of the code above to load an image and display the content of Exif properties.

Code Copy
[STAThread]
private static void Main(string[] args) {
using(Image image = Image.FromFile(args[0])) {
Console.WriteLine("{0} : {1} properties", args[0], image.PropertyItems.Length);

foreach (PropertyItem propertyItem in image.PropertyItems) {
Array result = ExifConvert.FromPropertyItem(propertyItem);
Console.WriteLine("Property #{0}, type : {1}, {2} value(s)", propertyItem.Id, (ExifPropertyType)propertyItem.Type, result.Length);

foreach (object value in result)
Console.WriteLine("\t{0}", value);
Console.WriteLine();
}
}
}

posted on Tuesday, April 19, 2005 12:20 PM

Feedback

# science articles 3/15/2011 10:20 AM sadie

Very Good!!!

But, how can i create this empty jpg with an empty tag?

Or, is it possible to download it?

# re: Exif Properties in .Net - Part 3 : converting properties 9/29/2011 6:00 PM organic seo service

This site is excellent and so is how the subject matter was explained. I also like some of the comments too.Waiting for next post.

# bag 11/11/2011 7:24 AM Marc by Marc Jacobs Bags

As an influx of people, rather bare, better than the tasteless. <a href="http://www.marcjacobs-">http://www.marcjacobs-handbags.org/">Marc">http://www.marcjacobs-">http://www.marcjacobs-handbags.org/">Marc

Jacobs</a> designed the product, especially the main and sub-brand bag brand <a href="http://www.marcjacobs-">http://www.marcjacobs-

handbags.org/">Marc by Marc Jacobs Bags</a>, is a unique mix of taste. <a href="http://www.marcjacobs-">http://www.marcjacobs-

handbags.org/">Marc Jacobs Handbag</a> used almost mature female, are to be highly it. Young people's favorite

handbag comes <a href="http://www.marcjacobs-">http://www.marcjacobs-handbags.org/">Marc">http://www.marcjacobs-">http://www.marcjacobs-handbags.org/">Marc by Marc Jacobs Handbag</a>. As long as you are

stylish, with a focus on people, then you have to have them.

# drug forum 11/16/2011 5:50 PM drug forum

I was delighted to find this web site.I wanted to thank you for your time reading this wonderful! I really enjoyed every bit of it and I've marked to ensure that the blog post something new.

# re: Exif Properties in .Net - Part 3 : converting properties 11/17/2011 11:03 PM best seo company

If you need more traffic to your website check out the website in my name. It really helped me and i think it can help your website.

# underwear 11/24/2011 6:50 AM calvin klein 365

The main function of underwear is more conducive to live and work. For men is to live in the root and eggs stretched, so as not to walk or do something random shaking, affecting work and life. For women, the menstrual period comes in an easy to absorbent pads good things, to avoid the outflow of blood affect the life and work. Then choose a suitable underwear becomes very important. <a href="http://www.underwear-sale.org">Calvin Klein Underwear</a> can help you do so. <a href="http://www.underwear-sale.org/womens-calvin-klein-c-48.html">calvin klein steel</a> and <a href="http://www.underwear-sale.org/mens-underwear-calvin-klein-underwear-c-42_46.html">calvin klein 365</a> series is especially good. We have <a href="http://www.underwear-sale.org">underwear sale</a>. In addition to these, this site also <a href="http://www.underwear-sale.org/aussiebum-retro-swimwear-c-44.html">aussieBum Swimwear</a> and so on. Welcome to win your favor. Thank you!

# Birthday parties for kids in Miami-kids fairyland 11/28/2011 7:48 AM Birthday parties for kids in Miami


Hey its been really a very good and informative post to read on. I will keep these points in my mind from now onwards, hope will not commit mistakes
<a href="http://www.kidsfairyland.com/kidsparty.html">Birthday parties for kids in Miami</a>
<a href="http://www.kidsfairyland.com/">Kids birthday parties in Miami</a>

# seo 12/2/2011 5:44 PM buy lortab online

I was delighted to find this web site.I wanted to thank you for your time reading this wonderful! I really enjoyed every bit of it and I've marked to ensure that the blog post something new.

# maquinas de coser 12/30/2011 2:38 PM maquinas de coser

Really enjoy reading your well written articles. I think you spend numerous effort and time in posting the blog. I have bookmarked it and I am looking ahead to reading new articles. Keep up the good articles.

# re: Exif Properties in .Net - Part 3 : converting properties 1/11/2012 11:18 AM 传奇世界私服

http://zhongpu-nba.com/
http://www.zhongpu-caps.com/
http://www.9kkcs.com/
http://www.hl066.info/
http://www.2zxc.net/
http://t2062.com/

# buy hydrocodone 1/25/2012 8:20 PM buy hydrocodone

Sometimes we are very concerned about our health, do not understand what to do. It is very easy to make better health. the use of natural vitamin supplements. Vitamins function in many metabolic reactions that occur in foods consumed in the body, control of vitamins and energy metabolism of our body.

# louis vuitton sale 2/1/2012 3:33 AM louis vuitton sale

Bags of many different models, materials and colors at the
louis vuitton sale

outlet can be significant along with ample, nevertheless quite trendy, fantastic requirement.Here is a world of
louis vuitton outlet

where you can find all kinds of new style and fashion Louis Vuitton bags. We really want to lead the trend and let our customer in the pursuit of luxury and fashion, satisfied the needs of customers.

# coach factory outlet 2/1/2012 4:49 AM coach factory outlet

If you do not know design can be the most fashionable this fall, consider a glance on
coach factory outlet

! This summer, you have a wide range of options, because there are numerous designs, you can find from.
coach factory online

is actually a stylish Coach online store to sell perfect quality and discount Coach handbags, Coach bags, Coach wallets and Cheap Coach Purse.If you love Coach,you will like to get the best price on it.

# christian louboutin uk 2/1/2012 4:49 AM christian louboutin uk

If you have enough leisure time, you may go to the mall or go to the christian franchised store to have a good look at varieties of
christian louboutin uk

the diverse styles and rich colors of the purses with low cost will surely impress you a lot!You will always get surprised by the beautiful colors and perfect details of
christian louboutin

.So come on, do not hesitate.

# aion gold 2/1/2012 7:15 AM aion gold

Wow gold http://virgolds.com/
buy eve online http://virgolds.com/Eve-Online-Isk/
final fantasy xi gil http://virgolds.com/Final-Fantasy-XI-Gil/
aion gold http://virgolds.com/Aion-Gold/

# coach bags 2/1/2012 10:07 AM coach bags

coach bags

with fashion style and top quality succeed. In any occasions they are very suitable and appropriate for its precise and rich design.
coach outlet store

vision system is a visual enjoy, is a visual art. The particular design has been integrated function and the element of elegancy, then show you an exquisite and excellent product.

# coach outlet online 2/2/2012 1:45 AM coach outlet online

Becoming a regular member of
coach outlet online

, you can even buy wholesale purses, handbags, leather wallets at preferential prices. Why not have a try?
coach factory outlet

is famous for the discounts it offers. Latest coach purses and sunglasses can be purchased at discounted rates from this coach outlet store.
http://www.coachoutletonlinecoachdays.com

# coach outlet 2/2/2012 1:46 AM coach outle

coach outlet

sells products which are excellent in quality and reasonable in price. All customers can easily pick up their favorite Coach briefcase, wallets, shoes, hats, scarf, jewelry and sunglasses.If you need to acquire the focus, you need to sustain the
coach outlet store online

, which with stylish components that will immediately concoct you appreciably more attracting and outstanding.
http://www.coachoutletcoachstore.com

# chanel uk 2/2/2012 1:47 AM chanel uk

Swarovski's Crystal is due to their commitment to consistency, precision and quality standards, and to the automatic cutting machine invented by the founder,
chanel bags

enjoy high reputation all over the world. They are designed for hand, elbow and shoulder carry thanks to comfortable flat leather handles.
http://www.chanel-outlet.org.uk

# coach factory outlet 2/2/2012 2:43 AM coach factory outlet

That experts claim coach factory outlet shopping is in the changes they are available in, which can make it well suited for benefit from to be a'luggage'bag. There are different kinds of crossbody bags within marketplace nowadays. Even so it is not possible to beat the timeless design jointly with traditional elegance of the Bags at the coach factory outlet online.
http://www.coachfactoryoutletonlinedays.com

# coach outlet online 2/2/2012 2:43 AM coach outlet online

If you buy Coach items at the
coach outlet online

store, the goods will be sent out within 24 hours after confirming your payment and arrive to your door within 7 work days.
coach outlet

can provide the coach exactly the same is expected in a retail store. It can help you find bags of various colors, shapes and designs, which prove once again that the coach is actually a selection for the housekeeper.
http://www.coachoutletonlinecell.com

# louis vuitton uk 2/2/2012 2:44 AM louis vuitton uk

More and more people can afford louis vuitton uk, not to say they are on sale. Price is not equivalent with value,they own classical style, fine materials, elaborate technique. If you want to catch up to the latest vogue, having Louis Vuitton Handbags of the latest styles can absolutely satisfy you.Just visit LV outlet webpage and select the most suitable products for yourself.
http://www.louisvuitton-full.org.uk

# christian louboutin 2/2/2012 2:44 AM christian louboutin

This elegant and discreet pair of rhodium-plated button christian louboutin will add sparkle to your outfit. They are covered in clear crystal pave and reflect the light in magical ways. christian Madison Handbags and christian Poppy Bags are viewed among probably the most newsworthy among the particular christian louboutin uk so far.
http://www.christian-louboutinshoes.co.uk

# chanel uk 2/2/2012 2:55 AM chanel uk

chanel uk have own characteristic designs. The beautiful crystals have added the magical finishing touch to countless bridal gowns. Just get some for yourself. I hope that I have helped you realize the potential for a breathtaking theme on your wedding day.Incorporating chanel handbags and pearls into your decor is a very fun and easy way to create a classic and warm setting.

http://www.chanel-bags.org.uk

# coach outlet store 2/2/2012 2:55 AM coach outlet store

Coach Outlet Store sells goods that are constructed to meet the highest standards of quality and functionality.You can trust it 100 percent. Wholesale coach outlet are even provided for VIP members. Haven't got your own Coach yet? Why not come to coach outlet store online outlet.

http://www.coachoutletstoreonlinegood.com

# coach outlet online 2/2/2012 2:56 AM coach outlet online

I got to know it from my elder sister who owns enviable luxury Coach bags. Coach Outlet Online Store is established to be your home shopping paradise. Coach New Signature BackPack Black Beige is a useful backpack for outdoors activities. It's convenient that you can freely take along with for travel,climbing and go for school.In our coach outlet,there are many graceful styles of Coach backpack for you.

http://www.coachoutletonlinefull.com

# louis vuitton uk 2/2/2012 3:56 AM louis vuitton uk

This
louis vuitton uk

for sale belongs to the sounding just what are termed as Louis Vuitton vintage best sellers, many other products and services for the reason that range appearing companies.I am so confused that I don,t even know where to buy the
louis vuitton

Handbags. Because I can prefer to chose the fashionable design, favorable price, top service .
http://www.louis-vuittonukoutlets.org.uk

# louboutin uk 2/2/2012 4:14 AM louboutin uk

Come by for dinner soon and check out the wine list for yourself. We are always here to help with selection. Cheers for the successful of christian
louboutin uk

.The christian Signature Hobo is from the latest release of
christian louboutin uk

. Its crisp, scribble material, leather handle, perfectly complements the relaxed shape of this stylish pouch.
http://www.christianlouboutinuk-sale.co.uk

Title
 
Name
 
Url
Comments   
Protected by Clearscreen.SharpHIPEnter the code you see: