Пример #1
0
        /// <summary>Constructs a TIFFDirectory by reading a SeekableStream.</summary>
        /// <remarks>
        /// Constructs a TIFFDirectory by reading a SeekableStream.
        /// The ifd_offset parameter specifies the stream offset from which
        /// to begin reading; this mechanism is sometimes used to store
        /// private IFDs within a TIFF file that are not part of the normal
        /// sequence of IFDs.
        /// </remarks>
        /// <param name="stream">a SeekableStream to read from.</param>
        /// <param name="ifd_offset">the long byte offset of the directory.</param>
        /// <param name="directory">
        /// the index of the directory to read beyond the
        /// one at the current stream offset; zero indicates the IFD
        /// at the current offset.
        /// </param>
        /// <exception cref="System.IO.IOException"/>
        public TIFFDirectory(RandomAccessFileOrArray stream, long ifd_offset, int directory)
        {
            long global_save_offset = stream.GetPosition();

            stream.Seek(0L);
            int endian = stream.ReadUnsignedShort();

            if (!IsValidEndianTag(endian))
            {
                throw new iText.IO.IOException(iText.IO.IOException.BadEndiannessTagNot0x4949Or0x4d4d);
            }
            isBigEndian = endian == 0x4d4d;
            // Seek to the first IFD.
            stream.Seek(ifd_offset);
            // Seek to desired IFD if necessary.
            int dirNum = 0;

            while (dirNum < directory)
            {
                // Get the number of fields in the current IFD.
                int numEntries = ReadUnsignedShort(stream);
                // Skip to the next IFD offset value field.
                stream.Seek(ifd_offset + 12 * numEntries);
                // Read the offset to the next IFD beyond this one.
                ifd_offset = ReadUnsignedInt(stream);
                // Seek to the next IFD.
                stream.Seek(ifd_offset);
                // Increment the directory.
                dirNum++;
            }
            Initialize(stream);
            stream.Seek(global_save_offset);
        }
Пример #2
0
        /// <summary>Extracts the names of the font in all the languages available.</summary>
        private void ReadNameTable()
        {
            int[] table_location = tables.Get("name");
            if (table_location == null)
            {
                if (fileName != null)
                {
                    throw new iText.IO.IOException(iText.IO.IOException.TableDoesNotExistsIn).SetMessageParams("name", fileName
                                                                                                               );
                }
                else
                {
                    throw new iText.IO.IOException(iText.IO.IOException.TableDoesNotExist).SetMessageParams("name");
                }
            }
            allNameEntries = new LinkedDictionary <int, IList <String[]> >();
            raf.Seek(table_location[0] + 2);
            int numRecords     = raf.ReadUnsignedShort();
            int startOfStorage = raf.ReadUnsignedShort();

            for (int k = 0; k < numRecords; ++k)
            {
                int platformID         = raf.ReadUnsignedShort();
                int platformEncodingID = raf.ReadUnsignedShort();
                int languageID         = raf.ReadUnsignedShort();
                int nameID             = raf.ReadUnsignedShort();
                int length             = raf.ReadUnsignedShort();
                int offset             = raf.ReadUnsignedShort();
                IList <String[]> names;
                if (allNameEntries.ContainsKey(nameID))
                {
                    names = allNameEntries.Get(nameID);
                }
                else
                {
                    allNameEntries.Put(nameID, names = new List <String[]>());
                }
                int pos = (int)raf.GetPosition();
                raf.Seek(table_location[0] + startOfStorage + offset);
                String name;
                if (platformID == 0 || platformID == 3 || platformID == 2 && platformEncodingID == 1)
                {
                    name = ReadUnicodeString(length);
                }
                else
                {
                    name = ReadStandardString(length);
                }
                names.Add(new String[] { JavaUtil.IntegerToString(platformID), JavaUtil.IntegerToString(platformEncodingID
                                                                                                        ), JavaUtil.IntegerToString(languageID), name });
                raf.Seek(pos);
            }
        }
        internal virtual void ReadSegment(Jbig2SegmentReader.Jbig2Segment s)
        {
            int ptr = (int)ra.GetPosition();

            if (s.dataLength == unchecked ((long)(0xffffffffl)))
            {
                // TODO figure this bit out, 7.2.7
                return;
            }
            byte[] data = new byte[(int)s.dataLength];
            ra.Read(data);
            s.data = data;
            if (s.type == PAGE_INFORMATION)
            {
                int last = (int)ra.GetPosition();
                ra.Seek(ptr);
                int page_bitmap_width  = ra.ReadInt();
                int page_bitmap_height = ra.ReadInt();
                ra.Seek(last);
                Jbig2SegmentReader.Jbig2Page p = pages.Get(s.page);
                if (p == null)
                {
                    throw new iText.IO.IOException("Referring to widht or height of a page we haven't seen yet: {0}").SetMessageParams
                              (s.page);
                }
                p.pageBitmapWidth  = page_bitmap_width;
                p.pageBitmapHeight = page_bitmap_height;
            }
        }
Пример #4
0
        // Utilities
        /// <summary>
        /// Returns the number of image directories (subimages) stored in a
        /// given TIFF file, represented by a <code>SeekableStream</code>.
        /// </summary>
        /// <exception cref="System.IO.IOException"/>
        public static int GetNumDirectories(RandomAccessFileOrArray stream)
        {
            long pointer = stream.GetPosition();

            // Save stream pointer
            stream.Seek(0L);
            int endian = stream.ReadUnsignedShort();

            if (!IsValidEndianTag(endian))
            {
                throw new iText.IO.IOException(iText.IO.IOException.BadEndiannessTagNot0x4949Or0x4d4d);
            }
            bool isBigEndian = endian == 0x4d4d;
            int  magic       = ReadUnsignedShort(stream, isBigEndian);

            if (magic != 42)
            {
                throw new iText.IO.IOException(iText.IO.IOException.BadMagicNumberShouldBe42);
            }
            stream.Seek(4L);
            long offset         = ReadUnsignedInt(stream, isBigEndian);
            int  numDirectories = 0;

            while (offset != 0L)
            {
                ++numDirectories;
                // EOFException means IFD was probably not properly terminated.
                try {
                    stream.Seek(offset);
                    int entries = ReadUnsignedShort(stream, isBigEndian);
                    stream.Skip(12 * entries);
                    offset = ReadUnsignedInt(stream, isBigEndian);
                }
                catch (EndOfStreamException) {
                    numDirectories--;
                    break;
                }
            }
            stream.Seek(pointer);
            // Reset stream pointer
            return(numDirectories);
        }
Пример #5
0
        /// <summary>Constructs a TIFFDirectory from a SeekableStream.</summary>
        /// <remarks>
        /// Constructs a TIFFDirectory from a SeekableStream.
        /// The directory parameter specifies which directory to read from
        /// the linked list present in the stream; directory 0 is normally
        /// read but it is possible to store multiple images in a single
        /// TIFF file by maintaining multiple directories.
        /// </remarks>
        /// <param name="stream">a SeekableStream to read from.</param>
        /// <param name="directory">the index of the directory to read.</param>
        /// <exception cref="System.IO.IOException"/>
        public TIFFDirectory(RandomAccessFileOrArray stream, int directory)
        {
            long global_save_offset = stream.GetPosition();
            long ifd_offset;

            // Read the TIFF header
            stream.Seek(0L);
            int endian = stream.ReadUnsignedShort();

            if (!IsValidEndianTag(endian))
            {
                throw new iText.IO.IOException(iText.IO.IOException.BadEndiannessTagNot0x4949Or0x4d4d);
            }
            isBigEndian = endian == 0x4d4d;
            int magic = ReadUnsignedShort(stream);

            if (magic != 42)
            {
                throw new iText.IO.IOException(iText.IO.IOException.BadMagicNumberShouldBe42);
            }
            // Get the initial ifd offset as an unsigned int (using a long)
            ifd_offset = ReadUnsignedInt(stream);
            for (int i = 0; i < directory; i++)
            {
                if (ifd_offset == 0L)
                {
                    throw new iText.IO.IOException(iText.IO.IOException.DirectoryNumberTooLarge);
                }
                stream.Seek(ifd_offset);
                int entries = ReadUnsignedShort(stream);
                stream.Skip(12 * entries);
                ifd_offset = ReadUnsignedInt(stream);
            }
            stream.Seek(ifd_offset);
            Initialize(stream);
            stream.Seek(global_save_offset);
        }
Пример #6
0
        //  0 = n/a
        //  1 = byte
        //  2 = ascii
        //  3 = short
        //  4 = long
        //  5 = rational
        //  6 = sbyte
        //  7 = undefined
        //  8 = sshort
        //  9 = slong
        // 10 = srational
        // 11 = float
        // 12 = double
        /// <exception cref="System.IO.IOException"/>
        private void Initialize(RandomAccessFileOrArray stream)
        {
            long nextTagOffset = 0L;
            long maxOffset     = stream.Length();
            int  i;
            int  j;

            IFDOffset  = stream.GetPosition();
            numEntries = ReadUnsignedShort(stream);
            fields     = new TIFFField[numEntries];
            for (i = 0; i < numEntries && nextTagOffset < maxOffset; i++)
            {
                int  tag        = ReadUnsignedShort(stream);
                int  type       = ReadUnsignedShort(stream);
                int  count      = (int)ReadUnsignedInt(stream);
                bool processTag = true;
                // The place to return to to read the next tag
                nextTagOffset = stream.GetPosition() + 4;
                try {
                    // If the tag data can't fit in 4 bytes, the next 4 bytes
                    // contain the starting offset of the data
                    if (count * sizeOfType[type] > 4)
                    {
                        long valueOffset = ReadUnsignedInt(stream);
                        // bounds check offset for EOF
                        if (valueOffset < maxOffset)
                        {
                            stream.Seek(valueOffset);
                        }
                        else
                        {
                            // bad offset pointer .. skip tag
                            processTag = false;
                        }
                    }
                }
                catch (IndexOutOfRangeException) {
                    // if the data type is unknown we should skip this TIFF Field
                    processTag = false;
                }
                if (processTag)
                {
                    fieldIndex[tag] = i;
                    Object obj = null;
                    switch (type)
                    {
                    case TIFFField.TIFF_BYTE:
                    case TIFFField.TIFF_SBYTE:
                    case TIFFField.TIFF_UNDEFINED:
                    case TIFFField.TIFF_ASCII: {
                        byte[] bvalues = new byte[count];
                        stream.ReadFully(bvalues, 0, count);
                        if (type == TIFFField.TIFF_ASCII)
                        {
                            // Can be multiple strings
                            int            index     = 0;
                            int            prevIndex = 0;
                            IList <String> v         = new List <String>();
                            while (index < count)
                            {
                                while (index < count && bvalues[index++] != 0)
                                {
                                }
                                // When we encountered zero, means one string has ended
                                v.Add(iText.IO.Util.JavaUtil.GetStringForBytes(bvalues, prevIndex, (index - prevIndex)));
                                prevIndex = index;
                            }
                            count = v.Count;
                            String[] strings = new String[count];
                            for (int c = 0; c < count; c++)
                            {
                                strings[c] = v[c];
                            }
                            obj = strings;
                        }
                        else
                        {
                            obj = bvalues;
                        }
                        break;
                    }

                    case TIFFField.TIFF_SHORT: {
                        char[] cvalues = new char[count];
                        for (j = 0; j < count; j++)
                        {
                            cvalues[j] = (char)ReadUnsignedShort(stream);
                        }
                        obj = cvalues;
                        break;
                    }

                    case TIFFField.TIFF_LONG: {
                        long[] lvalues = new long[count];
                        for (j = 0; j < count; j++)
                        {
                            lvalues[j] = ReadUnsignedInt(stream);
                        }
                        obj = lvalues;
                        break;
                    }

                    case TIFFField.TIFF_RATIONAL: {
                        long[][] llvalues = new long[count][];
                        for (j = 0; j < count; j++)
                        {
                            llvalues[j]    = new long[2];
                            llvalues[j][0] = ReadUnsignedInt(stream);
                            llvalues[j][1] = ReadUnsignedInt(stream);
                        }
                        obj = llvalues;
                        break;
                    }

                    case TIFFField.TIFF_SSHORT: {
                        short[] svalues = new short[count];
                        for (j = 0; j < count; j++)
                        {
                            svalues[j] = ReadShort(stream);
                        }
                        obj = svalues;
                        break;
                    }

                    case TIFFField.TIFF_SLONG: {
                        int[] ivalues = new int[count];
                        for (j = 0; j < count; j++)
                        {
                            ivalues[j] = ReadInt(stream);
                        }
                        obj = ivalues;
                        break;
                    }

                    case TIFFField.TIFF_SRATIONAL: {
                        int[][] iivalues = new int[count][];
                        for (j = 0; j < count; j++)
                        {
                            iivalues[j]    = new int[2];
                            iivalues[j][0] = ReadInt(stream);
                            iivalues[j][1] = ReadInt(stream);
                        }
                        obj = iivalues;
                        break;
                    }

                    case TIFFField.TIFF_FLOAT: {
                        float[] fvalues = new float[count];
                        for (j = 0; j < count; j++)
                        {
                            fvalues[j] = ReadFloat(stream);
                        }
                        obj = fvalues;
                        break;
                    }

                    case TIFFField.TIFF_DOUBLE: {
                        double[] dvalues = new double[count];
                        for (j = 0; j < count; j++)
                        {
                            dvalues[j] = ReadDouble(stream);
                        }
                        obj = dvalues;
                        break;
                    }

                    default: {
                        break;
                    }
                    }
                    fields[i] = new TIFFField(tag, type, count, obj);
                }
                stream.Seek(nextTagOffset);
            }
            // Read the offset of the next IFD.
            try {
                nextIFDOffset = ReadUnsignedInt(stream);
            }
            catch (Exception) {
                // broken tiffs may not have this pointer
                nextIFDOffset = 0;
            }
        }
Пример #7
0
        private static void ProcessTiffImageColor(TIFFDirectory dir, RandomAccessFileOrArray s, TiffImageHelper.TiffParameters
                                                  tiff)
        {
            try {
                int            compression = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_COMPRESSION);
                int            predictor   = 1;
                TIFFLZWDecoder lzwDecoder  = null;
                switch (compression)
                {
                case TIFFConstants.COMPRESSION_NONE:
                case TIFFConstants.COMPRESSION_LZW:
                case TIFFConstants.COMPRESSION_PACKBITS:
                case TIFFConstants.COMPRESSION_DEFLATE:
                case TIFFConstants.COMPRESSION_ADOBE_DEFLATE:
                case TIFFConstants.COMPRESSION_OJPEG:
                case TIFFConstants.COMPRESSION_JPEG: {
                    break;
                }

                default: {
                    throw new iText.IO.IOException(iText.IO.IOException.Compression1IsNotSupported).SetMessageParams(compression
                                                                                                                     );
                }
                }
                int photometric = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_PHOTOMETRIC);
                switch (photometric)
                {
                case TIFFConstants.PHOTOMETRIC_MINISWHITE:
                case TIFFConstants.PHOTOMETRIC_MINISBLACK:
                case TIFFConstants.PHOTOMETRIC_RGB:
                case TIFFConstants.PHOTOMETRIC_SEPARATED:
                case TIFFConstants.PHOTOMETRIC_PALETTE: {
                    break;
                }

                default: {
                    if (compression != TIFFConstants.COMPRESSION_OJPEG && compression != TIFFConstants.COMPRESSION_JPEG)
                    {
                        throw new iText.IO.IOException(iText.IO.IOException.Photometric1IsNotSupported).SetMessageParams(photometric
                                                                                                                         );
                    }
                    break;
                }
                }
                float rotation = 0;
                if (dir.IsTagPresent(TIFFConstants.TIFFTAG_ORIENTATION))
                {
                    int rot = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_ORIENTATION);
                    if (rot == TIFFConstants.ORIENTATION_BOTRIGHT || rot == TIFFConstants.ORIENTATION_BOTLEFT)
                    {
                        rotation = (float)Math.PI;
                    }
                    else
                    {
                        if (rot == TIFFConstants.ORIENTATION_LEFTTOP || rot == TIFFConstants.ORIENTATION_LEFTBOT)
                        {
                            rotation = (float)(Math.PI / 2.0);
                        }
                        else
                        {
                            if (rot == TIFFConstants.ORIENTATION_RIGHTTOP || rot == TIFFConstants.ORIENTATION_RIGHTBOT)
                            {
                                rotation = -(float)(Math.PI / 2.0);
                            }
                        }
                    }
                }
                if (dir.IsTagPresent(TIFFConstants.TIFFTAG_PLANARCONFIG) && dir.GetFieldAsLong(TIFFConstants.TIFFTAG_PLANARCONFIG
                                                                                               ) == TIFFConstants.PLANARCONFIG_SEPARATE)
                {
                    throw new iText.IO.IOException(iText.IO.IOException.PlanarImagesAreNotSupported);
                }
                int extraSamples = 0;
                if (dir.IsTagPresent(TIFFConstants.TIFFTAG_EXTRASAMPLES))
                {
                    extraSamples = 1;
                }
                int samplePerPixel = 1;
                if (dir.IsTagPresent(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL))
                {
                    // 1,3,4
                    samplePerPixel = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL);
                }
                int bitsPerSample = 1;
                if (dir.IsTagPresent(TIFFConstants.TIFFTAG_BITSPERSAMPLE))
                {
                    bitsPerSample = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_BITSPERSAMPLE);
                }
                switch (bitsPerSample)
                {
                case 1:
                case 2:
                case 4:
                case 8: {
                    break;
                }

                default: {
                    throw new iText.IO.IOException(iText.IO.IOException.BitsPerSample1IsNotSupported).SetMessageParams(bitsPerSample
                                                                                                                       );
                }
                }
                int h = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_IMAGELENGTH);
                int w = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_IMAGEWIDTH);
                int dpiX;
                int dpiY;
                int resolutionUnit = TIFFConstants.RESUNIT_INCH;
                if (dir.IsTagPresent(TIFFConstants.TIFFTAG_RESOLUTIONUNIT))
                {
                    resolutionUnit = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_RESOLUTIONUNIT);
                }
                dpiX = GetDpi(dir.GetField(TIFFConstants.TIFFTAG_XRESOLUTION), resolutionUnit);
                dpiY = GetDpi(dir.GetField(TIFFConstants.TIFFTAG_YRESOLUTION), resolutionUnit);
                int       fillOrder      = 1;
                TIFFField fillOrderField = dir.GetField(TIFFConstants.TIFFTAG_FILLORDER);
                if (fillOrderField != null)
                {
                    fillOrder = fillOrderField.GetAsInt(0);
                }
                bool reverse   = (fillOrder == TIFFConstants.FILLORDER_LSB2MSB);
                int  rowsStrip = h;
                if (dir.IsTagPresent(TIFFConstants.TIFFTAG_ROWSPERSTRIP))
                {
                    //another hack for broken tiffs
                    rowsStrip = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_ROWSPERSTRIP);
                }
                if (rowsStrip <= 0 || rowsStrip > h)
                {
                    rowsStrip = h;
                }
                long[] offset = GetArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPOFFSETS);
                long[] size   = GetArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPBYTECOUNTS);
                if ((size == null || (size.Length == 1 && (size[0] == 0 || size[0] + offset[0] > s.Length()))) && h == rowsStrip
                    )
                {
                    // some TIFF producers are really lousy, so...
                    size = new long[] { s.Length() - (int)offset[0] };
                }
                if (compression == TIFFConstants.COMPRESSION_LZW || compression == TIFFConstants.COMPRESSION_DEFLATE || compression
                    == TIFFConstants.COMPRESSION_ADOBE_DEFLATE)
                {
                    TIFFField predictorField = dir.GetField(TIFFConstants.TIFFTAG_PREDICTOR);
                    if (predictorField != null)
                    {
                        predictor = predictorField.GetAsInt(0);
                        if (predictor != 1 && predictor != 2)
                        {
                            throw new iText.IO.IOException(iText.IO.IOException.IllegalValueForPredictorInTiffFile);
                        }
                        if (predictor == 2 && bitsPerSample != 8)
                        {
                            throw new iText.IO.IOException(iText.IO.IOException._1BitSamplesAreNotSupportedForHorizontalDifferencingPredictor
                                                           ).SetMessageParams(bitsPerSample);
                        }
                    }
                }
                if (compression == TIFFConstants.COMPRESSION_LZW)
                {
                    lzwDecoder = new TIFFLZWDecoder(w, predictor, samplePerPixel);
                }
                int rowsLeft = h;
                ByteArrayOutputStream stream  = null;
                ByteArrayOutputStream mstream = null;
                DeflaterOutputStream  zip     = null;
                DeflaterOutputStream  mzip    = null;
                if (extraSamples > 0)
                {
                    mstream = new ByteArrayOutputStream();
                    mzip    = new DeflaterOutputStream(mstream);
                }
                CCITTG4Encoder g4 = null;
                if (bitsPerSample == 1 && samplePerPixel == 1 && photometric != TIFFConstants.PHOTOMETRIC_PALETTE)
                {
                    g4 = new CCITTG4Encoder(w);
                }
                else
                {
                    stream = new ByteArrayOutputStream();
                    if (compression != TIFFConstants.COMPRESSION_OJPEG && compression != TIFFConstants.COMPRESSION_JPEG)
                    {
                        zip = new DeflaterOutputStream(stream);
                    }
                }
                if (compression == TIFFConstants.COMPRESSION_OJPEG)
                {
                    // Assume that the TIFFTAG_JPEGIFBYTECOUNT tag is optional, since it's obsolete and
                    // is often missing
                    if ((!dir.IsTagPresent(TIFFConstants.TIFFTAG_JPEGIFOFFSET)))
                    {
                        throw new iText.IO.IOException(iText.IO.IOException.MissingTagsForOjpegCompression);
                    }
                    int jpegOffset = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_JPEGIFOFFSET);
                    int jpegLength = (int)s.Length() - jpegOffset;
                    if (dir.IsTagPresent(TIFFConstants.TIFFTAG_JPEGIFBYTECOUNT))
                    {
                        jpegLength = (int)dir.GetFieldAsLong(TIFFConstants.TIFFTAG_JPEGIFBYTECOUNT) + (int)size[0];
                    }
                    byte[] jpeg           = new byte[Math.Min(jpegLength, (int)s.Length() - jpegOffset)];
                    int    posFilePointer = (int)s.GetPosition();
                    posFilePointer += jpegOffset;
                    s.Seek(posFilePointer);
                    s.ReadFully(jpeg);
                    tiff.image.data = jpeg;
                    tiff.image.SetOriginalType(ImageType.JPEG);
                    JpegImageHelper.ProcessImage(tiff.image);
                    tiff.jpegProcessing = true;
                }
                else
                {
                    if (compression == TIFFConstants.COMPRESSION_JPEG)
                    {
                        if (size.Length > 1)
                        {
                            throw new iText.IO.IOException(iText.IO.IOException.CompressionJpegIsOnlySupportedWithASingleStripThisImageHas1Strips
                                                           ).SetMessageParams(size.Length);
                        }
                        byte[] jpeg = new byte[(int)size[0]];
                        s.Seek(offset[0]);
                        s.ReadFully(jpeg);
                        // if quantization and/or Huffman tables are stored separately in the tiff,
                        // we need to add them to the jpeg data
                        TIFFField jpegtables = dir.GetField(TIFFConstants.TIFFTAG_JPEGTABLES);
                        if (jpegtables != null)
                        {
                            byte[] temp        = jpegtables.GetAsBytes();
                            int    tableoffset = 0;
                            int    tablelength = temp.Length;
                            // remove FFD8 from start
                            if (temp[0] == (byte)0xFF && temp[1] == (byte)0xD8)
                            {
                                tableoffset  = 2;
                                tablelength -= 2;
                            }
                            // remove FFD9 from end
                            if (temp[temp.Length - 2] == (byte)0xFF && temp[temp.Length - 1] == (byte)0xD9)
                            {
                                tablelength -= 2;
                            }
                            byte[] tables = new byte[tablelength];
                            System.Array.Copy(temp, tableoffset, tables, 0, tablelength);
                            // TODO insert after JFIF header, instead of at the start
                            byte[] jpegwithtables = new byte[jpeg.Length + tables.Length];
                            System.Array.Copy(jpeg, 0, jpegwithtables, 0, 2);
                            System.Array.Copy(tables, 0, jpegwithtables, 2, tables.Length);
                            System.Array.Copy(jpeg, 2, jpegwithtables, tables.Length + 2, jpeg.Length - 2);
                            jpeg = jpegwithtables;
                        }
                        tiff.image.data = jpeg;
                        tiff.image.SetOriginalType(ImageType.JPEG);
                        JpegImageHelper.ProcessImage(tiff.image);
                        tiff.jpegProcessing = true;
                        if (photometric == TIFFConstants.PHOTOMETRIC_RGB)
                        {
                            tiff.image.SetColorTransform(0);
                        }
                    }
                    else
                    {
                        for (int k = 0; k < offset.Length; ++k)
                        {
                            byte[] im = new byte[(int)size[k]];
                            s.Seek(offset[k]);
                            s.ReadFully(im);
                            int    height = Math.Min(rowsStrip, rowsLeft);
                            byte[] outBuf = null;
                            if (compression != TIFFConstants.COMPRESSION_NONE)
                            {
                                outBuf = new byte[(w * bitsPerSample * samplePerPixel + 7) / 8 * height];
                            }
                            if (reverse)
                            {
                                TIFFFaxDecoder.ReverseBits(im);
                            }
                            switch (compression)
                            {
                            case TIFFConstants.COMPRESSION_DEFLATE:
                            case TIFFConstants.COMPRESSION_ADOBE_DEFLATE: {
                                FilterUtil.InflateData(im, outBuf);
                                ApplyPredictor(outBuf, predictor, w, height, samplePerPixel);
                                break;
                            }

                            case TIFFConstants.COMPRESSION_NONE: {
                                outBuf = im;
                                break;
                            }

                            case TIFFConstants.COMPRESSION_PACKBITS: {
                                DecodePackbits(im, outBuf);
                                break;
                            }

                            case TIFFConstants.COMPRESSION_LZW: {
                                lzwDecoder.Decode(im, outBuf, height);
                                break;
                            }
                            }
                            if (bitsPerSample == 1 && samplePerPixel == 1 && photometric != TIFFConstants.PHOTOMETRIC_PALETTE)
                            {
                                g4.Fax4Encode(outBuf, height);
                            }
                            else
                            {
                                if (extraSamples > 0)
                                {
                                    ProcessExtraSamples(zip, mzip, outBuf, samplePerPixel, bitsPerSample, w, height);
                                }
                                else
                                {
                                    zip.Write(outBuf);
                                }
                            }
                            rowsLeft -= rowsStrip;
                        }
                        if (bitsPerSample == 1 && samplePerPixel == 1 && photometric != TIFFConstants.PHOTOMETRIC_PALETTE)
                        {
                            RawImageHelper.UpdateRawImageParameters(tiff.image, w, h, false, RawImageData.CCITTG4, photometric == TIFFConstants
                                                                    .PHOTOMETRIC_MINISBLACK ? RawImageData.CCITT_BLACKIS1 : 0, g4.Close(), null);
                        }
                        else
                        {
                            zip.Close();
                            RawImageHelper.UpdateRawImageParameters(tiff.image, w, h, samplePerPixel - extraSamples, bitsPerSample, stream
                                                                    .ToArray());
                            tiff.image.SetDeflated(true);
                        }
                    }
                }
                tiff.image.SetDpi(dpiX, dpiY);
                if (compression != TIFFConstants.COMPRESSION_OJPEG && compression != TIFFConstants.COMPRESSION_JPEG)
                {
                    if (dir.IsTagPresent(TIFFConstants.TIFFTAG_ICCPROFILE))
                    {
                        try {
                            TIFFField  fd       = dir.GetField(TIFFConstants.TIFFTAG_ICCPROFILE);
                            IccProfile icc_prof = IccProfile.GetInstance(fd.GetAsBytes());
                            if (samplePerPixel - extraSamples == icc_prof.GetNumComponents())
                            {
                                tiff.image.SetProfile(icc_prof);
                            }
                        }
                        catch (Exception) {
                        }
                    }
                    //empty
                    if (dir.IsTagPresent(TIFFConstants.TIFFTAG_COLORMAP))
                    {
                        TIFFField fd      = dir.GetField(TIFFConstants.TIFFTAG_COLORMAP);
                        char[]    rgb     = fd.GetAsChars();
                        byte[]    palette = new byte[rgb.Length];
                        int       gColor  = rgb.Length / 3;
                        int       bColor  = gColor * 2;
                        for (int k = 0; k < gColor; ++k)
                        {
                            //there is no sense in >>> for unsigned char
                            palette[k * 3]     = (byte)(rgb[k] >> 8);
                            palette[k * 3 + 1] = (byte)(rgb[k + gColor] >> 8);
                            palette[k * 3 + 2] = (byte)(rgb[k + bColor] >> 8);
                        }
                        // Colormap components are supposed to go from 0 to 655535 but,
                        // as usually, some tiff producers just put values from 0 to 255.
                        // Let's check for these broken tiffs.
                        bool colormapBroken = true;
                        for (int k_1 = 0; k_1 < palette.Length; ++k_1)
                        {
                            if (palette[k_1] != 0)
                            {
                                colormapBroken = false;
                                break;
                            }
                        }
                        if (colormapBroken)
                        {
                            for (int k_2 = 0; k_2 < gColor; ++k_2)
                            {
                                palette[k_2 * 3]     = (byte)rgb[k_2];
                                palette[k_2 * 3 + 1] = (byte)rgb[k_2 + gColor];
                                palette[k_2 * 3 + 2] = (byte)rgb[k_2 + bColor];
                            }
                        }
                        Object[] indexed = new Object[4];
                        indexed[0]      = "Indexed";
                        indexed[1]      = "DeviceRGB";
                        indexed[2]      = gColor - 1;
                        indexed[3]      = PdfEncodings.ConvertToString(palette, null);
                        tiff.additional = new Dictionary <String, Object>();
                        tiff.additional["ColorSpace"] = indexed;
                    }
                }
                if (photometric == TIFFConstants.PHOTOMETRIC_MINISWHITE)
                {
                    tiff.image.SetInverted(true);
                }
                if (rotation != 0)
                {
                    tiff.image.SetRotation(rotation);
                }
                if (extraSamples > 0)
                {
                    mzip.Close();
                    RawImageData mimg = (RawImageData)ImageDataFactory.CreateRawImage(null);
                    RawImageHelper.UpdateRawImageParameters(mimg, w, h, 1, bitsPerSample, mstream.ToArray());
                    mimg.MakeMask();
                    mimg.SetDeflated(true);
                    tiff.image.SetImageMask(mimg);
                }
            }
            catch (Exception) {
                throw new iText.IO.IOException(iText.IO.IOException.CannotGetTiffImageColor);
            }
        }