Example #1
0
        private static void readDirEntry(TiffDirEntry[] dir, ulong dircount, byte[] bytes, int offset, bool isBigTiff)
        {
            int pos = offset;

            for (ulong i = 0; i < dircount; i++)
            {
                TiffDirEntry entry = new TiffDirEntry();
                entry.tdir_tag  = (TiffTag)(ushort)readShort(bytes, pos);
                pos            += sizeof(short);
                entry.tdir_type = (TiffType)readShort(bytes, pos);
                pos            += sizeof(short);
                if (isBigTiff)
                {
                    entry.tdir_count = (int)readULong(bytes, pos);
                    pos += sizeof(ulong);
                    entry.tdir_offset = readULong(bytes, pos);
                    pos += sizeof(ulong);
                }
                else
                {
                    entry.tdir_count = (int)readInt(bytes, pos);
                    pos += sizeof(int);
                    entry.tdir_offset = (ulong)(uint)readInt(bytes, pos);
                    pos += sizeof(int);
                }
                dir[i] = entry;
            }
        }
Example #2
0
        /// <summary>
        /// Fetches an array of FLOAT values.
        /// </summary>
        private bool fetchFloatArray(TiffDirEntry dir, float[] v)
        {
            if (dir.tdir_count == 1)
            {
                v[0] = BitConverter.ToSingle(BitConverter.GetBytes(dir.tdir_offset), 0);
                return(true);
            }

            int w  = DataWidth(dir.tdir_type);
            int cc = dir.tdir_count * w;

            byte[] b    = new byte [cc];
            int    read = fetchData(dir, b);

            if (read != 0)
            {
                int byteOffset = 0;
                for (int i = 0; i < read / 4; i++)
                {
                    v[i]        = BitConverter.ToSingle(b, byteOffset);
                    byteOffset += 4;
                }
            }

            return(read != 0);
        }
Example #3
0
 /// <summary>
 /// Setups a SHORT directory entry
 /// </summary>
 private void setupShort(TiffTag tag, ref TiffDirEntry dir, short v)
 {
     dir.tdir_tag    = tag;
     dir.tdir_count  = 1;
     dir.tdir_type   = TiffType.SHORT;
     dir.tdir_offset = insertData(TiffType.SHORT, v);
 }
Example #4
0
        /*
         * Fetch and set the SubjectDistance EXIF tag.
         */
        private bool fetchSubjectDistance(TiffDirEntry dir)
        {
            if (dir.tdir_count != 1 || dir.tdir_type != TiffType.RATIONAL)
            {
                Tiff.WarningExt(this, m_clientdata, m_name,
                                "incorrect count or type for SubjectDistance, tag ignored");

                return(false);
            }

            bool ok = false;

            byte[] b    = new byte[2 * sizeof(int)];
            int    read = fetchData(dir, b);

            if (read != 0)
            {
                int[] l = new int[2];
                l[0] = readInt(b, 0);
                l[1] = readInt(b, sizeof(int));

                float v;
                if (cvtRational(dir, l[0], l[1], out v))
                {
                    /*
                     * XXX: Numerator -1 means that we have infinite
                     * distance. Indicate that with a negative floating point
                     * SubjectDistance value.
                     */
                    ok = SetField(dir.tdir_tag, (l[0] != -1) ? v : -v);
                }
            }

            return(ok);
        }
Example #5
0
        /// <summary>
        /// Setup a directory entry of an array of SHORT or SSHORT and write
        /// the associated indirect values.
        /// </summary>
        private bool writeShortArray(ref TiffDirEntry dir, short[] v)
        {
            if (dir.tdir_count <= 2)
            {
                if (m_header.tiff_magic == TIFF_BIGENDIAN)
                {
                    dir.tdir_offset = (uint)(v[0] << 16);
                    if (dir.tdir_count == 2)
                    {
                        dir.tdir_offset |= (uint)(v[1] & 0xffff);
                    }
                }
                else
                {
                    dir.tdir_offset = (uint)(v[0] & 0xffff);
                    if (dir.tdir_count == 2)
                    {
                        dir.tdir_offset |= (uint)(v[1] << 16);
                    }
                }

                return(true);
            }

            return(writeData(ref dir, v, dir.tdir_count));
        }
Example #6
0
        private bool writeTransferFunction(ref TiffDirEntry dir)
        {
            // Check if the table can be written as a single column, or if it
            // must be written as 3 columns. Note that we write a 3-column tag
            // if there are 2 samples/pixel and a single column of data
            // won't suffice--hmm.
            int  u       = m_dir.td_samplesperpixel - m_dir.td_extrasamples;
            int  ncols   = 1;
            bool reCheck = false;
            int  n       = 1 << m_dir.td_bitspersample;

            if (u < 0 || u > 2)
            {
                if (Compare(m_dir.td_transferfunction[0], m_dir.td_transferfunction[2], n) != 0)
                {
                    ncols = 3;
                }
                else
                {
                    reCheck = true;
                }
            }

            if (u == 2 || reCheck)
            {
                if (Compare(m_dir.td_transferfunction[0], m_dir.td_transferfunction[1], n) != 0)
                {
                    ncols = 3;
                }
            }

            return(writeShortTable(TiffTag.TRANSFERFUNCTION, ref dir, ncols, m_dir.td_transferfunction));
        }
Example #7
0
        /// <summary>
        /// Fetch an array of RATIONAL or SRATIONAL values.
        /// </summary>
        private bool fetchRationalArray(TiffDirEntry dir, float[] v)
        {
            Debug.Assert(sizeof(float) == sizeof(int));

            bool ok = false;

            byte[] l = new byte [dir.tdir_count * DataWidth(dir.tdir_type)];
            if (fetchData(dir, l) != 0)
            {
                int   offset = 0;
                int[] pair   = new int[2];
                for (int i = 0; i < dir.tdir_count; i++)
                {
                    pair[0] = readInt(l, offset);
                    offset += sizeof(int);
                    pair[1] = readInt(l, offset);
                    offset += sizeof(int);

                    ok = cvtRational(dir, pair[0], pair[1], out v[i]);
                    if (!ok)
                    {
                        break;
                    }
                }
            }

            return(ok);
        }
Example #8
0
        /*
         * Fetch a pair of SHORT or BYTE values. Some tags may have either BYTE
         * or SHORT type and this function works with both ones.
         */
        private bool fetchShortPair(TiffDirEntry dir)
        {
            /*
             * Prevent overflowing arrays below by performing a sanity
             * check on tdir_count, this should never be greater than two.
             */
            if (dir.tdir_count > 2)
            {
                WarningExt(this, m_clientdata, m_name,
                           "unexpected count for field \"{0}\", {1}, expected 2; ignored",
                           FieldWithTag(dir.tdir_tag).Name, dir.tdir_count);
                return(false);
            }

            switch (dir.tdir_type)
            {
            case TiffType.BYTE:
            case TiffType.SBYTE:
                byte[] bytes = new byte[4];
                return(fetchByteArray(dir, bytes) && SetField(dir.tdir_tag, bytes[0], bytes[1]));

            case TiffType.SHORT:
            case TiffType.SSHORT:
                short[] shorts = new short[2];
                return(fetchShortArray(dir, shorts) && SetField(dir.tdir_tag, shorts[0], shorts[1]));
            }

            return(false);
        }
Example #9
0
 private bool writeInkNames(ref TiffDirEntry dir)
 {
     dir.tdir_tag  = TiffTag.INKNAMES;
     dir.tdir_type = TiffType.ASCII;
     byte[] bytes = Latin1Encoding.GetBytes(m_dir.td_inknames);
     dir.tdir_count = bytes.Length;
     return(writeByteArray(ref dir, bytes));
 }
Example #10
0
        /// <summary>
        /// Fetches an array of BYTE or SBYTE values.
        /// </summary>
        private bool fetchByteArray(TiffDirEntry dir, byte[] v)
        {
            if (dir.tdir_count <= 4)
            {
                // Extract data from offset field.
                int count = dir.tdir_count;

                if (m_header.tiff_magic == TIFF_BIGENDIAN)
                {
                    if (count == 4)
                    {
                        v[3] = (byte)(dir.tdir_offset & 0xff);
                    }

                    if (count >= 3)
                    {
                        v[2] = (byte)((dir.tdir_offset >> 8) & 0xff);
                    }

                    if (count >= 2)
                    {
                        v[1] = (byte)((dir.tdir_offset >> 16) & 0xff);
                    }

                    if (count >= 1)
                    {
                        v[0] = (byte)(dir.tdir_offset >> 24);
                    }
                }
                else
                {
                    if (count == 4)
                    {
                        v[3] = (byte)(dir.tdir_offset >> 24);
                    }

                    if (count >= 3)
                    {
                        v[2] = (byte)((dir.tdir_offset >> 16) & 0xff);
                    }

                    if (count >= 2)
                    {
                        v[1] = (byte)((dir.tdir_offset >> 8) & 0xff);
                    }

                    if (count >= 1)
                    {
                        v[0] = (byte)(dir.tdir_offset & 0xff);
                    }
                }

                return(true);
            }

            return(fetchData(dir, v) != 0);
        }
Example #11
0
        /// <summary>
        /// Fetches a contiguous directory item.
        /// </summary>
        private int fetchData(TiffDirEntry dir, byte[] buffer)
        {
            int width = DataWidth(dir.tdir_type);
            int count = (int)dir.tdir_count * width;

            // Check for overflow.
            if (dir.tdir_count == 0 || width == 0 || (count / width) != dir.tdir_count)
            {
                fetchFailed(dir);
            }

            if (!seekOK(dir.tdir_offset))
            {
                fetchFailed(dir);
            }

            if (!readOK(buffer, count))
            {
                fetchFailed(dir);
            }

            if ((m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                switch (dir.tdir_type)
                {
                case TiffType.SHORT:
                case TiffType.SSHORT:
                    short[] s = ByteArrayToShorts(buffer, 0, count);
                    SwabArrayOfShort(s, dir.tdir_count);
                    ShortsToByteArray(s, 0, dir.tdir_count, buffer, 0);
                    break;

                case TiffType.LONG:
                case TiffType.SLONG:
                case TiffType.FLOAT:
                case TiffType.IFD:
                    int[] l = ByteArrayToInts(buffer, 0, count);
                    SwabArrayOfLong(l, dir.tdir_count);
                    IntsToByteArray(l, 0, dir.tdir_count, buffer, 0);
                    break;

                case TiffType.RATIONAL:
                case TiffType.SRATIONAL:
                    int[] r = ByteArrayToInts(buffer, 0, count);
                    SwabArrayOfLong(r, 2 * dir.tdir_count);
                    IntsToByteArray(r, 0, 2 * dir.tdir_count, buffer, 0);
                    break;

                case TiffType.DOUBLE:
                    swab64BitData(buffer, 0, count);
                    break;
                }
            }

            return(count);
        }
Example #12
0
        /// <summary>
        /// Setup a directory entry of an array of LONG or SLONG and write the
        /// associated indirect values.
        /// </summary>
        private bool writeLongArray(ref TiffDirEntry dir, int[] v)
        {
            if (dir.tdir_count == 1)
            {
                dir.tdir_offset = (uint)v[0];
                return(true);
            }

            return(writeData(ref dir, v, dir.tdir_count));
        }
Example #13
0
        private bool writeFloatArray(ref TiffDirEntry dir, float[] v)
        {
            if (dir.tdir_count == 1)
            {
                dir.tdir_offset = BitConverter.ToUInt32(BitConverter.GetBytes(v[0]), 0);
                return(true);
            }

            return(writeData(ref dir, v, dir.tdir_count));
        }
Example #14
0
        private bool writeData(ref TiffDirEntry dir, float[] cp, int cc)
        {
            int[] ints = new int[cc];
            for (int i = 0; i < cc; i++)
            {
                byte[] result = BitConverter.GetBytes(cp[i]);
                ints[i] = BitConverter.ToInt32(result, 0);
            }

            return(writeData(ref dir, ints, cc));
        }
Example #15
0
        /// <summary>
        /// Reads IFD structure from the specified offset.
        /// </summary>
        /// <returns>The number of fields in the directory or 0 if failed.</returns>
        private short fetchDirectory(uint diroff, out TiffDirEntry[] pdir, out uint nextdiroff)
        {
            const string module = "fetchDirectory";

            m_diroff   = diroff;
            nextdiroff = 0;

            short dircount;

            TiffDirEntry[] dir = null;
            pdir = null;

            if (!seekOK(m_diroff))
            {
                ErrorExt(this, m_clientdata, module,
                         "{0}: Seek error accessing TIFF directory", m_name);
                return(0);
            }

            if (!readShortOK(out dircount))
            {
                ErrorExt(this, m_clientdata, module,
                         "{0}: Can not read TIFF directory count", m_name);
                return(0);
            }

            if ((m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                SwabShort(ref dircount);
            }

            dir = new TiffDirEntry [dircount];
            if (!readDirEntryOk(dir, dircount))
            {
                ErrorExt(this, m_clientdata, module, "{0}: Can not read TIFF directory", m_name);
                return(0);
            }

            // Read offset to next directory for sequential scans.
            int temp;

            readIntOK(out temp);
            nextdiroff = (uint)temp;

            if ((m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                temp = (int)nextdiroff;
                SwabLong(ref temp);
                nextdiroff = (uint)temp;
            }

            pdir = dir;
            return(dircount);
        }
Example #16
0
        private int extractData(TiffDirEntry dir)
        {
            int type = (int)dir.tdir_type;

            if (m_header.tiff_magic == TIFF_BIGENDIAN)
            {
                return((int)((dir.tdir_offset >> m_typeshift[type]) & m_typemask[type]));
            }

            return((int)(dir.tdir_offset & m_typemask[type]));
        }
Example #17
0
        /*
         * Setup a pair of shorts that are returned by
         * value, rather than as a reference to an array.
         */
        private bool setupShortPair(TiffTag tag, ref TiffDirEntry dir)
        {
            short[]      v      = new short[2];
            FieldValue[] result = GetField(tag);
            v[0] = result[0].ToShort();
            v[1] = result[1].ToShort();

            dir.tdir_tag   = tag;
            dir.tdir_type  = TiffType.SHORT;
            dir.tdir_count = 2;
            return(writeShortArray(ref dir, v));
        }
Example #18
0
        private bool writeData(ref TiffDirEntry dir, double[] buffer, int count)
        {
            if ((m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                SwabArrayOfDouble(buffer, count);
            }

            byte[] bytes = new byte[count * sizeof(double)];
            Buffer.BlockCopy(buffer, 0, bytes, 0, bytes.Length);

            return(writeData(ref dir, bytes, count * sizeof(double)));
        }
Example #19
0
        private bool writeData(ref TiffDirEntry dir, short[] buffer, int count)
        {
            if ((m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                SwabArrayOfShort(buffer, count);
            }

            int byteCount = count * sizeof(short);

            byte[] bytes = new byte [byteCount];
            ShortsToByteArray(buffer, 0, count, bytes, 0);
            return(writeData(ref dir, bytes, byteCount));
        }
Example #20
0
        /// <summary>
        /// Fetches a set of offsets or lengths.
        /// </summary>
        /// <remarks>While this routine says "strips", in fact it's also used
        /// for tiles.</remarks>
        private bool fetchStripThing(TiffDirEntry dir, int nstrips, ref int[] lpp)
        {
            checkDirCount(dir, nstrips);

            // Allocate space for strip information.
            if (lpp == null)
            {
                lpp = new int [nstrips];
            }
            else
            {
                Array.Clear(lpp, 0, lpp.Length);
            }

            bool status = false;

            if (dir.tdir_type == TiffType.SHORT)
            {
                // Handle short -> int expansion.
                short[] dp = new short[dir.tdir_count];
                status = fetchShortArray(dir, dp);
                if (status)
                {
                    for (int i = 0; i < nstrips && i < dir.tdir_count; i++)
                    {
                        lpp[i] = dp[i];
                    }
                }
            }
            else if (nstrips != dir.tdir_count)
            {
                // Special case to correct length
                int[] dp = new int[dir.tdir_count];
                status = fetchLongArray(dir, dp);
                if (status)
                {
                    for (int i = 0; i < nstrips && i < dir.tdir_count; i++)
                    {
                        lpp[i] = dp[i];
                    }
                }
            }
            else
            {
                status = fetchLongArray(dir, lpp);
            }

            return(status);
        }
Example #21
0
        /// <summary>
        /// Advance to next tiff directory within file
        /// </summary>
        /// <param name="nextdir">Start location of next directory to try and advance to
        /// This will be updated with location of next directory if found</param>
        /// <param name="off">Offset of the end of the directory, right before the offset of the following directory is given</param>
        /// <param name="dircount">Numbers of directories in this IFD</param>
        /// <returns>True if next directory was found and nextdir was updated</returns>
        private bool advanceDirectory(ref ulong nextdir, out long off, out ulong dircount)
        {
            off      = 0;
            dircount = 0;

            const string module = "advanceDirectory";

            //Number of directories in this header
            if (!seekOK((long)nextdir) || !readDirCountOK(out dircount, m_header.tiff_version == TIFF_BIGTIFF_VERSION))
            {
                ErrorExt(this, m_clientdata, module, "{0}: Error fetching directory count", m_name);
                return(false);
            }

            if ((m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                SwabBigTiffValue(ref dircount, m_header.tiff_version == TIFF_BIGTIFF_VERSION, true);
            }

            //The location of the end of the directory
            off = (long)seekFile((long)dircount * TiffDirEntry.SizeInBytes(m_header.tiff_version == TIFF_BIGTIFF_VERSION), SeekOrigin.Current);

            if (m_header.tiff_version == TIFF_BIGTIFF_VERSION)
            {
                if (!readUlongOK(out nextdir))
                {
                    ErrorExt(this, m_clientdata, module, "{0}: Error fetching directory link", m_name);
                    return(false);
                }
            }
            else
            {
                //Get start location of next directory
                uint tempNextDir;
                if (!readUIntOK(out tempNextDir))
                {
                    ErrorExt(this, m_clientdata, module, "{0}: Error fetching directory link", m_name);
                    return(false);
                }
                nextdir = tempNextDir;
            }

            if ((m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                SwabBigTiffValue(ref nextdir, m_header.tiff_version == TIFF_BIGTIFF_VERSION, false);
            }

            return(true);
        }
Example #22
0
 /// <summary>
 /// Setups a directory entry with either a SHORT or LONG type
 /// according to the value.
 /// </summary>
 private void setupShortLong(TiffTag tag, ref TiffDirEntry dir, int v)
 {
     dir.tdir_tag   = tag;
     dir.tdir_count = 1;
     if (v > 0xffffL)
     {
         dir.tdir_type   = TiffType.LONG;
         dir.tdir_offset = (uint)v;
     }
     else
     {
         dir.tdir_type   = TiffType.SHORT;
         dir.tdir_offset = insertData(TiffType.SHORT, v);
     }
 }
Example #23
0
        private bool writeRational(TiffType type, TiffTag tag, ref TiffDirEntry dir, float v)
        {
            dir.tdir_tag   = tag;
            dir.tdir_type  = type;
            dir.tdir_count = 1;

            float[] a = new float[1];
            a[0] = v;
            if (!writeRationalArray(ref dir, a))
            {
                return(false);
            }

            return(true);
        }
Example #24
0
        /// <summary>
        /// Writes a contiguous directory item.
        /// </summary>
        private bool writeData(ref TiffDirEntry dir, byte[] buffer, int count)
        {
            dir.tdir_offset = m_dataoff;
            count           = (int)dir.tdir_count * DataWidth(dir.tdir_type);
            if (seekOK(dir.tdir_offset) && writeOK(buffer, 0, count))
            {
                m_dataoff += (uint)((count + 1) & ~1);
                return(true);
            }

            ErrorExt(this, m_clientdata, m_name,
                     "Error writing data for field \"{0}\"",
                     FieldWithTag(dir.tdir_tag).Name);
            return(false);
        }
Example #25
0
        private bool writeData(ref TiffDirEntry dir, int[] cp, int cc)
        {
            if ((m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                SwabArrayOfLong(cp, cc);
            }

            int byteCount = cc * sizeof(int);

            byte[] bytes = new byte [byteCount];
            IntsToByteArray(cp, 0, cc, bytes, 0);
            bool res = writeData(ref dir, bytes, byteCount);

            return(res);
        }
Example #26
0
        /*
         * Setup a directory entry that references a samples/pixel array of ``type''
         * values and (potentially) write the associated indirect values.  The source
         * data from GetField() for the specified tag must be returned as double.
         */
        private bool writePerSampleAnys(TiffType type, TiffTag tag, ref TiffDirEntry dir)
        {
            double[] w = new double [m_dir.td_samplesperpixel];

            FieldValue[] result = GetField(tag);
            double       v      = result[0].ToDouble();

            for (short i = 0; i < m_dir.td_samplesperpixel; i++)
            {
                w[i] = v;
            }

            bool status = writeAnyArray(type, tag, ref dir, m_dir.td_samplesperpixel, w);

            return(status);
        }
Example #27
0
 /*
  * Convert numerator+denominator to float.
  */
 private bool cvtRational(TiffDirEntry dir, int num, int denom, out float rv)
 {
     if (denom == 0)
     {
         ErrorExt(this, m_clientdata, m_name,
                  "{0}: Rational with zero denominator (num = {1})",
                  FieldWithTag(dir.tdir_tag).Name, num);
         rv = float.NaN;
         return(false);
     }
     else
     {
         rv = ((float)num / (float)denom);
         return(true);
     }
 }
Example #28
0
        /// <summary>
        /// Write/copy data associated with an ASCII or opaque tag value.
        /// </summary>
        private bool writeByteArray(ref TiffDirEntry dir, byte[] cp)
        {
            if (dir.tdir_count <= 4)
            {
                if (m_header.tiff_magic == TIFF_BIGENDIAN)
                {
                    dir.tdir_offset = (uint)(cp[0] << 24);
                    if (dir.tdir_count >= 2)
                    {
                        dir.tdir_offset |= (uint)(cp[1] << 16);
                    }

                    if (dir.tdir_count >= 3)
                    {
                        dir.tdir_offset |= (uint)(cp[2] << 8);
                    }

                    if (dir.tdir_count == 4)
                    {
                        dir.tdir_offset |= cp[3];
                    }
                }
                else
                {
                    dir.tdir_offset = cp[0];
                    if (dir.tdir_count >= 2)
                    {
                        dir.tdir_offset |= (uint)(cp[1] << 8);
                    }

                    if (dir.tdir_count >= 3)
                    {
                        dir.tdir_offset |= (uint)(cp[2] << 16);
                    }

                    if (dir.tdir_count == 4)
                    {
                        dir.tdir_offset |= (uint)(cp[3] << 24);
                    }
                }

                return(true);
            }

            return(writeData(ref dir, cp, dir.tdir_count));
        }
Example #29
0
        /// <summary>
        /// Fetches and sets the RefBlackWhite tag.
        /// </summary>
        private bool fetchRefBlackWhite(TiffDirEntry dir)
        {
            // some OJPEG images specify Reference BlackWhite as array of longs
            //
            // so, we'll try to read value as float array and check them
            // if read was successfull and there is at least one value greater
            // then 1.0 then ok, return value just read.
            //
            // if read failed or all values are less then or equal to 1.0 then
            // try once again but read as long array this time.

            if (dir.tdir_type == TiffType.RATIONAL)
            {
                bool res = fetchNormalTag(dir);
                if (res)
                {
                    for (int i = 0; i < m_dir.td_refblackwhite.Length; i++)
                    {
                        if (m_dir.td_refblackwhite[i] > 1)
                        {
                            return(true);
                        }
                    }
                }
            }

            // Handle LONG's for backward compatibility.
            dir.tdir_type = TiffType.LONG;
            int[] cp = new int [dir.tdir_count];
            bool  ok = fetchLongArray(dir, cp);

            dir.tdir_type = TiffType.RATIONAL;

            if (ok)
            {
                float[] fp = new float [dir.tdir_count];
                for (int i = 0; i < dir.tdir_count; i++)
                {
                    fp[i] = (float)cp[i];
                }

                ok = SetField(dir.tdir_tag, fp);
            }

            return(ok);
        }
Example #30
0
        /// <summary>
        /// Fetch an array of SHORT or SSHORT values.
        /// </summary>
        private bool fetchShortArray(TiffDirEntry dir, short[] v)
        {
            if (dir.tdir_count <= 2)
            {
                int count = dir.tdir_count;

                if (m_header.tiff_magic == TIFF_BIGENDIAN)
                {
                    if (count == 2)
                    {
                        v[1] = (short)(dir.tdir_offset & 0xffff);
                    }

                    if (count >= 1)
                    {
                        v[0] = (short)(dir.tdir_offset >> 16);
                    }
                }
                else
                {
                    if (count == 2)
                    {
                        v[1] = (short)(dir.tdir_offset >> 16);
                    }

                    if (count >= 1)
                    {
                        v[0] = (short)(dir.tdir_offset & 0xffff);
                    }
                }

                return(true);
            }

            int cc = dir.tdir_count * sizeof(short);

            byte[] b    = new byte[cc];
            int    read = fetchData(dir, b);

            if (read != 0)
            {
                Buffer.BlockCopy(b, 0, v, 0, b.Length);
            }

            return(read != 0);
        }