Esempio n. 1
0
        /// <summary>
        /// Reads a custom directory from the arbitrary offset within file/stream.
        /// </summary>
        /// <param name="offset">The directory offset.</param>
        /// <param name="info">The array of <see cref="TiffFieldInfo"/> objects to merge to
        /// existing field information.</param>
        /// <param name="count">The number of items to use from
        /// the <paramref name="info"/> array.</param>
        /// <returns><c>true</c> if a custom directory was read successfully;
        /// otherwise, <c>false</c></returns>
        public bool ReadCustomDirectory(long offset, TiffFieldInfo[] info, int count)
        {
            const string module = "ReadCustomDirectory";

            setupFieldInfo(info, count);

            uint dummyNextDirOff;
            TiffDirEntry[] dir;
            short dircount = fetchDirectory((uint)offset, out dir, out dummyNextDirOff);
            if (dircount == 0)
            {
                ErrorExt(this, m_clientdata, module,
                    "{0}: Failed to read custom directory at offset {1}", m_name, offset);
                return false;
            }

            FreeDirectory();
            m_dir = new TiffDirectory();

            int fix = 0;
            for (short i = 0; i < dircount; i++)
            {
                if ((m_flags & TiffFlags.Swab) == TiffFlags.Swab)
                {
                    short temp = (short)dir[i].tdir_tag;
                    SwabShort(ref temp);
                    dir[i].tdir_tag = (TiffTag)(ushort)temp;

                    temp = (short)dir[i].tdir_type;
                    SwabShort(ref temp);
                    dir[i].tdir_type = (TiffType)temp;

                    SwabLong(ref dir[i].tdir_count);
                    SwabUInt(ref dir[i].tdir_offset);
                }

                if (fix >= m_nfields || dir[i].tdir_tag == TiffTag.Ignore)
                    continue;

                while (fix < m_nfields && m_fieldinfo[fix].Tag < dir[i].tdir_tag)
                    fix++;

                if (fix >= m_nfields || m_fieldinfo[fix].Tag != dir[i].tdir_tag)
                {
                    WarningExt(this, m_clientdata, module,
                        "{0}: unknown field with tag {1} (0x{2:x}) encountered",
                        m_name, (ushort)dir[i].tdir_tag, (ushort)dir[i].tdir_tag);

                    TiffFieldInfo[] arr = new TiffFieldInfo[1];
                    arr[0] = createAnonFieldInfo(dir[i].tdir_tag, dir[i].tdir_type);
                    MergeFieldInfo(arr, 1);

                    fix = 0;
                    while (fix < m_nfields && m_fieldinfo[fix].Tag < dir[i].tdir_tag)
                        fix++;
                }

                // null out old tags that we ignore.
                if (m_fieldinfo[fix].Bit == FieldBit.Ignore)
                {
                    dir[i].tdir_tag = TiffTag.Ignore;
                    continue;
                }

                // Check data type.
                TiffFieldInfo fip = m_fieldinfo[fix];
                while (dir[i].tdir_type != fip.Type && fix < m_nfields)
                {
                    if (fip.Type == TiffType.Any)
                    {
                        // wildcard
                        break;
                    }

                    fip = m_fieldinfo[++fix];
                    if (fix >= m_nfields || fip.Tag != dir[i].tdir_tag)
                    {
                        WarningExt(this, m_clientdata, module,
                            "{0}: wrong data type {1} for \"{2}\"; tag ignored",
                            m_name, dir[i].tdir_type, m_fieldinfo[fix - 1].Name);

                        dir[i].tdir_tag = TiffTag.Ignore;
                        continue;
                    }
                }

                // Check count if known in advance.
                if (fip.ReadCount != TiffFieldInfo.Variable &&
                    fip.ReadCount != TiffFieldInfo.Variable2)
                {
                    int expected = fip.ReadCount;
                    if (fip.ReadCount == TiffFieldInfo.Spp)
                        expected = m_dir.td_samplesperpixel;

                    if (!checkDirCount(dir[i], expected))
                    {
                        dir[i].tdir_tag = TiffTag.Ignore;
                        continue;
                    }
                }

                // EXIF tags which need to be specifically processed.
                switch (dir[i].tdir_tag)
                {
                    case TiffTag.EXIF_SUBJECTDISTANCE:
                        fetchSubjectDistance(dir[i]);
                        break;
                    default:
                        fetchNormalTag(dir[i]);
                        break;
                }
            }

            return true;
        }
Esempio n. 2
0
        /// <summary>
        /// Releases storage associated with current directory.
        /// </summary>
        public void FreeDirectory()
        {
            if (m_dir != null)
            {
                clearFieldBit(FieldBit.YCbCrSubsampling);
                clearFieldBit(FieldBit.YCbCrPositioning);

                m_dir = null;
            }
        }
Esempio n. 3
0
 private static void defaultRefBlackWhite(TiffDirectory td)
 {
     td.td_refblackwhite = new float[6];
     if (td.td_photometric == Photometric.YCBCR)
     {
         // YCbCr (Class Y) images must have the ReferenceBlackWhite tag set. Fix the
         // broken images, which lacks that tag.
         td.td_refblackwhite[0] = 0.0F;
         td.td_refblackwhite[1] = td.td_refblackwhite[3] = td.td_refblackwhite[5] = 255.0F;
         td.td_refblackwhite[2] = td.td_refblackwhite[4] = 128.0F;
     }
     else
     {
         // Assume RGB (Class R)
         for (int i = 0; i < 3; i++)
         {
             td.td_refblackwhite[2 * i + 0] = 0;
             td.td_refblackwhite[2 * i + 1] = (float)((1L << td.td_bitspersample) - 1L);
         }
     }
 }
Esempio n. 4
0
        private static bool defaultTransferFunction(TiffDirectory td)
        {
            short[][] tf = td.td_transferfunction;
            tf[0] = null;
            tf[1] = null;
            tf[2] = null;

            if (td.td_bitspersample >= sizeof(int) * 8 - 2)
                return false;

            int n = 1 << td.td_bitspersample;
            tf[0] = new short[n];
            tf[0][0] = 0;
            for (int i = 1; i < n; i++)
            {
                double t = (double)i / ((double)n - 1.0);
                tf[0][i] = (short)Math.Floor(65535.0 * Math.Pow(t, 2.2) + 0.5);
            }

            if (td.td_samplesperpixel - td.td_extrasamples > 1)
            {
                tf[1] = new short[n];
                Buffer.BlockCopy(tf[0], 0, tf[1], 0, tf[0].Length * sizeof(short));

                tf[2] = new short[n];
                Buffer.BlockCopy(tf[0], 0, tf[2], 0, tf[0].Length * sizeof(short));
            }

            return true;
        }
Esempio n. 5
0
        /*
        * Setup a default directory structure.
        */
        private void setupDefaultDirectory()
        {
            int tiffFieldInfoCount;
            TiffFieldInfo[] tiffFieldInfo = getFieldInfo(out tiffFieldInfoCount);
            setupFieldInfo(tiffFieldInfo, tiffFieldInfoCount);

            m_dir = new TiffDirectory();
            m_postDecodeMethod = PostDecodeMethodType.pdmNone;
            m_foundfield = null;

            m_tagmethods = m_defaultTagMethods;

            /*
             *  Give client code a chance to install their own
             *  tag extensions & methods, prior to compression overloads.
             */
            if (m_extender != null)
                m_extender(this);

            SetField(TiffTag.Compression, Compression.None);

            /*
             * NB: The directory is marked dirty as a result of setting
             * up the default compression scheme.  However, this really
             * isn't correct -- we want DirtyDirect to be set only
             * if the user does something.  We could just do the setup
             * by hand, but it seems better to use the normal mechanism
             * (i.e. SetField).
             */
            m_flags &= ~TiffFlags.DirtyDirect;

            /*
             * we clear the IsTiled flag when setting up a new directory.
             * Should we also be clearing stuff like InSubIFD?
             */
            m_flags &= ~TiffFlags.IsTiled;

            /*
             * Clear other directory-specific fields.
             */
            m_tilesize = -1;
            m_scanlinesize = -1;
        }
Esempio n. 6
0
        /// <summary>
        /// Install extra samples information.
        /// </summary>
        private static bool setExtraSamples(TiffDirectory td, ref int v, FieldValue[] ap)
        {
            // XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below
            const short EXTRASAMPLE_COREL_UNASSALPHA = 999;

            v = ap[0].ToInt();
            if (v > td.td_samplesperpixel)
                return false;

            byte[] va = ap[1].ToByteArray();
            if (v > 0 && va == null)
            {
                // typically missing param
                return false;
            }

            for (int i = 0; i < v; i++)
            {
                if ((ExtraSample)va[i] > ExtraSample.UnAssociatedAlpha)
                {
                    // XXX: Corel Draw is known to produce incorrect 
                    // ExtraSamples tags which must be patched here if we
                    // want to be able to open some of the damaged TIFF files: 
                    if (i < v - 1)
                    {
                        short s = BitConverter.ToInt16(va, i);
                        if (s == EXTRASAMPLE_COREL_UNASSALPHA)
                            va[i] = (byte)ExtraSample.UnAssociatedAlpha;
                    }
                    else
                        return false;
                }
            }

            td.td_extrasamples = (short)v;
            td.td_sampleinfo = new ExtraSample[td.td_extrasamples];
            for (int i = 0; i < td.td_extrasamples; i++)
                td.td_sampleinfo[i] = (ExtraSample)va[i];

            return true;
        }
Esempio n. 7
0
 private bool byteCountLooksBad(TiffDirectory td)
 {
     /* 
      * Assume we have wrong StripByteCount value (in case of single strip) in
      * following cases:
      *   - it is equal to zero along with StripOffset;
      *   - it is larger than file itself (in case of uncompressed image);
      *   - it is smaller than the size of the bytes per row multiplied on the
      *     number of rows.  The last case should not be checked in the case of
      *     writing new image, because we may do not know the exact strip size
      *     until the whole image will be written and directory dumped out.
      */
     return
     (
         (td.td_stripbytecount[0] == 0 && td.td_stripoffset[0] != 0) ||
         (td.td_compression == Compression.None && td.td_stripbytecount[0] > getFileSize() - td.td_stripoffset[0]) ||
         (m_mode == O_RDONLY && td.td_compression == Compression.None && td.td_stripbytecount[0] < ScanlineSize() * td.td_imagelength)
     );
 }