BitMiracle.LibTiff.Classic.Tiff.writeDirectory C# (CSharp) Method

writeDirectory() private method

Writes the contents of the current directory to the specified file.
This routine doesn't handle overwriting a directory with auxiliary storage that's been changed.
private writeDirectory ( bool done ) : bool
done bool
return bool
        private bool writeDirectory(bool done)
        {
            if (m_mode == O_RDONLY)
                return true;

            // Clear write state so that subsequent images with different
            // characteristics get the right buffers setup for them.
            if (done)
            {
                if ((m_flags & TiffFlags.POSTENCODE) == TiffFlags.POSTENCODE)
                {
                    m_flags &= ~TiffFlags.POSTENCODE;
                    if (!m_currentCodec.PostEncode())
                    {
                        ErrorExt(this, m_clientdata, m_name, "Error post-encoding before directory write");
                        return false;
                    }
                }

                // shutdown encoder
                m_currentCodec.Close();

                // Flush any data that might have been written by the
                // compression close+cleanup routines.
                if (m_rawcc > 0 && (m_flags & TiffFlags.BEENWRITING) == TiffFlags.BEENWRITING && !flushData1())
                {
                    ErrorExt(this, m_clientdata, m_name, "Error flushing data before directory write");
                    return false;
                }

                if ((m_flags & TiffFlags.MYBUFFER) == TiffFlags.MYBUFFER && m_rawdata != null)
                {
                    m_rawdata = null;
                    m_rawcc = 0;
                    m_rawdatasize = 0;
                }

                m_flags &= ~(TiffFlags.BEENWRITING | TiffFlags.BUFFERSETUP);
            }

            // Size the directory so that we can calculate offsets for the data
            // items that aren't kept in-place in each field.
            int nfields = 0;
            for (int b = 0; b <= FieldBit.Last; b++)
            {
                if (fieldSet(b) && b != FieldBit.Custom)
                    nfields += (b < FieldBit.SubFileType ? 2 : 1);
            }

            nfields += m_dir.td_customValueCount;
            int dirsize = nfields * TiffDirEntry.SizeInBytes;
            TiffDirEntry[] data = new TiffDirEntry [nfields];
            for (int i = 0; i < nfields; i++)
                data[i] = new TiffDirEntry();

            // Directory hasn't been placed yet, put it at the end of the file
            // and link it into the existing directory structure.
            if (m_diroff == 0 && !linkDirectory())
                return false;

            m_dataoff = m_diroff + sizeof(short) + (uint)dirsize + sizeof(int);
            if ((m_dataoff & 1) != 0)
                m_dataoff++;

            seekFile(m_dataoff, SeekOrigin.Begin);
            m_curdir++;
            int dir = 0;

            // Setup external form of directory entries and write data items.
            int[] fields = new int[FieldBit.SetLongs];
            Buffer.BlockCopy(m_dir.td_fieldsset, 0, fields, 0, FieldBit.SetLongs * sizeof(int));

            // Write out ExtraSamples tag only if extra samples are present in the data.
            if (fieldSet(fields, FieldBit.ExtraSamples) && m_dir.td_extrasamples == 0)
            {
                resetFieldBit(fields, FieldBit.ExtraSamples);
                nfields--;
                dirsize -= TiffDirEntry.SizeInBytes;
            } // XXX

            for (int fi = 0, nfi = m_nfields; nfi > 0; nfi--, fi++)
            {
                TiffFieldInfo fip = m_fieldinfo[fi];

                // For custom fields, we test to see if the custom field is set
                // or not.  For normal fields, we just use the fieldSet test.
                if (fip.Bit == FieldBit.Custom)
                {
                    bool is_set = false;
                    for (int ci = 0; ci < m_dir.td_customValueCount; ci++)
                        is_set |= (m_dir.td_customValues[ci].info == fip);

                    if (!is_set)
                        continue;
                }
                else if (!fieldSet(fields, fip.Bit))
                {
                    continue;
                }

                // Handle other fields.

                TiffTag tag = (TiffTag)FieldBit.Ignore;
                switch (fip.Bit)
                {
                    case FieldBit.StripOffsets:
                        // We use one field bit for both strip and tile
                        // offsets, and so must be careful in selecting
                        // the appropriate field descriptor (so that tags
                        // are written in sorted order).
                        tag = IsTiled() ? TiffTag.TILEOFFSETS : TiffTag.STRIPOFFSETS;
                        if (tag != fip.Tag)
                            continue;

                        data[dir].tdir_tag = tag;
                        data[dir].tdir_type = TiffType.LONG;
                        data[dir].tdir_count = m_dir.td_nstrips;
                        if (!writeLongArray(ref data[dir], m_dir.td_stripoffset))
                            return false;

                        break;
                    case FieldBit.StripByteCounts:
                        // We use one field bit for both strip and tile byte
                        // counts, and so must be careful in selecting the
                        // appropriate field descriptor (so that tags are
                        // written in sorted order).
                        tag = IsTiled() ? TiffTag.TILEBYTECOUNTS: TiffTag.STRIPBYTECOUNTS;
                        if (tag != fip.Tag)
                            continue;

                        data[dir].tdir_tag = tag;
                        data[dir].tdir_type = TiffType.LONG;
                        data[dir].tdir_count = m_dir.td_nstrips;
                        if (!writeLongArray(ref data[dir], m_dir.td_stripbytecount))
                            return false;

                        break;
                    case FieldBit.RowsPerStrip:
                        setupShortLong(TiffTag.ROWSPERSTRIP, ref data[dir], m_dir.td_rowsperstrip);
                        break;
                    case FieldBit.ColorMap:
                        if (!writeShortTable(TiffTag.COLORMAP, ref data[dir], 3, m_dir.td_colormap))
                            return false;

                        break;
                    case FieldBit.ImageDimensions:
                        setupShortLong(TiffTag.IMAGEWIDTH, ref data[dir++], m_dir.td_imagewidth);
                        setupShortLong(TiffTag.IMAGELENGTH, ref data[dir], m_dir.td_imagelength);
                        break;
                    case FieldBit.TileDimensions:
                        setupShortLong(TiffTag.TILEWIDTH, ref data[dir++], m_dir.td_tilewidth);
                        setupShortLong(TiffTag.TILELENGTH, ref data[dir], m_dir.td_tilelength);
                        break;
                    case FieldBit.Compression:
                        setupShort(TiffTag.COMPRESSION, ref data[dir], (short)m_dir.td_compression);
                        break;
                    case FieldBit.Photometric:
                        setupShort(TiffTag.PHOTOMETRIC, ref data[dir], (short)m_dir.td_photometric);
                        break;
                    case FieldBit.Position:
                        if (!writeRationalPair(data, dir, TiffType.RATIONAL, TiffTag.XPOSITION, m_dir.td_xposition, TiffTag.YPOSITION, m_dir.td_yposition))
                            return false;

                        dir++;
                        break;
                    case FieldBit.Resolution:
                        if (!writeRationalPair(data, dir, TiffType.RATIONAL, TiffTag.XRESOLUTION, m_dir.td_xresolution, TiffTag.YRESOLUTION, m_dir.td_yresolution))
                            return false;

                        dir++;
                        break;
                    case FieldBit.BitsPerSample:
                    case FieldBit.MinSampleValue:
                    case FieldBit.MaxSampleValue:
                    case FieldBit.SampleFormat:
                        if (!writePerSampleShorts(fip.Tag, ref data[dir]))
                            return false;

                        break;
                    case FieldBit.SMinSampleValue:
                    case FieldBit.SMaxSampleValue:
                        if (!writePerSampleAnys(sampleToTagType(), fip.Tag, ref data[dir]))
                            return false;

                        break;
                    case FieldBit.PageNumber:
                    case FieldBit.HalftoneHints:
                    case FieldBit.YCbCrSubsampling:
                        if (!setupShortPair(fip.Tag, ref data[dir]))
                            return false;

                        break;
                    case FieldBit.InkNames:
                        if (!writeInkNames(ref data[dir]))
                            return false;

                        break;
                    case FieldBit.TransferFunction:
                        if (!writeTransferFunction(ref data[dir]))
                            return false;

                        break;
                    case FieldBit.SubIFD:
                        // XXX: Always write this field using LONG type
                        // for backward compatibility.
                        data[dir].tdir_tag = fip.Tag;
                        data[dir].tdir_type = TiffType.LONG;
                        data[dir].tdir_count = m_dir.td_nsubifd;
                        if (!writeLongArray(ref data[dir], m_dir.td_subifd))
                            return false;

                        // Total hack: if this directory includes a SubIFD
                        // tag then force the next <n> directories to be
                        // written as "sub directories" of this one.  This
                        // is used to write things like thumbnails and
                        // image masks that one wants to keep out of the
                        // normal directory linkage access mechanism.
                        if (data[dir].tdir_count > 0)
                        {
                            m_flags |= TiffFlags.INSUBIFD;
                            m_nsubifd = (short)data[dir].tdir_count;
                            if (data[dir].tdir_count > 1)
                            {
                                m_subifdoff = data[dir].tdir_offset;
                            }
                            else
                            {
                                m_subifdoff = m_diroff + sizeof(short) +
                                    (uint)dir * TiffDirEntry.SizeInBytes +
                                    sizeof(short) * 2 + sizeof(int);
                            }
                        }
                        break;
                    default:
                        // XXX: Should be fixed and removed.
                        if (fip.Tag == TiffTag.DOTRANGE)
                        {
                            if (!setupShortPair(fip.Tag, ref data[dir]))
                                return false;
                        }
                        else if (!writeNormalTag(ref data[dir], fip))
                            return false;

                        break;
                }

                dir++;

                if (fip.Bit != FieldBit.Custom)
                    resetFieldBit(fields, fip.Bit);
            }

            // Write directory.

            short dircount = (short)nfields;
            uint diroff = m_nextdiroff;
            if ((m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                // The file's byte order is opposite to the native machine
                // architecture. We overwrite the directory information with
                // impunity because it'll be released below after we write it to
                // the file. Note that all the other tag construction routines
                // assume that we do this byte-swapping; i.e. they only
                // byte-swap indirect data.
                for (dir = 0; dircount != 0; dir++, dircount--)
                {
                    short temp = (short)data[dir].tdir_tag;
                    SwabShort(ref temp);
                    data[dir].tdir_tag = (TiffTag)(ushort)temp;

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

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

                dircount = (short)nfields;
                SwabShort(ref dircount);
                SwabUInt(ref diroff);
            }

            seekFile(m_diroff, SeekOrigin.Begin);
            if (!writeShortOK(dircount))
            {
                ErrorExt(this, m_clientdata, m_name, "Error writing directory count");
                return false;
            }

            if (!writeDirEntryOK(data, dirsize / TiffDirEntry.SizeInBytes))
            {
                ErrorExt(this, m_clientdata, m_name, "Error writing directory contents");
                return false;
            }

            if (!writeIntOK((int)diroff))
            {
                ErrorExt(this, m_clientdata, m_name, "Error writing directory link");
                return false;
            }

            if (done)
            {
                FreeDirectory();
                m_flags &= ~TiffFlags.DIRTYDIRECT;
                m_currentCodec.Cleanup();

                // Reset directory-related state for subsequent directories.
                CreateDirectory();
            }

            return true;
        }
Tiff