Example #1
0
        /// <summary>
        /// Computes the size of the image file directory.
        /// </summary>
        /// <param name="imageFileDirectory">The image file directory.</param>
        /// <returns>The size of the image file directory (in bytes).</returns>
        private Int64 ComputeImageFileDirectorySize(TiffImageFileDirectory imageFileDirectory)
        {
            Int64 size = (_structure == TiffStructure.BigTiff ? 8 : 2)             // number of entries
                         + _imageFileDirectoryEntrySize * imageFileDirectory.Count // entries
                         + _imageFileDirectoryFieldSize;                           // position of next directory

            TiffTagType entryType;
            UInt16      dataSize;
            Int32       dataCount;

            foreach (UInt16 entryTag in imageFileDirectory.Keys)
            {
                entryType = TiffTag.GetType(imageFileDirectory[entryTag][0]);
                dataSize  = TiffTag.GetSize(entryType);

                if (entryType == TiffTagType.ASCII)
                {
                    dataCount = 0;
                    for (Int32 i = 0; i < imageFileDirectory[entryTag].Length; i++)
                    {
                        dataCount += (imageFileDirectory[entryTag][i] as String).Length;
                    }
                }
                else
                {
                    dataCount = imageFileDirectory[entryTag].Length;
                }

                if (dataCount * dataSize > _imageFileDirectoryFieldSize)
                {
                    size += dataCount * dataSize + (dataCount * dataSize) % 2;
                }
            }

            return(size);
        }
Example #2
0
        /// <summary>
        /// Writes an image file directory to the stream.
        /// </summary>
        /// <param name="imageFileDirectory">The image file directory.</param>
        private void WriteImageFileDirectory(TiffImageFileDirectory imageFileDirectory)
        {
            _currentImageFileDirectoryStartPosition = _baseStream.Position;

            // write starting position
            _baseStream.Seek(_currentImageFileDirectoryEndPosition, SeekOrigin.Begin);
            _baseStream.Write(EndianBitConverter.GetBytes((UInt32)_currentImageFileDirectoryStartPosition), 0, _imageFileDirectoryFieldSize);

            // compute size of directory (without additional fields)
            Int64 imageFileDirectorySize = 2 + _imageFileDirectoryEntrySize * imageFileDirectory.Count;

            _currentImageFileDirectoryEndPosition = _currentImageFileDirectoryStartPosition + imageFileDirectorySize;

            // position after the IFD to write exceeding values
            _baseStream.Seek(_currentImageFileDirectoryEndPosition + _imageFileDirectoryFieldSize, SeekOrigin.Begin);

            // the IFD should be written in one operation
            Byte[] bytes;
            if (_imageCount == _maxImageCount - 1)
            {
                bytes = new Byte[imageFileDirectorySize + _imageFileDirectoryFieldSize];
            }
            else
            {
                bytes = new Byte[imageFileDirectorySize];
            }

            EndianBitConverter.CopyBytes((UInt16)imageFileDirectory.Count, bytes, 0); // number of entries
            Int32 byteIndex = 2;

            TiffTagType entryType;
            UInt16      dataSize;
            Int64       dataCount;

            foreach (UInt16 entryTag in imageFileDirectory.Keys)
            {
                entryType = TiffTag.GetType(imageFileDirectory[entryTag][0]);
                dataSize  = TiffTag.GetSize(entryType);

                if (entryType == TiffTagType.ASCII)
                {
                    dataCount = 0;
                    for (Int32 i = 0; i < imageFileDirectory[entryTag].Length; i++)
                    {
                        dataCount += (imageFileDirectory[entryTag][i] as String).Length;
                    }
                }
                else
                {
                    dataCount = imageFileDirectory[entryTag].Length;
                }

                EndianBitConverter.CopyBytes(entryTag, bytes, byteIndex);
                EndianBitConverter.CopyBytes((UInt16)entryType, bytes, byteIndex + 2);
                EndianBitConverter.CopyBytes((UInt32)dataCount, bytes, byteIndex + 4);

                // values exceeding he field size (4) must be written to another position
                Byte[] dataBytes;
                Int32  dataStartIndex;
                if (dataCount * dataSize <= 4)
                {
                    dataBytes      = bytes;
                    dataStartIndex = byteIndex + 8;
                }
                else
                {
                    dataBytes      = new Byte[dataCount * dataSize + (dataCount * dataSize) % 2];
                    dataStartIndex = 0;
                }

                for (Int32 valueIndex = 0; valueIndex < imageFileDirectory[entryTag].Length; valueIndex++)
                {
                    dataStartIndex = TiffTag.SetValue(entryType, imageFileDirectory[entryTag][valueIndex], dataBytes, dataStartIndex);
                }

                if (dataCount * dataSize > 4)
                {
                    Int64 valuePosition = _baseStream.Position;
                    _baseStream.Write(dataBytes, 0, dataBytes.Length);

                    EndianBitConverter.CopyBytes((UInt32)valuePosition, bytes, byteIndex + 8);
                }

                byteIndex += _imageFileDirectoryEntrySize;
            }

            _currentImageStartPosition = _baseStream.Position;

            // write the IFD
            _baseStream.Seek(_currentImageFileDirectoryStartPosition, SeekOrigin.Begin);
            _baseStream.Write(bytes, 0, bytes.Length);
        }