/// <summary>
        /// Will stock the thumbnail into exif directory if available.
        /// </summary>
        /// <param name="exifDirectory">where to stock the thumbnail</param>
        /// <param name="tiffHeaderOffset">the tiff lcHeader lcOffset value</param>
        private void StoreThumbnailBytes(AbstractDirectory exifDirectory, int tiffHeaderOffset)
        {
            if (!exifDirectory.ContainsTag(ExifDirectory.TAG_COMPRESSION))
            {
                return;
            }

            if (!exifDirectory.ContainsTag(ExifDirectory.TAG_THUMBNAIL_LENGTH) ||
                !exifDirectory.ContainsTag(ExifDirectory.TAG_THUMBNAIL_OFFSET))
            {
                return;
            }
            try
            {
                int offset = exifDirectory.GetInt(ExifDirectory.TAG_THUMBNAIL_OFFSET);
                int length = exifDirectory.GetInt(ExifDirectory.TAG_THUMBNAIL_LENGTH);
                byte[] result = new byte[length];
                for (int i = 0; i < result.Length; i++)
                {
                    result[i] = base.data[tiffHeaderOffset + offset + i];
                }
                exifDirectory.SetObject(ExifDirectory.TAG_THUMBNAIL_DATA, result);
            }
            catch (Exception e)
            {
                exifDirectory.HasError = true;
                Trace.TraceError("Unable to extract thumbnail: " + e.Message);
            }
        }
 /// <summary>
 /// This method serves as marsheller of objects for dataset. 
 /// It converts from IPTC octets to relevant java object.
 /// </summary>
 /// <param name="aDirectory">the directory</param>
 /// <param name="aDirectoryType">the directory type</param>
 /// <param name="aTagType">the tag type</param>
 /// <param name="anOffset">the lcOffset</param>
 /// <param name="aTagByteCount">the tag byte count</param>
 private void ProcessTag(
     AbstractDirectory aDirectory,
     int aDirectoryType,
     int aTagType,
     int anOffset,
     int aTagByteCount)
 {
     int tagIdentifier = aTagType | (aDirectoryType << 8);
     switch (tagIdentifier)
     {
         case IptcDirectory.TAG_RECORD_VERSION:
             // short
             short shortValue = (short)((base.data[anOffset] << 8) | base.data[anOffset + 1]);
             aDirectory.SetObject(tagIdentifier, shortValue);
             return;
         case IptcDirectory.TAG_URGENCY:
             // byte
             aDirectory.SetObject(tagIdentifier, base.data[anOffset]);
             return;
         case IptcDirectory.TAG_RELEASE_DATE:
         case IptcDirectory.TAG_DATE_CREATED:
             // Date object
             if (aTagByteCount >= 8)
             {
                 string dateStr = Utils.Decode(base.data, anOffset, aTagByteCount, false);
                 try
                 {
                     int year = Convert.ToInt32(dateStr.Substring(0, 4));
                     int month = Convert.ToInt32(dateStr.Substring(4, 2)); //No -1 here;
                     int day = Convert.ToInt32(dateStr.Substring(6, 2));
                     DateTime date = new DateTime(year, month, day);
                     aDirectory.SetObject(tagIdentifier, date);
                     return;
                 }
                 catch (Exception)
                 {
                     // fall through and we'll store whatever was there as a String
                 }
             }
             break; // Added for .Net compiler
         //case IptcDirectory.TAG_RELEASE_TIME:
         //case IptcDirectory.TAG_TIME_CREATED: 
     }
     // If no special handling by now, treat it as a string
     string str = null;
     if (aTagByteCount < 1)
     {
         str = "";
     }
     else
     {
         str = Utils.Decode(base.data, anOffset, aTagByteCount, false);
     }
     if (aDirectory.ContainsTag(tagIdentifier))
     {
         string[] oldStrings;
         string[] newStrings;
         try
         {
             oldStrings = aDirectory.GetStringArray(tagIdentifier);
         }
         catch (MetadataException)
         {
             oldStrings = null;
         }
         if (oldStrings == null)
         {
             newStrings = new String[1];
         }
         else
         {
             newStrings = new string[oldStrings.Length + 1];
             for (int i = 0; i < oldStrings.Length; i++)
             {
                 newStrings[i] = oldStrings[i];
             }
         }
         newStrings[newStrings.Length - 1] = str;
         aDirectory.SetObject(tagIdentifier, newStrings);
     }
     else
     {
         aDirectory.SetObject(tagIdentifier, str);
     }
 }
        /// <summary>
        /// Processes tag
        /// </summary>
        /// <param name="directory">the directory</param>
        /// <param name="aTagType">the tag type</param>
        /// <param name="tagValueOffset">the lcOffset value</param>
        /// <param name="componentCount">the component count</param>
        /// <param name="formatCode">the format code</param>
        private void ProcessTag(
            AbstractDirectory directory,
            int tagType,
            int tagValueOffset,
            int componentCount,
            int formatCode)
        {
            // Directory simply stores raw values
            // The display side uses a Descriptor class per directory to turn the raw values into 'pretty' descriptions
            switch (formatCode)
            {
                case FMT_UNDEFINED:
                    Debug.Write("Found a tag made of bytes");
                    // this includes exif user comments
                    byte[] tagBytes = new byte[componentCount];
                    int byteCount = componentCount * BYTES_PER_FORMAT[formatCode];
                    for (int i = 0; i < byteCount; i++)
                    {
                        tagBytes[i] = base.data[tagValueOffset + i];
                    }
                    directory.SetObject(tagType, tagBytes);
                    break;
                case FMT_STRING:
                    Debug.Write("Found a tag made of string");
                    string lcStr = null;
                    if (tagType == ExifDirectory.TAG_USER_COMMENT)
                    {
                        lcStr =
                            ReadCommentString(
                            tagValueOffset,
                            componentCount,
                            formatCode);
                    }
                    else
                    {
                        lcStr = ReadString(tagValueOffset, componentCount);
                    }
                    directory.SetObject(tagType, lcStr);
                    break;
                case FMT_SRATIONAL: //goto case FMT_URATIONAL;
                case FMT_URATIONAL:
                    if (componentCount == 1)
                    {
                        Debug.Write("Found a tag made of rational");
                        Rational rational = new Rational(Get32Bits(tagValueOffset), Get32Bits(tagValueOffset + 4));
                        directory.SetObject(tagType, rational);

                    }
                    else
                    {
                        Debug.Write("Found a tag made of rationals");
                        Rational[] rationals = new Rational[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            rationals[i] = new Rational(Get32Bits(tagValueOffset + (8 * i)), Get32Bits(tagValueOffset + 4 + (8 * i)));
                        }
                        directory.SetObject(tagType, rationals);

                    }

                    break;
                case FMT_SBYTE: //goto case FMT_BYTE;
                case FMT_BYTE:
                    if (componentCount == 1)
                    {
                        Debug.Write("Found a tag made of byte");
                        // this may need to be a byte, but I think casting to int is fine
                        int b = base.data[tagValueOffset];
                        directory.SetObject(tagType, b);
                    }
                    else
                    {
                        Debug.Write("Found a tag made of bytes but will use ints");
                        int[] bytes = new int[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            bytes[i] = base.data[tagValueOffset + i];
                        }
                        directory.SetIntArray(tagType, bytes);
                    }
                    break;
                case FMT_SINGLE: //goto case FMT_DOUBLE;
                case FMT_DOUBLE:
                    if (componentCount == 1)
                    {
                        Debug.Write("Found a tag made of double but will use int");
                        int i = base.data[tagValueOffset];
                        directory.SetObject(tagType, i);
                    }
                    else
                    {
                        Debug.Write("Found a tag made of doubles but will use ints");
                        int[] ints = new int[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            ints[i] = base.data[tagValueOffset + i];
                        }
                        directory.SetIntArray(tagType, ints);
                    }
                    break;
                case FMT_USHORT: //goto case FMT_SSHORT;
                case FMT_SSHORT:
                    if (componentCount == 1)
                    {
                        Debug.Write("Found a tag made of short but will use int");
                        int i = Get16Bits(tagValueOffset);
                        directory.SetObject(tagType, i);
                    }
                    else
                    {
                        Debug.Write("Found a tag made of shorts but will use ints");
                        int[] ints = new int[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            ints[i] = Get16Bits(tagValueOffset + (i * 2));
                        }
                        directory.SetIntArray(tagType, ints);
                    }
                    break;
                case FMT_SLONG: //goto case FMT_ULONG;
                case FMT_ULONG:
                    if (componentCount == 1)
                    {
                        Debug.Write("Found a tag made of long but will use int");
                        int i = Get32Bits(tagValueOffset);
                        directory.SetObject(tagType, i);
                    }
                    else
                    {
                        Debug.Write("Found a tag made of longs but will use ints");
                        int[] ints = new int[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            ints[i] = Get32Bits(tagValueOffset + (i * 4));
                        }
                        directory.SetIntArray(tagType, ints);
                    }
                    break;
                default:
                    Trace.TraceWarning("Unknown format code " + formatCode + " for tag " + tagType);
                    break;
            }
        }