/// <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); }
/// <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; } }
// 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); }
/// <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); }
// 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; } }
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); } }