Example #1
0
        /// <summary>
        /// Handles an error by writing it text to the <see cref="Console.Error"/>.
        /// </summary>
        /// <param name="tif">An instance of the <see cref="Tiff"/> class. Can be <c>null</c>.</param>
        /// <param name="method">The method where an error is detected.</param>
        /// <param name="format">A composite format string (see Remarks).</param>
        /// <param name="args">An object array that contains zero or more objects to format.</param>
        /// <remarks>
        /// The <paramref name="format"/> is a composite format string that uses the same format as
        /// <see cref="O:System.String.Format"/> method. The <paramref name="method"/> parameter, if
        /// not <c>null</c>, is printed before the message; it typically is used to identify the
        /// method in which an error is detected.
        /// </remarks>
        public virtual void ErrorHandler(Tiff tif, string method, string format, params object[] args)
        {
            TextWriter stderr = Console.Error;
            if (method != null)
                stderr.Write("{0}: ", method);

            stderr.Write(format, args);
            stderr.Write("\n");
        }
Example #2
0
        public int getNumberofTiffPages(Tiff image)
        {
            int pageCount = 0;
            do
            {
                ++pageCount;
            } while (image.ReadDirectory());

            return pageCount;
        }
        public override void ErrorHandler(Tiff tif, string module, string fmt, params object[] ap)
        {
            using (TextWriter stdout = Console.Out)
            {
                if (module != null)
                    stdout.Write("{0}: ", module);

                stdout.Write(fmt, ap);
                stdout.Write(".\n");
            }
        }
Example #4
0
        /// <summary>
        /// Handles a warning by writing it text to the <see cref="Console.Error"/>.
        /// </summary>
        /// <param name="tif">An instance of the <see cref="Tiff"/> class. Can be <c>null</c>.</param>
        /// <param name="method">The method where a warning is detected.</param>
        /// <param name="format">A composite format string (see Remarks).</param>
        /// <param name="args">An object array that contains zero or more objects to format.</param>
        /// <remarks>
        /// The <paramref name="format"/> is a composite format string that uses the same format as
        /// <see cref="O:System.String.Format"/> method. The <paramref name="method"/> parameter, if
        /// not <c>null</c>, is printed before the message; it typically is used to identify the
        /// method in which a warning is detected.
        /// </remarks>
        public virtual void WarningHandler(Tiff tif, string method, string format, params object[] args)
        {
            TextWriter stderr = Console.Error;

            if (method != null)
            {
                stderr.Write("{0}: ", method);
            }

            stderr.Write("Warning, ");
            stderr.Write(format, args);
            stderr.Write("\n");
        }
Example #5
0
        public bool tiffcvt(Tiff inImage, Tiff outImage)
        {
            FieldValue[] result = inImage.GetField(TiffTag.IMAGEWIDTH);
            if (result == null)
                return false;
            int width = result[0].ToInt();

            result = inImage.GetField(TiffTag.IMAGELENGTH);
            if (result == null)
                return false;
            int height = result[0].ToInt();

            copyField(inImage, outImage, TiffTag.SUBFILETYPE);
            outImage.SetField(TiffTag.IMAGEWIDTH, width);
            outImage.SetField(TiffTag.IMAGELENGTH, height);
            outImage.SetField(TiffTag.BITSPERSAMPLE, 8);
            outImage.SetField(TiffTag.COMPRESSION, m_compression);
            outImage.SetField(TiffTag.PHOTOMETRIC, Photometric.RGB);

            copyField(inImage, outImage, TiffTag.FILLORDER);
            outImage.SetField(TiffTag.ORIENTATION, Orientation.TOPLEFT);

            if (m_noAlpha)
                outImage.SetField(TiffTag.SAMPLESPERPIXEL, 3);
            else
                outImage.SetField(TiffTag.SAMPLESPERPIXEL, 4);

            if (!m_noAlpha)
            {
                short[] v = new short[1];
                v[0] = (short)ExtraSample.ASSOCALPHA;
                outImage.SetField(TiffTag.EXTRASAMPLES, 1, v);
            }

            copyField(inImage, outImage, TiffTag.XRESOLUTION);
            copyField(inImage, outImage, TiffTag.YRESOLUTION);
            copyField(inImage, outImage, TiffTag.RESOLUTIONUNIT);
            outImage.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);

            if (!m_testFriendly)
                outImage.SetField(TiffTag.SOFTWARE, Tiff.GetVersion());

            copyField(inImage, outImage, TiffTag.DOCUMENTNAME);
            
            if (m_processByBlock && inImage.IsTiled())
                return cvt_by_tile(inImage, outImage, width, height);
            else if (m_processByBlock)
                return cvt_by_strip(inImage, outImage, width, height);

            return cvt_whole_image(inImage, outImage, width, height);
        }
Example #6
0
        static Tiff Open(string fileName, string mode, TiffErrorHandler errorHandler, TiffExtendProc extender)
        {
            const string module = "Open";

            FileMode   fileMode;
            FileAccess fileAccess;

            getMode(mode, module, out fileMode, out fileAccess);

            FileStream stream = null;

            try
            {
                if (fileAccess == FileAccess.Read)
                {
                    stream = File.Open(fileName, fileMode, fileAccess, FileShare.Read);
                }
                else
                {
                    stream = File.Open(fileName, fileMode, fileAccess);
                }
            }
#if THREAD_SAFE_LIBTIFF
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception)
#pragma warning restore CA1031 // Do not catch general exception types
            {
                return(null);
            }
#else
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
            {
                Error(module, "Failed to open '{0}'. {1}", fileName, e.Message);
                return(null);
            }
#endif

            Tiff tif = ClientOpen(fileName, mode, stream, new TiffStream(), errorHandler, extender);
            if (tif == null)
            {
                stream.Dispose();
            }
            else
            {
                tif.m_fileStream = stream;
            }

            return(tif);
        }
Example #7
0
        private bool writeOK(byte[] buffer, int offset, int count)
        {
            try
            {
                m_stream.Write(m_clientdata, buffer, offset, count);
            }
            catch (Exception)
            {
                Tiff.Warning(this, "writeOK", "Failed to write {0} bytes", count);
                return(false);
            }

            return(true);
        }
        private static TiffErrorHandler getErrorHandler(Tiff tif)
        {
            TiffErrorHandler errorHandler = null;

#if THREAD_SAFE_LIBTIFF
            if (tif != null)
            {
                errorHandler = tif.m_errorHandler;
            }
#else
            errorHandler = m_errorHandler;
#endif
            return(errorHandler);
        }
Example #9
0
        static Tiff Open(string name, string mode, Stream stream, TiffErrorHandler errorHandler, TiffExtendProc extender)
        {
            Tiff tif = ClientOpen(name, mode, stream, new TiffStream(), errorHandler, extender);

            if (tif == null)
            {
                stream.Dispose();
            }
            else
            {
                tif.m_fileStream = stream;
            }

            return(tif);
        }
Example #10
0
        private bool writeOK(byte[] buffer, int offset, int count)
        {
            try
            {
                m_stream.Write(m_clientdata, buffer, offset, count);
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception)
#pragma warning restore CA1031 // Do not catch general exception types
            {
                Tiff.Warning(this, "writeOK", "Failed to write {0} bytes", count);
                return(false);
            }

            return(true);
        }
        private static Metadata ReadMetadata(T.Tiff tiff, int defaultTileWidth)
        {
            var x      = tiff.GetField(T.TiffTag.IMAGEWIDTH);
            int width  = tiff.GetField(T.TiffTag.IMAGEWIDTH)[0].ToInt();
            int height = tiff.GetField(T.TiffTag.IMAGELENGTH)[0].ToInt();
            var twtag  = tiff.GetField(T.TiffTag.TILEWIDTH);

            var tileWidth = twtag == null ? defaultTileWidth : twtag[0].ToInt();

            return(new Metadata
            {
                Width = width,
                Height = height,
                TileWidth = tileWidth,
                ScalingLevels = (int)(Math.Floor(Math.Log(Math.Max(width, height), 2)) - 3)
            });
        }
        private static (ProcessState state, SKImage image) ReadFullImage(T.Tiff tiff, ImageRequest request, bool allowSizeAboveFull)
        {
            int width  = tiff.GetField(T.TiffTag.IMAGEWIDTH)[0].ToInt();
            int height = tiff.GetField(T.TiffTag.IMAGELENGTH)[0].ToInt();

            var restag  = tiff.GetField(T.TiffTag.RESOLUTIONUNIT);
            var xrestag = tiff.GetField(T.TiffTag.XRESOLUTION);
            var yrestag = tiff.GetField(T.TiffTag.YRESOLUTION);

            var resunit = restag == null ? 2 : restag[0].ToShort();
            var xres    = xrestag == null ? 96 : xrestag[0].ToDouble();
            var yres    = yrestag == null ? 96 : yrestag[0].ToDouble();

            // pixels per metre
            if (resunit == 3)
            {
                xres = xres / 0.0254;
                yres = yres / 0.0254;
            }

            var isTileable = tiff.IsTiled();
            var state      = ImageRequestInterpreter.GetInterpretedValues(request, width, height, allowSizeAboveFull);

            state.HorizontalResolution = Convert.ToUInt16(xres);
            state.VerticalResolution   = Convert.ToUInt16(yres);
            var raster = new int[width * height];

            if (!tiff.ReadRGBAImageOriented(width, height, raster, T.Orientation.TOPLEFT))
            {
                throw new IOException("Unable to decode TIFF file");
            }
            using (var bmp = CreateBitmapFromPixels(raster, width, height))
            {
                var desiredWidth  = Math.Max(1, (int)Math.Round(state.RegionWidth * state.ImageScale));
                var desiredHeight = Math.Max(1, (int)Math.Round(state.RegionHeight * state.ImageScale));
                Log.Debug("Desired size {@DesiredWidth}, {@DesiredHeight}", desiredWidth, desiredHeight);

                var regionWidth  = state.RegionWidth;
                var regionHeight = state.RegionHeight;

                var srcRegion = SKRectI.Create(state.StartX, state.StartY, regionWidth, regionHeight);
                return(state, CopyImageRegion2(bmp, desiredWidth, desiredHeight, srcRegion));
            }
        }
Example #13
0
        public void TagExtender(Tiff tif)
        {
            TiffFieldInfo[] tiffFieldInfo = 
            {
                new TiffFieldInfo(TIFFTAG_ASCIITAG, -1, -1, TiffType.ASCII, FieldBit.Custom, true, false, "MyTag"),
                new TiffFieldInfo(TIFFTAG_SHORTTAG, 2, 2, TiffType.SHORT, FieldBit.Custom, false, true, "ShortTag"),
                new TiffFieldInfo(TIFFTAG_LONGTAG, 2, 2, TiffType.LONG, FieldBit.Custom, false, true, "LongTag"),
                new TiffFieldInfo(TIFFTAG_RATIONALTAG, 2, 2, TiffType.RATIONAL, FieldBit.Custom, false, true, "RationalTag"),
                new TiffFieldInfo(TIFFTAG_FLOATTAG, 2, 2, TiffType.FLOAT, FieldBit.Custom, false, true, "FloatTag"),
                new TiffFieldInfo(TIFFTAG_DOUBLETAG, 2, 2, TiffType.DOUBLE, FieldBit.Custom, false, true, "DoubleTag"),
                new TiffFieldInfo(TIFFTAG_BYTETAG, 2, 2, TiffType.BYTE, FieldBit.Custom, false, true, "ByteTag"),
                new TiffFieldInfo(TIFFTAG_IFDTAG, 1, 1, TiffType.IFD, FieldBit.Custom, false, false, "IfdTag"),
            };

            tif.MergeFieldInfo(tiffFieldInfo, tiffFieldInfo.Length);

            if (m_parentExtender != null)
                m_parentExtender(tif);
        }
        static Tiff Open(Stream stream, string mode, TiffErrorHandler errorHandler, TiffExtendProc extender)
        {
            const string module = "Open";

            getMode(mode, module);

            Tiff tif = ClientOpen("Stream", mode, stream, new TiffStream(), errorHandler, extender);

            if (tif == null)
            {
                stream.Dispose();
            }
            else
            {
                tif.m_fileStream = stream;
            }

            return(tif);
        }
Example #15
0
    public TiffGrid(string filename, string NewFileName)
    {
      ValuesToWrite = new Dictionary<int, Dictionary<int, double>>();

      tiff_org = BitMiracle.LibTiff.Classic.Tiff.Open(Path.GetFullPath(filename), "r");

      tiff = BitMiracle.LibTiff.Classic.Tiff.Open(Path.GetFullPath(NewFileName), "w");
      foreach (TiffTag enu in Enum.GetValues(typeof(TiffTag)))
      {
        var val = tiff_org.GetField(enu);
        if (val != null & enu != TiffTag.EXTRASAMPLES)
          tiff.SetField(enu, val[0]);
      }

      for (int i = 0; i < tiff_org.GetTagListCount(); i++)
      {
        int k = tiff_org.GetTagListEntry(i);
        var ff = tiff_org.FindFieldInfo((TiffTag)k, TiffType.ANY);
        tiff.MergeFieldInfo(new TiffFieldInfo[] { ff }, 1);
        var val = tiff_org.GetField((TiffTag)tiff_org.GetTagListEntry(i));
        tiff.SetField((TiffTag)k, val[0], val[1]);
      }

      var val2 = tiff_org.GetField((TiffTag)33922)[1].ToDoubleArray();
      XOrigin = val2[3];
      YOrigin = val2[4]; //Upper basegrid assumes Lower
      val2 = tiff_org.GetField((TiffTag)33550)[1].ToDoubleArray();
      GridSize = val2[0];
      GridSize = val2[1];
      NumberOfColumns = tiff_org.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
      NumberOfRows = tiff_org.GetField(TiffTag.IMAGELENGTH)[0].ToInt();

      //Shift YOrigin to lower left
      YOrigin -= GridSize * NumberOfRows;
      scanline = new byte[tiff_org.ScanlineSize()];
      bits = scanline.Count() / NumberOfColumns;
      ScanLineCache = new Dictionary<int, byte[]>();




    }
Example #16
0
    public TiffGrid(string FileName)
    {

      string fname = Path.GetFullPath(FileName);

      tiff = Tiff.Open(FileName, "r");
      var val = tiff.GetField((TiffTag)33922)[1].ToDoubleArray();
      XOrigin = val[3];
      YOrigin = val[4]; //Upper basegrid assumes Lower
      val = tiff.GetField((TiffTag)33550)[1].ToDoubleArray();
      GridSize = val[0];
      GridSize = val[1];
      NumberOfColumns = tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
      NumberOfRows = tiff.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
      scanline = new byte[tiff.ScanlineSize()];
      bits = tiff.ScanlineSize() / NumberOfColumns;
      ScanLineCache = new Dictionary<int, byte[]>();

      
    }
Example #17
0
        static Tiff Open(string fileName, string mode, TiffErrorHandler errorHandler, TiffExtendProc extender)
        {
            const string module = "Open";

            FileMode   fileMode;
            FileAccess fileAccess;

            getMode(mode, module, out fileMode, out fileAccess);

            FileStream stream = null;

            try
            {
                if (fileAccess == FileAccess.Read)
                {
                    stream = File.Open(fileName, fileMode, fileAccess, FileShare.Read);
                }
                else
                {
                    stream = File.Open(fileName, fileMode, fileAccess);
                }
            }
            catch (Exception e)
            {
                Error(module, "Failed to open '{0}'. {1}", fileName, e.Message);
                return(null);
            }

            Tiff tif = ClientOpen(fileName, mode, stream, new TiffStream(), errorHandler, extender);

            if (tif == null)
            {
                stream.Dispose();
            }
            else
            {
                tif.m_fileStream = stream;
            }

            return(tif);
        }
Example #18
0
        private static void PrintTagInfo(Tiff tiff, TiffTag tiffTag)
        {
            try
            {
                var field = tiff.GetField(tiffTag);
                if (field != null)
                {
                    Console.WriteLine($"{tiffTag}");
                    for (int i = 0; i < field.Length; i++)
                    {
                        Console.WriteLine($"  [{i}] {field[i].Value}");
                        byte[] bytes = field[i].Value as byte[];
                        if (bytes != null)
                        {
                            Console.WriteLine($"    Length: {bytes.Length}");
                            if (bytes.Length % 8 == 0)
                            {
                                for (int k = 0; k < bytes.Length / 8; k++)
                                {
                                    Console.WriteLine($"      [{k}] {BitConverter.ToDouble(bytes, k * 8)}");
                                }
                            }

                            try
                            {
                                Console.WriteLine($"   > {System.Text.Encoding.ASCII.GetString(bytes).Trim()} < ");
                            }
                            catch (Exception ex)
                            {

                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"ERROR: {tiffTag}");
            }
        }
        private static int checkInkNamesString(Tiff tif, int slen, string s)
        {
            bool  failed = false;
            short i      = tif.m_dir.td_samplesperpixel;

            if (slen > 0)
            {
                int endPos = slen;
                int pos    = 0;

                for (; i > 0; i--)
                {
                    for (; s[pos] != '\0'; pos++)
                    {
                        if (pos >= endPos)
                        {
                            failed = true;
                            break;
                        }
                    }

                    if (failed)
                    {
                        break;
                    }

                    pos++; // skip \0
                }

                if (!failed)
                {
                    return(pos);
                }
            }

            Tiff.ErrorExt(tif, tif.m_clientdata, "TIFFSetField",
                          "{0}: Invalid InkNames value; expecting {1} names, found {2}",
                          tif.m_name, tif.m_dir.td_samplesperpixel, tif.m_dir.td_samplesperpixel - i);
            return(0);
        }
Example #20
0
        private static void SetTiffField(TiffInfo info, BitMiracle.LibTiff.Classic.Tiff image)
        {
            if (image == null)
            {
                throw new NullReferenceException("image");
            }

            // We need to set some values for basic tags before we can add any data
            image.SetField(TiffTag.IMAGEWIDTH, info.Width);
            image.SetField(TiffTag.IMAGELENGTH, info.Height);
            image.SetField(TiffTag.BITSPERSAMPLE, info.BitsPerSample);
            image.SetField(TiffTag.SAMPLESPERPIXEL, info.SamplesPerPixel);
            image.SetField(TiffTag.ORIENTATION, info.Orientation);
            image.SetField(TiffTag.ROWSPERSTRIP, info.Height);
            image.SetField(TiffTag.XRESOLUTION, info.XResolution);
            image.SetField(TiffTag.YRESOLUTION, info.YResolution);
            image.SetField(TiffTag.RESOLUTIONUNIT, info.ResolutionUnit);
            image.SetField(TiffTag.PLANARCONFIG, info.PlanarConfig);
            image.SetField(TiffTag.PHOTOMETRIC, info.Photometric);
            image.SetField(TiffTag.COMPRESSION, info.Compression);
            image.SetField(TiffTag.FILLORDER, info.FillOrder);
        }
Example #21
0
        public TiffGrid(string FileName)
    {

      string fname = Path.GetFullPath(FileName);
      if (!File.Exists(fname))
        return;
        tiff = BitMiracle.LibTiff.Classic.Tiff.Open(FileName, "r");
      
      var val = tiff.GetField((TiffTag)33922)[1].ToDoubleArray();
      XOrigin = val[3];
      YOrigin = val[4]; //Upper basegrid assumes Lower
      val = tiff.GetField((TiffTag)33550)[1].ToDoubleArray();
      GridSize = val[0];
      GridSize = val[1];
      NumberOfColumns = tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
      NumberOfRows = tiff.GetField(TiffTag.IMAGELENGTH)[0].ToInt();

      //Shift YOrigin to lower left
      YOrigin -= GridSize * NumberOfRows;
      scanline = new byte[tiff.ScanlineSize()];
      bits = scanline.Count() / NumberOfColumns;
      ScanLineCache = new Dictionary<int, byte[]>();
      
    }
Example #22
0
        bool readContigTilesIntoBuffer(Tiff inImage, byte[] buf, int imagelength, int imagewidth, short spp)
        {
            byte[] tilebuf = new byte[inImage.TileSize()];

            FieldValue[] result = inImage.GetField(TiffTag.TILEWIDTH);
            int tw = result[0].ToInt();

            result = inImage.GetField(TiffTag.TILELENGTH);
            int tl = result[0].ToInt();

            int imagew = inImage.ScanlineSize();
            int tilew = inImage.TileRowSize();
            int iskew = imagew - tilew;

            int bufp = 0;

            for (int row = 0; row < imagelength; row += tl)
            {
                int nrow = (row + tl > imagelength) ? imagelength - row : tl;
                int colb = 0;

                for (int col = 0; col < imagewidth; col += tw)
                {
                    if (inImage.ReadTile(tilebuf, 0, col, row, 0, 0) < 0 && !m_ignore)
                    {
                        Tiff.Error(inImage.FileName(), "Error, can't read tile at {0} {1}", col, row);
                        return false;
                    }

                    if (colb + tilew > imagew)
                    {
                        int width = imagew - colb;
                        int oskew = tilew - width;
                        cpStripToTile(buf, bufp + colb, tilebuf, 0, nrow, width, oskew + iskew, oskew);
                    }
                    else
                        cpStripToTile(buf, bufp + colb, tilebuf, 0, nrow, tilew, iskew, 0);

                    colb += tilew;
                }

                bufp += imagew * nrow;
            }

            return true;
        }
Example #23
0
        bool readSeparateStripsIntoBuffer(Tiff inImage, byte[] buf, int imagelength, int imagewidth, short spp)
        {
            int scanlinesize = inImage.ScanlineSize();
            if (scanlinesize == 0)
                return false;

            byte[] scanline = new byte[scanlinesize];
            int bufp = 0;
            for (int row = 0; row < imagelength; row++)
            {
                /* merge channels */
                for (short s = 0; s < spp; s++)
                {
                    if (!inImage.ReadScanline(scanline, row, s) && !m_ignore)
                    {
                        Tiff.Error(inImage.FileName(), "Error, can't read scanline {0}", row);
                        return false;
                    }

                    int n = scanlinesize;
                    int bp = s;
                    int sbuf = 0;
                    while (n-- > 0)
                    {
                        buf[bufp + bp] = scanline[sbuf];
                        sbuf++;
                        bp += spp;
                    }
                }

                bufp += scanlinesize * spp;
            }

            return true;
        }
Example #24
0
 public override void ErrorHandler(Tiff tif, string method, string format, params object[] args)
 {
 }
Example #25
0
        /*
         * Contig -> contig by scanline while subtracting a bias image.
         */
        bool cpBiasedContig2Contig(Tiff inImage, Tiff outImage, int imagelength, int imagewidth, short spp)
        {
            if (spp == 1)
            {
                int biasSize = m_bias.ScanlineSize();
                int bufSize = inImage.ScanlineSize();

                FieldValue[] result = m_bias.GetField(TiffTag.IMAGEWIDTH);
                int biasWidth = result[0].ToInt();

                result = m_bias.GetField(TiffTag.IMAGELENGTH);
                int biasLength = result[0].ToInt();

                if (biasSize == bufSize && imagelength == biasLength && imagewidth == biasWidth)
                {
                    result = inImage.GetField(TiffTag.BITSPERSAMPLE);
                    short sampleBits = result[0].ToShort();

                    if (sampleBits == 8 || sampleBits == 16 || sampleBits == 32)
                    {
                        byte[] buf = new byte[bufSize];
                        byte[] biasBuf = new byte[bufSize];

                        for (int row = 0; row < imagelength; row++)
                        {
                            if (!inImage.ReadScanline(buf, row, 0) && !m_ignore)
                            {
                                Tiff.Error(inImage.FileName(), "Error, can't read scanline {0}", row);
                                return false;
                            }

                            if (!m_bias.ReadScanline(biasBuf, row, 0) && !m_ignore)
                            {
                                Tiff.Error(inImage.FileName(), "Error, can't read biased scanline {0}", row);
                                return false;
                            }

                            if (sampleBits == 8)
                                subtract8(buf, biasBuf, imagewidth);
                            else if (sampleBits == 16)
                                subtract16(buf, biasBuf, imagewidth);
                            else if (sampleBits == 32)
                                subtract32(buf, biasBuf, imagewidth);

                            if (!outImage.WriteScanline(buf, row, 0))
                            {
                                Tiff.Error(outImage.FileName(), "Error, can't write scanline {0}", row);
                                return false;
                            }
                        }

                        m_bias.SetDirectory(m_bias.CurrentDirectory()); /* rewind */
                        return true;
                    }
                    else
                    {
                        Tiff.Error(inImage.FileName(), "No support for biasing {0} bit pixels\n", sampleBits);
                        return false;
                    }
                }

                Tiff.Error(inImage.FileName(), "Bias image {0},{1}\nis not the same size as {2},{3}\n",
                    m_bias.FileName(), m_bias.CurrentDirectory(), inImage.FileName(), inImage.CurrentDirectory());
                return false;
            }
            else
            {
                Tiff.Error(inImage.FileName(), "Can't bias {0},{1} as it has >1 Sample/Pixel\n",
                    inImage.FileName(), inImage.CurrentDirectory());
                return false;
            }
        }
Example #26
0
        public bool Copy(Tiff inImage, Tiff outImage)
        {
            int width = 0;
            FieldValue[] result = inImage.GetField(TiffTag.IMAGEWIDTH);
            if (result != null)
            {
                width = result[0].ToInt();
                outImage.SetField(TiffTag.IMAGEWIDTH, width);
            }

            int length = 0;
            result = inImage.GetField(TiffTag.IMAGELENGTH);
            if (result != null)
            {
                length = result[0].ToInt();
                outImage.SetField(TiffTag.IMAGELENGTH, length);
            }

            short bitspersample = 1;
            result = inImage.GetField(TiffTag.BITSPERSAMPLE);
            if (result != null)
            {
                bitspersample = result[0].ToShort();
                outImage.SetField(TiffTag.BITSPERSAMPLE, bitspersample);
            }

            short samplesperpixel = 1;
            result = inImage.GetField(TiffTag.SAMPLESPERPIXEL);
            if (result != null)
            {
                samplesperpixel = result[0].ToShort();
                outImage.SetField(TiffTag.SAMPLESPERPIXEL, samplesperpixel);
            }

            if (m_compression != (Compression)(-1))
                outImage.SetField(TiffTag.COMPRESSION, m_compression);
            else
            {
                result = inImage.GetField(TiffTag.COMPRESSION);
                if (result != null)
                {
                    m_compression = (Compression)result[0].ToInt();
                    outImage.SetField(TiffTag.COMPRESSION, m_compression);
                }
            }

            result = inImage.GetFieldDefaulted(TiffTag.COMPRESSION);
            Compression input_compression = (Compression)result[0].ToInt();

            result = inImage.GetFieldDefaulted(TiffTag.PHOTOMETRIC);
            Photometric input_photometric = (Photometric)result[0].ToShort();
    
            if (input_compression == Compression.JPEG)
            {
                /* Force conversion to RGB */
                inImage.SetField(TiffTag.JPEGCOLORMODE, JpegColorMode.RGB);
            }
            else if (input_photometric == Photometric.YCBCR)
            {
                /* Otherwise, can't handle subsampled input */
                result = inImage.GetFieldDefaulted(TiffTag.YCBCRSUBSAMPLING);
                short subsamplinghor = result[0].ToShort();
                short subsamplingver = result[1].ToShort();

                if (subsamplinghor != 1 || subsamplingver != 1)
                {
                    Console.Error.WriteLine("tiffcp: {0}: Can't copy/convert subsampled image.", inImage.FileName());
                    return false;
                }
            }

            if (m_compression == Compression.JPEG)
            {
                if (input_photometric == Photometric.RGB && m_jpegcolormode == JpegColorMode.RGB)
                    outImage.SetField(TiffTag.PHOTOMETRIC, Photometric.YCBCR);
                else
                    outImage.SetField(TiffTag.PHOTOMETRIC, input_photometric);
            }
            else if (m_compression == Compression.SGILOG || m_compression == Compression.SGILOG24)
            {
                outImage.SetField(TiffTag.PHOTOMETRIC, samplesperpixel == 1 ? Photometric.LOGL : Photometric.LOGLUV);
            }
            else
            {
                if (input_compression != Compression.JPEG)
                    copyTag(inImage, outImage, TiffTag.PHOTOMETRIC, 1, TiffType.SHORT);
            }

            if (m_fillorder != 0)
                outImage.SetField(TiffTag.FILLORDER, m_fillorder);
            else
                copyTag(inImage, outImage, TiffTag.FILLORDER, 1, TiffType.SHORT);

            /*
             * Will copy `Orientation' tag from input image
             */
            result = inImage.GetFieldDefaulted(TiffTag.ORIENTATION);
            m_orientation = (Orientation)result[0].ToByte();
            switch (m_orientation)
            {
                case Orientation.BOTRIGHT:
                case Orientation.RIGHTBOT:
                    Tiff.Warning(inImage.FileName(), "using bottom-left orientation");
                    m_orientation = Orientation.BOTLEFT;
                    break;

                case Orientation.LEFTBOT:
                case Orientation.BOTLEFT:
                    break;

                case Orientation.TOPRIGHT:
                case Orientation.RIGHTTOP:
                default:
                    Tiff.Warning(inImage.FileName(), "using top-left orientation");
                    m_orientation = Orientation.TOPLEFT;
                    break;

                case Orientation.LEFTTOP:
                case Orientation.TOPLEFT:
                    break;
            }

            outImage.SetField(TiffTag.ORIENTATION, m_orientation);

            /*
             * Choose tiles/strip for the output image according to
             * the command line arguments (-tiles, -strips) and the
             * structure of the input image.
             */
            if (m_outtiled == -1)
            {
                if (inImage.IsTiled())
                    m_outtiled = 1;
                else
                    m_outtiled = 0;
            }

            if (m_outtiled != 0)
            {
                /*
                 * Setup output file's tile width&height.  If either
                 * is not specified, use either the value from the
                 * input image or, if nothing is defined, use the
                 * library default.
                 */
                if (m_tilewidth == -1)
                {
                    result = inImage.GetFieldDefaulted(TiffTag.TILEWIDTH);
                    if (result != null)
                        m_tilewidth = result[0].ToInt();
                }

                if (m_tilelength == -1)
                {
                    result = inImage.GetFieldDefaulted(TiffTag.TILELENGTH);
                    if (result != null)
                        m_tilelength = result[0].ToInt();
                }

                outImage.DefaultTileSize(ref m_tilewidth, ref m_tilelength);
                outImage.SetField(TiffTag.TILEWIDTH, m_tilewidth);
                outImage.SetField(TiffTag.TILELENGTH, m_tilelength);
            }
            else
            {
                /*
                 * RowsPerStrip is left unspecified: use either the
                 * value from the input image or, if nothing is defined,
                 * use the library default.
                 */
                if (m_rowsperstrip == 0)
                {
                    result = inImage.GetField(TiffTag.ROWSPERSTRIP);
                    if (result == null)
                        m_rowsperstrip = outImage.DefaultStripSize(m_rowsperstrip);
                    else
                        m_rowsperstrip = result[0].ToInt();

                    if (m_rowsperstrip > length && m_rowsperstrip != -1)
                        m_rowsperstrip = length;
                }
                else if (m_rowsperstrip == -1)
                    m_rowsperstrip = length;

                outImage.SetField(TiffTag.ROWSPERSTRIP, m_rowsperstrip);
            }

            if (m_config != PlanarConfig.UNKNOWN)
                outImage.SetField(TiffTag.PLANARCONFIG, m_config);
            else
            {
                result = inImage.GetField(TiffTag.PLANARCONFIG);
                if (result != null)
                {
                    m_config = (PlanarConfig)result[0].ToShort();
                    outImage.SetField(TiffTag.PLANARCONFIG, m_config);
                }
            }

            if (samplesperpixel <= 4)
                copyTag(inImage, outImage, TiffTag.TRANSFERFUNCTION, 4, TiffType.SHORT);

            copyTag(inImage, outImage, TiffTag.COLORMAP, 4, TiffType.SHORT);

            /* SMinSampleValue & SMaxSampleValue */
            switch (m_compression)
            {
                case Compression.JPEG:
                    outImage.SetField(TiffTag.JPEGQUALITY, m_quality);
                    outImage.SetField(TiffTag.JPEGCOLORMODE, m_jpegcolormode);
                    break;
                case Compression.LZW:
                case Compression.ADOBE_DEFLATE:
                case Compression.DEFLATE:
                    if (m_predictor != -1)
                        outImage.SetField(TiffTag.PREDICTOR, m_predictor);
                    else
                    {
                        result = inImage.GetField(TiffTag.PREDICTOR);
                        if (result != null)
                        {
                            m_predictor = result[0].ToShort();
                            outImage.SetField(TiffTag.PREDICTOR, m_predictor);
                        }
                    }
                    break;
                case Compression.CCITTFAX3:
                case Compression.CCITTFAX4:
                    if (m_compression == Compression.CCITTFAX3)
                    {
                        if (m_g3opts != Group3Opt.UNKNOWN)
                            outImage.SetField(TiffTag.GROUP3OPTIONS, m_g3opts);
                        else
                        {
                            result = inImage.GetField(TiffTag.GROUP3OPTIONS);
                            if (result != null)
                            {
                                m_g3opts = (Group3Opt)result[0].ToShort();
                                outImage.SetField(TiffTag.GROUP3OPTIONS, m_g3opts);
                            }
                        }
                    }
                    else
                        copyTag(inImage, outImage, TiffTag.GROUP4OPTIONS, 1, TiffType.LONG);

                    copyTag(inImage, outImage, TiffTag.BADFAXLINES, 1, TiffType.LONG);
                    copyTag(inImage, outImage, TiffTag.CLEANFAXDATA, 1, TiffType.LONG);
                    copyTag(inImage, outImage, TiffTag.CONSECUTIVEBADFAXLINES, 1, TiffType.LONG);
                    copyTag(inImage, outImage, TiffTag.FAXRECVPARAMS, 1, TiffType.LONG);
                    copyTag(inImage, outImage, TiffTag.FAXRECVTIME, 1, TiffType.LONG);
                    copyTag(inImage, outImage, TiffTag.FAXSUBADDRESS, 1, TiffType.ASCII);
                    break;
            }

            result = inImage.GetField(TiffTag.ICCPROFILE);
            if (result != null)
                outImage.SetField(TiffTag.ICCPROFILE, result[0], result[1]);

            result = inImage.GetField(TiffTag.NUMBEROFINKS);
            if (result != null)
            {
                short ninks = result[0].ToShort();
                outImage.SetField(TiffTag.NUMBEROFINKS, ninks);

                result = inImage.GetField(TiffTag.INKNAMES);
                if (result != null)
                {
                    string inknames = result[0].ToString();
                    string[] parts = inknames.Split(new char[] { '\0' });

                    int inknameslen = 0;
                    foreach (string part in parts)
                        inknameslen += part.Length + 1;

                    outImage.SetField(TiffTag.INKNAMES, inknameslen, inknames);
                }
            }

            result = inImage.GetField(TiffTag.PAGENUMBER);
            if (m_pageInSeq == 1)
            {
                if (m_pageNum < 0)
                {
                    /* only one input file */ 
                    if (result != null) 
                        outImage.SetField(TiffTag.PAGENUMBER, result[0], result[1]);
                }
                else
                {
                    outImage.SetField(TiffTag.PAGENUMBER, m_pageNum++, 0);
                }
            }
            else
            {
                if (result != null)
                {
                    if (m_pageNum < 0)
                    {
                        /* only one input file */
                        outImage.SetField(TiffTag.PAGENUMBER, result[0], result[1]);
                    }
                    else
                    {
                        outImage.SetField(TiffTag.PAGENUMBER, m_pageNum++, 0);
                    }
                }
            }

            int NTAGS = g_tags.Length;
            for (int i = 0; i < NTAGS; i++)
            {
                tagToCopy p = g_tags[i];
                copyTag(inImage, outImage, p.tag, p.count, p.type);
            }

            return pickFuncAndCopy(inImage, outImage, bitspersample, samplesperpixel, length, width);
        }
Example #27
0
        bool writeBufferToSeparateTiles(Tiff outImage, byte[] buf, int imagelength, int imagewidth, short spp)
        {
            byte[] obuf = new byte[outImage.TileSize()];

            FieldValue[] result = outImage.GetField(TiffTag.TILELENGTH);
            int tl = result[0].ToInt();

            result = outImage.GetField(TiffTag.TILEWIDTH);
            int tw = result[0].ToInt();

            result = outImage.GetField(TiffTag.BITSPERSAMPLE);
            short bps = result[0].ToShort();

            Debug.Assert(bps % 8 == 0);

            short bytes_per_sample = (short)(bps / 8);

            int imagew = outImage.ScanlineSize();
            int tilew = outImage.TileRowSize();
            int iimagew = outImage.RasterScanlineSize();
            int iskew = iimagew - tilew * spp;

            int bufp = 0;

            for (int row = 0; row < imagelength; row += tl)
            {
                int nrow = (row + tl > imagelength) ? imagelength - row : tl;
                int colb = 0;

                for (int col = 0; col < imagewidth; col += tw)
                {
                    for (short s = 0; s < spp; s++)
                    {
                        /*
                         * Tile is clipped horizontally.  Calculate
                         * visible portion and skewing factors.
                         */
                        if (colb + tilew > imagew)
                        {
                            int width = imagew - colb;
                            int oskew = tilew - width;

                            cpContigBufToSeparateBuf(obuf, buf, bufp + (colb * spp) + s, nrow, width / bytes_per_sample, oskew, (oskew * spp) + iskew, spp, bytes_per_sample);
                        }
                        else
                            cpContigBufToSeparateBuf(obuf, buf, bufp + (colb * spp) + s, nrow, m_tilewidth, 0, iskew, spp, bytes_per_sample);

                        if (outImage.WriteTile(obuf, col, row, 0, s) < 0)
                        {
                            Tiff.Error(outImage.FileName(), "Error, can't write tile at {0} {1} sample {2}", col, row, s);
                            return false;
                        }
                    }

                    colb += tilew;
                }

                bufp += nrow * iimagew;
            }

            return true;
        }
Example #28
0
        static bool writeBufferToSeparateStrips(Tiff outImage, byte[] buf, int imagelength, int imagewidth, short spp)
        {
            byte[] obuf = new byte[outImage.StripSize()];

            FieldValue[] result = outImage.GetFieldDefaulted(TiffTag.ROWSPERSTRIP);
            int rowsperstrip = result[0].ToInt();

            int rowsize = imagewidth * spp;
            int strip = 0;

            for (short s = 0; s < spp; s++)
            {
                for (int row = 0; row < imagelength; row += rowsperstrip)
                {
                    int nrows = (row + rowsperstrip > imagelength) ? imagelength - row : rowsperstrip;
                    int stripsize = outImage.VStripSize(nrows);

                    cpContigBufToSeparateBuf(obuf, buf, row * rowsize + s, nrows, imagewidth, 0, 0, spp, 1);
                    if (outImage.WriteEncodedStrip(strip++, obuf, stripsize) < 0)
                    {
                        Tiff.Error(outImage.FileName(), "Error, can't write strip {0}", strip - 1);
                        return false;
                    }
                }
            }

            return true;
        }
Example #29
0
        /// <summary>
        /// Invokes the library-wide error handling methods to (normally) write an error message
        /// to the <see cref="Console.Error"/>.
        /// </summary>
        /// <param name="tif">An instance of the <see cref="Tiff"/> class. Can be <c>null</c>.</param>
        /// <param name="method">The method where an error is detected.</param>
        /// <param name="format">A composite format string (see Remarks).</param>
        /// <param name="args">An object array that contains zero or more objects to format.</param>
        /// <remarks>
        /// <para>
        /// The <paramref name="format"/> is a composite format string that uses the same format as
        /// <see cref="O:System.String.Format"/> method. The <paramref name="method"/> parameter, if
        /// not <c>null</c>, is printed before the message; it typically is used to identify the
        /// method in which an error is detected.
        /// </para>
        /// <para>Applications that desire to capture control in the event of an error should use
        /// <see cref="SetErrorHandler"/> to override the default error and warning handler.
        /// </para>
        /// </remarks>
        /// <overloads>
        /// Invokes the library-wide error handling methods to (normally) write an error message
        /// to the <see cref="Console.Error"/>.
        /// </overloads>
        public static void Error(Tiff tif, string method, string format, params object[] args)
        {
            TiffErrorHandler errorHandler = getErrorHandler(tif);
            if (errorHandler == null)
                return;

            errorHandler.ErrorHandler(tif, method, format, args);
            errorHandler.ErrorHandlerExt(tif, null, method, format, args);
        }
Example #30
0
 /// <summary>
 /// Handles an error by writing it text to the <see cref="Console.Error"/>.
 /// </summary>
 /// <param name="tif">An instance of the <see cref="Tiff"/> class. Can be <c>null</c>.</param>
 /// <param name="clientData">A client data.</param>
 /// <param name="method">The method where an error is detected.</param>
 /// <param name="format">A composite format string (see Remarks).</param>
 /// <param name="args">An object array that contains zero or more objects to format.</param>
 /// <remarks><para>
 /// The <paramref name="format"/> is a composite format string that uses the same format as
 /// <see cref="O:System.String.Format"/> method. The <paramref name="method"/> parameter, if
 /// not <c>null</c>, is printed before the message; it typically is used to identify the
 /// method in which an error is detected.
 /// </para><para>
 /// The <paramref name="clientData"/> parameter can be anything. Its value and meaning is
 /// defined by an application and not the library.
 /// </para></remarks>
 public virtual void ErrorHandlerExt(Tiff tif, object clientData, string method, string format, params object[] args)
 {
 }
Example #31
0
        static bool cpImage(Tiff inImage, Tiff outImage, readFunc fin, writeFunc fout, int imagelength, int imagewidth, short spp)
        {
            bool status = false;

            int scanlinesize = inImage.RasterScanlineSize();
            int bytes = scanlinesize * imagelength;

            /*
             * XXX: Check for integer overflow.
             */
            if (scanlinesize != 0 && imagelength != 0 && (bytes / imagelength == scanlinesize))
            {
                byte[] buf = new byte[bytes];
                if (fin(inImage, buf, imagelength, imagewidth, spp))
                    status = fout(outImage, buf, imagelength, imagewidth, spp);
            }
            else
            {
                Tiff.Error(inImage.FileName(), "Error, no space for image buffer");
            }

            return status;
        }
Example #32
0
        /*
         * Separate -> separate by row for rows/strip change.
         */
        bool cpSeparate2SeparateByRow(Tiff inImage, Tiff outImage, int imagelength, int imagewidth, short spp)
        {
            byte[] buf = new byte[inImage.ScanlineSize()];

            for (short s = 0; s < spp; s++)
            {
                for (int row = 0; row < imagelength; row++)
                {
                    if (!inImage.ReadScanline(buf, row, s) && !m_ignore)
                    {
                        Tiff.Error(inImage.FileName(), "Error, can't read scanline {0}", row);
                        return false;
                    }

                    if (!outImage.WriteScanline(buf, row, s))
                    {
                        Tiff.Error(outImage.FileName(), "Error, can't write scanline {0}", row);
                        return false;
                    }
                }
            }

            return true;
        }
 /// <summary>
 /// Prints formatted description of the contents of the current directory to the
 /// specified stream using specified print (formatting) options.
 /// </summary>
 /// <param name="tif">An instance of the <see cref="Tiff"/> class.</param>
 /// <param name="stream">The stream to print to.</param>
 /// <param name="flags">The print (formatting) options.</param>
 public virtual void PrintDir(Tiff tif, Stream stream, TiffPrintFlags flags)
 {
 }
Example #34
0
        bool readSeparateTilesIntoBuffer(Tiff inImage, byte[] buf, int imagelength, int imagewidth, short spp)
        {
            byte[] tilebuf = new byte[inImage.TileSize()];

            FieldValue[] result = inImage.GetField(TiffTag.TILEWIDTH);
            int tw = result[0].ToInt();

            result = inImage.GetField(TiffTag.TILELENGTH);
            int tl = result[0].ToInt();

            result = inImage.GetField(TiffTag.BITSPERSAMPLE);
            short bps = result[0].ToShort();

            Debug.Assert(bps % 8 == 0);

            short bytes_per_sample = (short)(bps / 8);

            int imagew = inImage.RasterScanlineSize();
            int tilew = inImage.TileRowSize();
            int iskew = imagew - tilew * spp;

            int bufp = 0;

            for (int row = 0; row < imagelength; row += tl)
            {
                int nrow = (row + tl > imagelength) ? imagelength - row : tl;
                int colb = 0;

                for (int col = 0; col < imagewidth; col += tw)
                {
                    for (short s = 0; s < spp; s++)
                    {
                        if (inImage.ReadTile(tilebuf, 0, col, row, 0, s) < 0 && !m_ignore)
                        {
                            Tiff.Error(inImage.FileName(), "Error, can't read tile at {0} {1}, sample {2}", col, row, s);
                            return false;
                        }

                        /*
                         * Tile is clipped horizontally.  Calculate
                         * visible portion and skewing factors.
                         */
                        if (colb + tilew * spp > imagew)
                        {
                            int width = imagew - colb;
                            int oskew = tilew * spp - width;
                            cpSeparateBufToContigBuf(buf, bufp + colb + s * bytes_per_sample, tilebuf, nrow, width / (spp * bytes_per_sample), oskew + iskew, oskew / spp, spp, bytes_per_sample);
                        }
                        else
                            cpSeparateBufToContigBuf(buf, bufp + colb + s * bytes_per_sample, tilebuf, nrow, tw, iskew, 0, spp, bytes_per_sample);
                    }

                    colb += tilew * spp;
                }

                bufp += imagew * nrow;
            }

            return true;
        }
Example #35
0
        static bool writeBufferToContigStrips(Tiff outImage, byte[] buffer, int imagelength, int imagewidth, short spp)
        {
            FieldValue[] result = outImage.GetFieldDefaulted(TiffTag.ROWSPERSTRIP);
            int rowsperstrip = result[0].ToInt();

            int strip = 0;
            int offset = 0;
            for (int row = 0; row < imagelength; row += rowsperstrip)
            {
                int nrows = (row + rowsperstrip > imagelength) ? imagelength - row : rowsperstrip;
                int stripsize = outImage.VStripSize(nrows);

                if (outImage.WriteEncodedStrip(strip++, buffer, offset, stripsize) < 0)
                {
                    Tiff.Error(outImage.FileName(), "Error, can't write strip {0}", strip - 1);
                    return false;
                }

                offset += stripsize;
            }

            return true;
        }
Example #36
0
        /// <summary>
        /// Invokes the library-wide warning handling methods to (normally) write a warning message
        /// to the <see cref="Console.Error"/> and passes client data to the warning handler.
        /// </summary>
        /// <param name="tif">An instance of the <see cref="Tiff"/> class. Can be <c>null</c>.</param>
        /// <param name="clientData">The client data to be passed to warning handler.</param>
        /// <param name="method">The method in which a warning is detected.</param>
        /// <param name="format">A composite format string (see Remarks).</param>
        /// <param name="args">An object array that contains zero or more objects to format.</param>
        /// <remarks>
        /// <para>
        /// The <paramref name="format"/> is a composite format string that uses the same format as
        /// <see cref="O:System.String.Format"/> method. The <paramref name="method"/> parameter, if
        /// not <c>null</c>, is printed before the message; it typically is used to identify the
        /// method in which a warning is detected.
        /// </para>
        /// <para>
        /// The <paramref name="clientData"/> parameter can be anything you want. It will be passed
        /// unchanged to the warning handler. Default warning handler does not use it. Only custom
        /// warning handlers may make use of it.
        /// </para>
        /// <para>Applications that desire to capture control in the event of a warning should use
        /// <see cref="SetErrorHandler"/> to override the default error and warning handler.
        /// </para>
        /// </remarks>
        /// <overloads>
        /// Invokes the library-wide warning handling methods to (normally) write a warning message
        /// to the <see cref="Console.Error"/> and passes client data to the warning handler.
        /// </overloads>
        public static void WarningExt(Tiff tif, object clientData, string method, string format, params object[] args)
        {
            TiffErrorHandler errorHandler = getErrorHandler(tif);
            if (errorHandler == null)
                return;

            errorHandler.WarningHandler(tif, method, format, args);
            errorHandler.WarningHandlerExt(tif, clientData, method, format, args);
        }
Example #37
0
        bool writeBufferToContigTiles(Tiff outImage, byte[] buf, int imagelength, int imagewidth, short spp)
        {
            byte[] obuf = new byte[outImage.TileSize()];

            FieldValue[] result = outImage.GetField(TiffTag.TILELENGTH);
            int tl = result[0].ToInt();

            result = outImage.GetField(TiffTag.TILEWIDTH);
            int tw = result[0].ToInt();

            int imagew = outImage.ScanlineSize();
            int tilew = outImage.TileRowSize();
            int iskew = imagew - tilew;

            int bufp = 0;

            for (int row = 0; row < imagelength; row += m_tilelength)
            {
                int nrow = (row + tl > imagelength) ? imagelength - row : tl;
                int colb = 0;

                for (int col = 0; col < imagewidth; col += tw)
                {
                    /*
                     * Tile is clipped horizontally.  Calculate
                     * visible portion and skewing factors.
                     */
                    if (colb + tilew > imagew)
                    {
                        int width = imagew - colb;
                        int oskew = tilew - width;
                        cpStripToTile(obuf, 0, buf, bufp + colb, nrow, width, oskew, oskew + iskew);
                    }
                    else
                        cpStripToTile(obuf, 0, buf, bufp + colb, nrow, tilew, 0, iskew);

                    if (outImage.WriteTile(obuf, col, row, 0, 0) < 0)
                    {
                        Tiff.Error(outImage.FileName(), "Error, can't write tile at {0} {1}", col, row);
                        return false;
                    }

                    colb += tilew;
                }

                bufp += nrow * imagew;
            }

            return true;
        }
        static Tiff ClientOpen(string name, string mode, Stream clientData, TiffStream stream, TiffErrorHandler errorHandler, TiffExtendProc extender)
        {
            const string module = "ClientOpen";

            if (mode == null || mode.Length == 0)
            {
                ErrorExt(null, clientData, module, "{0}: mode string should contain at least one char", name);
                return(null);
            }

            int m = getMode(mode, module);

            Tiff tif = new Tiff();

#if THREAD_SAFE_LIBTIFF
            if (errorHandler != null)
            {
                tif.m_errorHandler = errorHandler;
            }
            if (extender != null)
            {
                tif.m_extender = extender;
            }
#endif
            tif.m_name = name;

            tif.m_mode       = m & ~(O_CREAT | O_TRUNC);
            tif.m_curdir     = -1; // non-existent directory
            tif.m_curoff     = 0;
            tif.m_curstrip   = -1; // invalid strip
            tif.m_row        = -1; // read/write pre-increment
            tif.m_clientdata = clientData;

            if (stream == null)
            {
                ErrorExt(tif, clientData, module, "TiffStream is null pointer.");
                return(null);
            }

            tif.m_stream = stream;

            // setup default state
            tif.m_currentCodec = tif.m_builtInCodecs[0];

            // Default is to return data MSB2LSB and enable the use of
            // strip chopping when a file is opened read-only.
            tif.m_flags = TiffFlags.MSB2LSB;

            if (m == O_RDONLY || m == O_RDWR)
            {
                tif.m_flags |= STRIPCHOP_DEFAULT;
            }

            // Process library-specific flags in the open mode string.
            // See remarks for Open method for the list of supported flags.
            int modelength = mode.Length;
            for (int i = 0; i < modelength; i++)
            {
                switch (mode[i])
                {
                case 'b':
                    if ((m & O_CREAT) != 0)
                    {
                        tif.m_flags |= TiffFlags.SWAB;
                    }
                    break;

                case 'l':
                    break;

                case 'B':
                    tif.m_flags = (tif.m_flags & ~TiffFlags.FILLORDER) | TiffFlags.MSB2LSB;
                    break;

                case 'L':
                    tif.m_flags = (tif.m_flags & ~TiffFlags.FILLORDER) | TiffFlags.LSB2MSB;
                    break;

                case 'H':
                    tif.m_flags = (tif.m_flags & ~TiffFlags.FILLORDER) | TiffFlags.LSB2MSB;
                    break;

                case 'C':
                    if (m == O_RDONLY)
                    {
                        tif.m_flags |= TiffFlags.STRIPCHOP;
                    }
                    break;

                case 'c':
                    if (m == O_RDONLY)
                    {
                        tif.m_flags &= ~TiffFlags.STRIPCHOP;
                    }
                    break;

                case 'h':
                    tif.m_flags |= TiffFlags.HEADERONLY;
                    break;

                case '4':
                    tif.m_flags |= TiffFlags.NOBIGTIFF;
                    break;

                case '8':
                    tif.m_flags |= TiffFlags.ISBIGTIFF;
                    break;
                }
            }

            // Read in TIFF header.

            if ((tif.m_mode & O_TRUNC) != 0 || !tif.readHeaderOk(ref tif.m_header))
            {
                if (tif.m_mode == O_RDONLY)
                {
                    ErrorExt(tif, tif.m_clientdata, name, "Cannot read TIFF header");
                    return(null);
                }

                // Setup header and write.

                if ((tif.m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
                {
                    tif.m_header.tiff_magic = TIFF_BIGENDIAN;
                }
                else
                {
                    tif.m_header.tiff_magic = TIFF_LITTLEENDIAN;
                }


                if ((tif.m_flags & TiffFlags.ISBIGTIFF) == TiffFlags.ISBIGTIFF)
                {
                    tif.m_header.tiff_version = TIFF_BIGTIFF_VERSION;
                    tif.m_header.tiff_diroff  = 0; //filled in later
                    tif.m_header.tiff_fill    = 0;
                    tif.m_header.tiff_offsize = sizeof(long);
                    if ((tif.m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
                    {
                        SwabShort(ref tif.m_header.tiff_version);
                        SwabShort(ref tif.m_header.tiff_offsize);
                    }
                }
                else
                {
                    tif.m_header.tiff_version = TIFF_VERSION;
                    tif.m_header.tiff_diroff  = 0; //filled in later
                    tif.m_header.tiff_fill    = sizeof(long);
                    if ((tif.m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
                    {
                        SwabShort(ref tif.m_header.tiff_version);
                    }
                }

                tif.seekFile(0, SeekOrigin.Begin);

                if (!tif.writeHeaderOK(tif.m_header))
                {
                    ErrorExt(tif, tif.m_clientdata, name, "Error writing TIFF header");
                    tif.m_mode = O_RDONLY;
                    return(null);
                }

                // Setup the byte order handling.
                tif.initOrder(tif.m_header.tiff_magic);

                // Setup default directory.
                tif.setupDefaultDirectory();
                tif.m_diroff      = 0;
                tif.m_dirlist     = null;
                tif.m_dirlistsize = 0;
                tif.m_dirnumber   = 0;
                return(tif);
            }

            // Setup the byte order handling.
            if (tif.m_header.tiff_magic != TIFF_BIGENDIAN &&
                tif.m_header.tiff_magic != TIFF_LITTLEENDIAN &&
                tif.m_header.tiff_magic != MDI_LITTLEENDIAN)
            {
                ErrorExt(tif, tif.m_clientdata, name,
                         "Not a TIFF or MDI file, bad magic number {0} (0x{1:x})",
                         tif.m_header.tiff_magic, tif.m_header.tiff_magic);
                tif.m_mode = O_RDONLY;
                return(null);
            }

            tif.initOrder(tif.m_header.tiff_magic);

            // Swap header if required.
            if ((tif.m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
            {
                SwabShort(ref tif.m_header.tiff_version);
                SwabBigTiffValue(ref tif.m_header.tiff_diroff, tif.m_header.tiff_version == TIFF_BIGTIFF_VERSION, false);
            }

            // Now check version (if needed, it's been byte-swapped).
            // Note that this isn't actually a version number, it's a
            // magic number that doesn't change (stupid).
            if (tif.m_header.tiff_version == TIFF_BIGTIFF_VERSION)
            {
                if ((tif.m_flags & TiffFlags.NOBIGTIFF) == TiffFlags.NOBIGTIFF)
                {
                    ErrorExt(tif, tif.m_clientdata, name,
                             "This is a BigTIFF file. Non-BigTIFF mode '32' is forced");
                    tif.m_mode = O_RDONLY;
                    return(null);
                }
            }
            if (tif.m_header.tiff_version == TIFF_VERSION)
            {
                if ((tif.m_flags & TiffFlags.ISBIGTIFF) == TiffFlags.ISBIGTIFF)
                {
                    ErrorExt(tif, tif.m_clientdata, name,
                             "This is a non-BigTIFF file. BigTIFF mode '64' is forced");
                    tif.m_mode = O_RDONLY;
                    return(null);
                }
            }
            if (tif.m_header.tiff_version != TIFF_VERSION && tif.m_header.tiff_version != TIFF_BIGTIFF_VERSION)
            {
                ErrorExt(tif, tif.m_clientdata, name,
                         "Not a TIFF file, bad version number {0} (0x{1:x})",
                         tif.m_header.tiff_version, tif.m_header.tiff_version);
                tif.m_mode = O_RDONLY;
                return(null);
            }

            tif.m_flags      |= TiffFlags.MYBUFFER;
            tif.m_rawcp       = 0;
            tif.m_rawdata     = null;
            tif.m_rawdatasize = 0;

            // Sometimes we do not want to read the first directory (for example,
            // it may be broken) and want to proceed to other directories. I this
            // case we use the HEADERONLY flag to open file and return
            // immediately after reading TIFF header.
            if ((tif.m_flags & TiffFlags.HEADERONLY) == TiffFlags.HEADERONLY)
            {
                return(tif);
            }

            // Setup initial directory.
            switch (mode[0])
            {
            case 'r':
                tif.m_nextdiroff = tif.m_header.tiff_diroff;

                if (tif.ReadDirectory())
                {
                    tif.m_rawcc  = -1;
                    tif.m_flags |= TiffFlags.BUFFERSETUP;
                    return(tif);
                }
                break;

            case 'a':
                // New directories are automatically append to the end of
                // the directory chain when they are written out (see WriteDirectory).
                tif.setupDefaultDirectory();
                return(tif);
            }

            tif.m_mode = O_RDONLY;
            return(null);
        }
Example #39
0
 private static void copyTag(Tiff inImage, Tiff outImage, TiffTag tag, short count, TiffType type)
 {
     FieldValue[] result = null;
     switch (type)
     {
         case TiffType.SHORT:
             result = inImage.GetField(tag);
             if (result != null)
             {
                 if (count == 1)
                     outImage.SetField(tag, result[0]);
                 else if (count == 2)
                     outImage.SetField(tag, result[0], result[1]);
                 else if (count == 4)
                     outImage.SetField(tag, result[0], result[1], result[2]);
                 else if (count == -1)
                     outImage.SetField(tag, result[0], result[1]);
             }
             break;
         case TiffType.LONG:
             result = inImage.GetField(tag);
             if (result != null)
                 outImage.SetField(tag, result[0]);
             break;
         case TiffType.RATIONAL:
             result = inImage.GetField(tag);
             if (result != null)
                 outImage.SetField(tag, result[0]);
             break;
         case TiffType.ASCII:
             result = inImage.GetField(tag);
             if (result != null)
                 outImage.SetField(tag, result[0]);
             break;
         case TiffType.DOUBLE:
             result = inImage.GetField(tag);
             if (result != null)
                 outImage.SetField(tag, result[0]);
             break;
         default:
             Tiff.Error(inImage.FileName(),
                 "Data type {0} is not supported, tag {1} skipped.", tag, type);
             break;
     }
 }
Example #40
0
 static Tiff Open(string fileName, string mode, TiffErrorHandler errorHandler)
 {
     return(Tiff.Open(fileName, mode, errorHandler, null));
 }
Example #41
0
        /*
         * Select the appropriate copy function to use.
         */
        bool pickFuncAndCopy(Tiff inImage, Tiff outImage, short bitspersample, short samplesperpixel, int length, int width)
        {
            using (TextWriter stderr = Console.Error)
            {
                FieldValue[] result = inImage.GetField(TiffTag.PLANARCONFIG);
                PlanarConfig shortv = (PlanarConfig)result[0].ToShort();

                if (shortv != m_config && bitspersample != 8 && samplesperpixel > 1)
                {
                    stderr.Write("{0}: Cannot handle different planar configuration w/ bits/sample != 8\n", inImage.FileName());
                    return false;
                }

                result = inImage.GetField(TiffTag.IMAGEWIDTH);
                int w = result[0].ToInt();

                result = inImage.GetField(TiffTag.IMAGELENGTH);
                int l = result[0].ToInt();

                bool bychunk;
                if (!(outImage.IsTiled() || inImage.IsTiled()))
                {
                    result = inImage.GetField(TiffTag.ROWSPERSTRIP);
                    if (result != null)
                    {
                        int irps = result[0].ToInt();

                        /* if biased, force decoded copying to allow image subtraction */
                        bychunk = (m_bias == null) && (m_rowsperstrip == irps);
                    }
                    else
                        bychunk = false;
                }
                else
                {
                    /* either inImage or outImage is tiled */
                    if (m_bias != null)
                    {
                        stderr.Write("{0}: Cannot handle tiled configuration w/bias image\n", inImage.FileName());
                        return false;
                    }

                    if (outImage.IsTiled())
                    {
                        int tw;
                        result = inImage.GetField(TiffTag.TILEWIDTH);
                        if (result == null)
                            tw = w;
                        else
                            tw = result[0].ToInt();

                        int tl;
                        result = inImage.GetField(TiffTag.TILELENGTH);
                        if (result == null)
                            tl = l;
                        else
                            tl = result[0].ToInt();

                        bychunk = (tw == m_tilewidth && tl == m_tilelength);
                    }
                    else
                    {
                        /* outImage's not, so inImage must be tiled */
                        result = inImage.GetField(TiffTag.TILEWIDTH);
                        int tw = result[0].ToInt();

                        result = inImage.GetField(TiffTag.TILELENGTH);
                        int tl = result[0].ToInt();

                        bychunk = (tw == w && tl == m_rowsperstrip);
                    }
                }

                if (inImage.IsTiled())
                {
                    if (outImage.IsTiled())
                    {
                        /* Tiles -> Tiles */
                        if (shortv == PlanarConfig.CONTIG && m_config == PlanarConfig.CONTIG)
                            return cpContigTiles2ContigTiles(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.CONTIG && m_config == PlanarConfig.SEPARATE)
                            return cpContigTiles2SeparateTiles(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.SEPARATE && m_config == PlanarConfig.CONTIG)
                            return cpSeparateTiles2ContigTiles(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.SEPARATE && m_config == PlanarConfig.SEPARATE)
                            return cpSeparateTiles2SeparateTiles(inImage, outImage, length, width, samplesperpixel);
                    }
                    else
                    {
                        /* Tiles -> Strips */
                        if (shortv == PlanarConfig.CONTIG && m_config == PlanarConfig.CONTIG)
                            return cpContigTiles2ContigStrips(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.CONTIG && m_config == PlanarConfig.SEPARATE)
                            return cpContigTiles2SeparateStrips(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.SEPARATE && m_config == PlanarConfig.CONTIG)
                            return cpSeparateTiles2ContigStrips(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.SEPARATE && m_config == PlanarConfig.SEPARATE)
                            return cpSeparateTiles2SeparateStrips(inImage, outImage, length, width, samplesperpixel);
                    }
                }
                else
                {
                    if (outImage.IsTiled())
                    {
                        /* Strips -> Tiles */
                        if (shortv == PlanarConfig.CONTIG && m_config == PlanarConfig.CONTIG)
                            return cpContigStrips2ContigTiles(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.CONTIG && m_config == PlanarConfig.SEPARATE)
                            return cpContigStrips2SeparateTiles(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.SEPARATE && m_config == PlanarConfig.CONTIG)
                            return cpSeparateStrips2ContigTiles(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.SEPARATE && m_config == PlanarConfig.SEPARATE)
                            return cpSeparateStrips2SeparateTiles(inImage, outImage, length, width, samplesperpixel);
                    }
                    else
                    {
                        /* Strips -> Strips */
                        if (shortv == PlanarConfig.CONTIG && m_config == PlanarConfig.CONTIG && !bychunk)
                        {
                            if (m_bias != null)
                                return cpBiasedContig2Contig(inImage, outImage, length, width, samplesperpixel);

                            return cpContig2ContigByRow(inImage, outImage, length, width, samplesperpixel);
                        }
                        else if (shortv == PlanarConfig.CONTIG && m_config == PlanarConfig.CONTIG && bychunk)
                            return cpDecodedStrips(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.CONTIG && m_config == PlanarConfig.SEPARATE)
                            return cpContig2SeparateByRow(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.SEPARATE && m_config == PlanarConfig.CONTIG)
                            return cpSeparate2ContigByRow(inImage, outImage, length, width, samplesperpixel);
                        else if (shortv == PlanarConfig.SEPARATE && m_config == PlanarConfig.SEPARATE)
                            return cpSeparate2SeparateByRow(inImage, outImage, length, width, samplesperpixel);
                    }
                }

                stderr.Write("tiffcp: {0}: Don't know how to copy/convert image.\n", inImage.FileName());
            }

            return false;
        }
Example #42
0
        bool readContigStripsIntoBuffer(Tiff inImage, byte[] buffer, int imagelength, int imagewidth, short spp)
        {
            int scanlinesize = inImage.ScanlineSize();
            int offset = 0;

            for (int row = 0; row < imagelength; row++)
            {
                if (!inImage.ReadScanline(buffer, offset, row, 0) && !m_ignore)
                {
                    Tiff.Error(inImage.FileName(), "Error, can't read scanline {0}", row);
                    return false;
                }

                offset += scanlinesize;
            }

            return true;
        }
Example #43
0
        /*
         * Strip -> strip for change in encoding.
         */
        bool cpDecodedStrips(Tiff inImage, Tiff outImage, int imagelength, int imagewidth, short spp)
        {
            int stripsize = inImage.StripSize();
            byte[] buf = new byte[stripsize];
            int ns = inImage.NumberOfStrips();
            int row = 0;
            for (int s = 0; s < ns; s++)
            {
                int cc = (row + m_rowsperstrip > imagelength) ? inImage.VStripSize(imagelength - row) : stripsize;
                if (inImage.ReadEncodedStrip(s, buf, 0, cc) < 0 && !m_ignore)
                {
                    Tiff.Error(inImage.FileName(), "Error, can't read strip {0}", s);
                    return false;
                }

                if (outImage.WriteEncodedStrip(s, buf, cc) < 0)
                {
                    Tiff.Error(outImage.FileName(), "Error, can't write strip {0}", s);
                    return false;
                }

                row += m_rowsperstrip;
            }

            return true;
        }
Example #44
0
 /// <summary>
 /// Handles an error by writing it text to the <see cref="Console.Error"/>.
 /// </summary>
 /// <param name="tif">An instance of the <see cref="Tiff"/> class. Can be <c>null</c>.</param>
 /// <param name="clientData">A client data.</param>
 /// <param name="method">The method where an error is detected.</param>
 /// <param name="format">A composite format string (see Remarks).</param>
 /// <param name="args">An object array that contains zero or more objects to format.</param>
 /// <remarks><para>
 /// The <paramref name="format"/> is a composite format string that uses the same format as
 /// <see cref="O:System.String.Format"/> method. The <paramref name="method"/> parameter, if
 /// not <c>null</c>, is printed before the message; it typically is used to identify the
 /// method in which an error is detected.
 /// </para><para>
 /// The <paramref name="clientData"/> parameter can be anything. Its value and meaning is
 /// defined by an application and not the library.
 /// </para></remarks>
 public virtual void ErrorHandlerExt(Tiff tif, object clientData, string method, string format, params object[] args)
 {
 }
Example #45
0
        /*
         * Separate -> contig by row.
         */
        bool cpSeparate2ContigByRow(Tiff inImage, Tiff outImage, int imagelength, int imagewidth, short spp)
        {
            byte[] inbuf = new byte[inImage.ScanlineSize()];
            byte[] outbuf = new byte[outImage.ScanlineSize()];

            for (int row = 0; row < imagelength; row++)
            {
                /* merge channels */
                for (short s = 0; s < spp; s++)
                {
                    if (!inImage.ReadScanline(inbuf, row, s) && !m_ignore)
                    {
                        Tiff.Error(inImage.FileName(), "Error, can't read scanline {0}", row);
                        return false;
                    }

                    int inp = 0;
                    int outp = s;

                    for (int n = imagewidth; n-- > 0; )
                    {
                        outbuf[outp] = inbuf[inp];
                        inp++;
                        outp += spp;
                    }
                }

                if (!outImage.WriteScanline(outbuf, row, 0))
                {
                    Tiff.Error(outImage.FileName(), "Error, can't write scanline {0}", row);
                    return false;
                }
            }

            return true;
        }
        /// <summary>
        /// Sets the value(s) of a tag in a TIFF file/stream open for writing.
        /// </summary>
        /// <param name="tif">An instance of the <see cref="Tiff"/> class.</param>
        /// <param name="tag">The tag.</param>
        /// <param name="value">The tag value(s).</param>
        /// <returns>
        /// <c>true</c> if tag value(s) were set successfully; otherwise, <c>false</c>.
        /// </returns>
        /// <seealso cref="Tiff.SetField"/>
        public virtual bool SetField(Tiff tif, TiffTag tag, FieldValue[] value)
        {
            const string module = "vsetfield";

            TiffDirectory td     = tif.m_dir;
            bool          status = true;
            int           v32    = 0;
            int           v      = 0;

            bool end        = false;
            bool badvalue   = false;
            bool badvalue32 = false;

            switch (tag)
            {
            case TiffTag.SUBFILETYPE:
                td.td_subfiletype = (FileType)value[0].ToByte();
                break;

            case TiffTag.IMAGEWIDTH:
                td.td_imagewidth = value[0].ToInt();
                break;

            case TiffTag.IMAGELENGTH:
                td.td_imagelength = value[0].ToInt();
                break;

            case TiffTag.BITSPERSAMPLE:
                td.td_bitspersample = value[0].ToShort();
                // If the data require post-decoding processing to byte-swap samples, set it
                // up here. Note that since tags are required to be ordered, compression code
                // can override this behavior in the setup method if it wants to roll the post
                // decoding work in with its normal work.
                if ((tif.m_flags & TiffFlags.SWAB) == TiffFlags.SWAB)
                {
                    switch (td.td_bitspersample)
                    {
                    case 16:
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab16Bit;
                        break;

                    case 24:
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab24Bit;
                        break;

                    case 32:
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab32Bit;
                        break;

                    case 64:
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab64Bit;
                        break;

                    case 128:
                        // two 64's
                        tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab64Bit;
                        break;
                    }
                }
                break;

            case TiffTag.COMPRESSION:
                v = value[0].ToInt() & 0xffff;
                Compression comp = (Compression)v;
                // If we're changing the compression scheme, then notify the previous module
                // so that it can cleanup any state it's setup.
                if (tif.fieldSet(FieldBit.Compression))
                {
                    if (td.td_compression == comp)
                    {
                        break;
                    }

                    tif.m_currentCodec.Cleanup();
                    tif.m_flags &= ~TiffFlags.CODERSETUP;
                }
                // Setup new compression scheme.
                status = tif.setCompressionScheme(comp);
                if (status)
                {
                    td.td_compression = comp;
                }
                else
                {
                    status = false;
                }
                break;

            case TiffTag.PHOTOMETRIC:
                td.td_photometric = (Photometric)value[0].ToInt();
                break;

            case TiffTag.THRESHHOLDING:
                td.td_threshholding = (Threshold)value[0].ToByte();
                break;

            case TiffTag.FILLORDER:
                v = value[0].ToInt();
                FillOrder fo = (FillOrder)v;
                if (fo != FillOrder.LSB2MSB && fo != FillOrder.MSB2LSB)
                {
                    badvalue = true;
                    break;
                }

                td.td_fillorder = fo;
                break;

            case TiffTag.ORIENTATION:
                v = value[0].ToInt();
                Orientation or = (Orientation)v;
                if (or < Orientation.TOPLEFT || Orientation.LEFTBOT < or)
                {
                    badvalue = true;
                    break;
                }
                else
                {
                    td.td_orientation = or;
                }
                break;

            case TiffTag.SAMPLESPERPIXEL:
                // XXX should cross check - e.g. if pallette, then 1
                v = value[0].ToInt();
                if (v == 0)
                {
                    badvalue = true;
                    break;
                }

                td.td_samplesperpixel = (short)v;
                break;

            case TiffTag.ROWSPERSTRIP:
                v32 = value[0].ToInt();
                if (v32 == 0)
                {
                    badvalue32 = true;
                    break;
                }

                td.td_rowsperstrip = v32;
                if (!tif.fieldSet(FieldBit.TileDimensions))
                {
                    td.td_tilelength = v32;
                    td.td_tilewidth  = td.td_imagewidth;
                }
                break;

            case TiffTag.MINSAMPLEVALUE:
                td.td_minsamplevalue = value[0].ToUShort();
                break;

            case TiffTag.MAXSAMPLEVALUE:
                td.td_maxsamplevalue = value[0].ToUShort();
                break;

            case TiffTag.SMINSAMPLEVALUE:
                td.td_sminsamplevalue = value[0].ToDouble();
                break;

            case TiffTag.SMAXSAMPLEVALUE:
                td.td_smaxsamplevalue = value[0].ToDouble();
                break;

            case TiffTag.XRESOLUTION:
                td.td_xresolution = value[0].ToFloat();
                break;

            case TiffTag.YRESOLUTION:
                td.td_yresolution = value[0].ToFloat();
                break;

            case TiffTag.PLANARCONFIG:
                v = value[0].ToInt();
                PlanarConfig pc = (PlanarConfig)v;
                if (pc != PlanarConfig.CONTIG && pc != PlanarConfig.SEPARATE)
                {
                    badvalue = true;
                    break;
                }
                td.td_planarconfig = pc;
                break;

            case TiffTag.XPOSITION:
                td.td_xposition = value[0].ToFloat();
                break;

            case TiffTag.YPOSITION:
                td.td_yposition = value[0].ToFloat();
                break;

            case TiffTag.RESOLUTIONUNIT:
                v = value[0].ToInt();
                ResUnit ru = (ResUnit)v;
                if (ru < ResUnit.NONE || ResUnit.CENTIMETER < ru)
                {
                    badvalue = true;
                    break;
                }

                td.td_resolutionunit = ru;
                break;

            case TiffTag.PAGENUMBER:
                td.td_pagenumber[0] = value[0].ToShort();
                td.td_pagenumber[1] = value[1].ToShort();
                break;

            case TiffTag.HALFTONEHINTS:
                td.td_halftonehints[0] = value[0].ToShort();
                td.td_halftonehints[1] = value[1].ToShort();
                break;

            case TiffTag.COLORMAP:
                v32 = 1 << td.td_bitspersample;
                Tiff.setShortArray(out td.td_colormap[0], value[0].ToShortArray(), v32);
                Tiff.setShortArray(out td.td_colormap[1], value[1].ToShortArray(), v32);
                Tiff.setShortArray(out td.td_colormap[2], value[2].ToShortArray(), v32);
                break;

            case TiffTag.EXTRASAMPLES:
                if (!setExtraSamples(td, ref v, value))
                {
                    badvalue = true;
                    break;
                }

                break;

            case TiffTag.MATTEING:
                if (value[0].ToShort() != 0)
                {
                    td.td_extrasamples = 1;
                }
                else
                {
                    td.td_extrasamples = 0;
                }

                if (td.td_extrasamples != 0)
                {
                    td.td_sampleinfo    = new ExtraSample[1];
                    td.td_sampleinfo[0] = ExtraSample.ASSOCALPHA;
                }
                break;

            case TiffTag.TILEWIDTH:
                v32 = value[0].ToInt();
                if ((v32 % 16) != 0)
                {
                    if (tif.m_mode != Tiff.O_RDONLY)
                    {
                        badvalue32 = true;
                        break;
                    }

                    Tiff.WarningExt(tif, tif.m_clientdata, tif.m_name,
                                    "Nonstandard tile width {0}, convert file", v32);
                }
                td.td_tilewidth = v32;
                tif.m_flags    |= TiffFlags.ISTILED;
                break;

            case TiffTag.TILELENGTH:
                v32 = value[0].ToInt();
                if ((v32 % 16) != 0)
                {
                    if (tif.m_mode != Tiff.O_RDONLY)
                    {
                        badvalue32 = true;
                        break;
                    }

                    Tiff.WarningExt(tif, tif.m_clientdata, tif.m_name,
                                    "Nonstandard tile length {0}, convert file", v32);
                }
                td.td_tilelength = v32;
                tif.m_flags     |= TiffFlags.ISTILED;
                break;

            case TiffTag.TILEDEPTH:
                v32 = value[0].ToInt();
                if (v32 == 0)
                {
                    badvalue32 = true;
                    break;
                }

                td.td_tiledepth = v32;
                break;

            case TiffTag.DATATYPE:
                v = value[0].ToInt();
                SampleFormat sf = SampleFormat.VOID;
                switch (v)
                {
                case DATATYPE_VOID:
                    sf = SampleFormat.VOID;
                    break;

                case DATATYPE_INT:
                    sf = SampleFormat.INT;
                    break;

                case DATATYPE_UINT:
                    sf = SampleFormat.UINT;
                    break;

                case DATATYPE_IEEEFP:
                    sf = SampleFormat.IEEEFP;
                    break;

                default:
                    badvalue = true;
                    break;
                }

                if (!badvalue)
                {
                    td.td_sampleformat = sf;
                }

                break;

            case TiffTag.SAMPLEFORMAT:
                v  = value[0].ToInt();
                sf = (SampleFormat)v;
                if (sf < SampleFormat.UINT || SampleFormat.COMPLEXIEEEFP < sf)
                {
                    badvalue = true;
                    break;
                }

                td.td_sampleformat = sf;

                // Try to fix up the SWAB function for complex data.
                if (td.td_sampleformat == SampleFormat.COMPLEXINT &&
                    td.td_bitspersample == 32 && tif.m_postDecodeMethod == Tiff.PostDecodeMethodType.pdmSwab32Bit)
                {
                    tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab16Bit;
                }
                else if ((td.td_sampleformat == SampleFormat.COMPLEXINT ||
                          td.td_sampleformat == SampleFormat.COMPLEXIEEEFP) &&
                         td.td_bitspersample == 64 && tif.m_postDecodeMethod == Tiff.PostDecodeMethodType.pdmSwab64Bit)
                {
                    tif.m_postDecodeMethod = Tiff.PostDecodeMethodType.pdmSwab32Bit;
                }
                break;

            case TiffTag.IMAGEDEPTH:
                td.td_imagedepth = value[0].ToInt();
                break;

            case TiffTag.SUBIFD:
                if ((tif.m_flags & TiffFlags.INSUBIFD) != TiffFlags.INSUBIFD)
                {
                    td.td_nsubifd = value[0].ToInt();
                    Tiff.setLong8Array(out td.td_subifd, value[1].TolongArray(), td.td_nsubifd);
                }
                else
                {
                    Tiff.ErrorExt(tif, tif.m_clientdata, module,
                                  "{0}: Sorry, cannot nest SubIFDs", tif.m_name);
                    status = false;
                }
                break;

            case TiffTag.YCBCRPOSITIONING:
                td.td_ycbcrpositioning = (YCbCrPosition)value[0].ToShort();
                break;

            case TiffTag.YCBCRSUBSAMPLING:
                td.td_ycbcrsubsampling[0] = value[0].ToShort();
                td.td_ycbcrsubsampling[1] = value[1].ToShort();
                break;

            case TiffTag.TRANSFERFUNCTION:
                v = ((td.td_samplesperpixel - td.td_extrasamples) > 1 ? 3 : 1);
                for (int i = 0; i < v; i++)
                {
                    Tiff.setShortArray(out td.td_transferfunction[i], value[0].ToShortArray(), 1 << td.td_bitspersample);
                }
                break;

            case TiffTag.REFERENCEBLACKWHITE:
                // XXX should check for null range
                Tiff.setFloatArray(out td.td_refblackwhite, value[0].ToFloatArray(), 6);
                break;

            case TiffTag.INKNAMES:
                v = value[0].ToInt();
                string s = value[1].ToString();
                v      = checkInkNamesString(tif, v, s);
                status = v > 0;
                if (v > 0)
                {
                    setNString(out td.td_inknames, s, v);
                    td.td_inknameslen = v;
                }
                break;

            default:
                // This can happen if multiple images are open with
                // different codecs which have private tags. The global tag
                // information table may then have tags that are valid for
                // one file but not the other. If the client tries to set a
                // tag that is not valid for the image's codec then we'll
                // arrive here. This happens, for example, when tiffcp is
                // used to convert between compression schemes and
                // codec-specific tags are blindly copied.
                TiffFieldInfo fip = tif.FindFieldInfo(tag, TiffType.ANY);
                if (fip == null || fip.Bit != FieldBit.Custom)
                {
                    Tiff.ErrorExt(tif, tif.m_clientdata, module,
                                  "{0}: Invalid {1}tag \"{2}\" (not supported by codec)",
                                  tif.m_name, Tiff.isPseudoTag(tag) ? "pseudo-" : string.Empty,
                                  fip != null ? fip.Name : "Unknown");
                    status = false;
                    break;
                }

                // Find the existing entry for this custom value.
                int tvIndex = -1;
                for (int iCustom = 0; iCustom < td.td_customValueCount; iCustom++)
                {
                    if (td.td_customValues[iCustom].info.Tag == tag)
                    {
                        tvIndex = iCustom;
                        td.td_customValues[iCustom].value = null;
                        break;
                    }
                }

                // Grow the custom list if the entry was not found.
                if (tvIndex == -1)
                {
                    td.td_customValueCount++;
                    TiffTagValue[] new_customValues = Tiff.Realloc(
                        td.td_customValues, td.td_customValueCount - 1, td.td_customValueCount);
                    td.td_customValues = new_customValues;

                    tvIndex = td.td_customValueCount - 1;
                    td.td_customValues[tvIndex].info  = fip;
                    td.td_customValues[tvIndex].value = null;
                    td.td_customValues[tvIndex].count = 0;
                }

                // Set custom value ... save a copy of the custom tag value.
                int tv_size = Tiff.dataSize(fip.Type);
                if (tv_size == 0)
                {
                    status = false;
                    Tiff.ErrorExt(tif, tif.m_clientdata, module,
                                  "{0}: Bad field type {1} for \"{2}\"",
                                  tif.m_name, fip.Type, fip.Name);
                    end = true;
                    break;
                }

                int paramIndex = 0;
                if (fip.PassCount)
                {
                    if (fip.WriteCount == TiffFieldInfo.Variable2)
                    {
                        td.td_customValues[tvIndex].count = value[paramIndex++].ToInt();
                    }
                    else
                    {
                        td.td_customValues[tvIndex].count = value[paramIndex++].ToInt();
                    }
                }
                else if (fip.WriteCount == TiffFieldInfo.Variable ||
                         fip.WriteCount == TiffFieldInfo.Variable2)
                {
                    td.td_customValues[tvIndex].count = 1;
                }
                else if (fip.WriteCount == TiffFieldInfo.Spp)
                {
                    td.td_customValues[tvIndex].count = td.td_samplesperpixel;
                }
                else
                {
                    td.td_customValues[tvIndex].count = fip.WriteCount;
                }

                if (fip.Type == TiffType.ASCII)
                {
                    string ascii;
                    Tiff.setString(out ascii, value[paramIndex++].ToString());
                    td.td_customValues[tvIndex].value = Tiff.Latin1Encoding.GetBytes(ascii);
                }
                else
                {
                    td.td_customValues[tvIndex].value = new byte[tv_size * td.td_customValues[tvIndex].count];
                    if ((fip.PassCount ||
                         fip.WriteCount == TiffFieldInfo.Variable ||
                         fip.WriteCount == TiffFieldInfo.Variable2 ||
                         fip.WriteCount == TiffFieldInfo.Spp ||
                         td.td_customValues[tvIndex].count > 1) &&
                        fip.Tag != TiffTag.PAGENUMBER &&
                        fip.Tag != TiffTag.HALFTONEHINTS &&
                        fip.Tag != TiffTag.YCBCRSUBSAMPLING &&
                        fip.Tag != TiffTag.DOTRANGE)
                    {
                        byte[] apBytes = value[paramIndex++].GetBytes();
                        Buffer.BlockCopy(apBytes, 0, td.td_customValues[tvIndex].value, 0, Math.Min(apBytes.Length, td.td_customValues[tvIndex].value.Length));
                    }
                    else
                    {
                        // XXX: The following loop required to handle
                        // PAGENUMBER, HALFTONEHINTS,
                        // YCBCRSUBSAMPLING and DOTRANGE tags.
                        // These tags are actually arrays and should be
                        // passed as arrays to SetField() function, but
                        // actually passed as a list of separate values.
                        // This behavior must be changed in the future!

                        // Upd: This loop also processes some EXIF tags with
                        // UNDEFINED type (like EXIF_FILESOURCE or EXIF_SCENETYPE)
                        // In this case input value is string-based, so
                        // in TiffType.UNDEFINED case we use FieldValue.GetBytes()[0]
                        // construction instead of direct call of FieldValue.ToByte() method.
                        byte[] val    = td.td_customValues[tvIndex].value;
                        int    valPos = 0;
                        for (int i = 0; i < td.td_customValues[tvIndex].count; i++, valPos += tv_size)
                        {
                            switch (fip.Type)
                            {
                            case TiffType.BYTE:
                            case TiffType.UNDEFINED:
                                val[valPos] = value[paramIndex + i].GetBytes()[0];
                                break;

                            case TiffType.SBYTE:
                                val[valPos] = value[paramIndex + i].ToByte();
                                break;

                            case TiffType.SHORT:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToShort()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.SSHORT:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToShort()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.LONG:
                            case TiffType.IFD:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToInt()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.SLONG:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToInt()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.RATIONAL:
                            case TiffType.SRATIONAL:
                            case TiffType.FLOAT:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToFloat()), 0, val, valPos, tv_size);
                                break;

                            case TiffType.DOUBLE:
                                Buffer.BlockCopy(BitConverter.GetBytes(value[paramIndex + i].ToDouble()), 0, val, valPos, tv_size);
                                break;

                            default:
                                Array.Clear(val, valPos, tv_size);
                                status = false;
                                break;
                            }
                        }
                    }
                }
                break;
            }

            if (!end && !badvalue && !badvalue32)
            {
                if (status)
                {
                    tif.setFieldBit(tif.FieldWithTag(tag).Bit);
                    tif.m_flags |= TiffFlags.DIRTYDIRECT;
                }
            }

            if (badvalue)
            {
                Tiff.ErrorExt(tif, tif.m_clientdata, module,
                              "{0}: Bad value {1} for \"{2}\" tag",
                              tif.m_name, v, tif.FieldWithTag(tag).Name);
                return(false);
            }

            if (badvalue32)
            {
                Tiff.ErrorExt(tif, tif.m_clientdata, module,
                              "{0}: Bad value {1} for \"{2}\" tag",
                              tif.m_name, v32, tif.FieldWithTag(tag).Name);
                return(false);
            }

            return(status);
        }
Example #47
0
 /*
  * Contig strips -> separate tiles.
  */
 bool cpContigStrips2SeparateTiles(Tiff inImage, Tiff outImage, int imagelength, int imagewidth, short spp)
 {
     return cpImage(
         inImage, outImage,
         new readFunc(readContigStripsIntoBuffer),
         new writeFunc(writeBufferToSeparateTiles),
         imagelength, imagewidth, spp);
 }
        /// <summary>
        /// Gets the value(s) of a tag in an open TIFF file.
        /// </summary>
        /// <param name="tif">An instance of the <see cref="Tiff"/> class.</param>
        /// <param name="tag">The tag.</param>
        /// <returns>The value(s) of a tag in an open TIFF file/stream as array of
        /// <see cref="FieldValue"/> objects or <c>null</c> if there is no such tag set.</returns>
        /// <seealso cref="Tiff.GetField"/>
        public virtual FieldValue[] GetField(Tiff tif, TiffTag tag)
        {
            TiffDirectory td = tif.m_dir;

            FieldValue[] result = null;

            switch (tag)
            {
            case TiffTag.SUBFILETYPE:
                result = new FieldValue[1];
                result[0].Set(td.td_subfiletype);
                break;

            case TiffTag.IMAGEWIDTH:
                result = new FieldValue[1];
                result[0].Set(td.td_imagewidth);
                break;

            case TiffTag.IMAGELENGTH:
                result = new FieldValue[1];
                result[0].Set(td.td_imagelength);
                break;

            case TiffTag.BITSPERSAMPLE:
                result = new FieldValue[1];
                result[0].Set(td.td_bitspersample);
                break;

            case TiffTag.COMPRESSION:
                result = new FieldValue[1];
                result[0].Set(td.td_compression);
                break;

            case TiffTag.PHOTOMETRIC:
                result = new FieldValue[1];
                result[0].Set(td.td_photometric);
                break;

            case TiffTag.THRESHHOLDING:
                result = new FieldValue[1];
                result[0].Set(td.td_threshholding);
                break;

            case TiffTag.FILLORDER:
                result = new FieldValue[1];
                result[0].Set(td.td_fillorder);
                break;

            case TiffTag.ORIENTATION:
                result = new FieldValue[1];
                result[0].Set(td.td_orientation);
                break;

            case TiffTag.SAMPLESPERPIXEL:
                result = new FieldValue[1];
                result[0].Set(td.td_samplesperpixel);
                break;

            case TiffTag.ROWSPERSTRIP:
                result = new FieldValue[1];
                result[0].Set(td.td_rowsperstrip);
                break;

            case TiffTag.MINSAMPLEVALUE:
                result = new FieldValue[1];
                result[0].Set(td.td_minsamplevalue);
                break;

            case TiffTag.MAXSAMPLEVALUE:
                result = new FieldValue[1];
                result[0].Set(td.td_maxsamplevalue);
                break;

            case TiffTag.SMINSAMPLEVALUE:
                result = new FieldValue[1];
                result[0].Set(td.td_sminsamplevalue);
                break;

            case TiffTag.SMAXSAMPLEVALUE:
                result = new FieldValue[1];
                result[0].Set(td.td_smaxsamplevalue);
                break;

            case TiffTag.XRESOLUTION:
                result = new FieldValue[1];
                result[0].Set(td.td_xresolution);
                break;

            case TiffTag.YRESOLUTION:
                result = new FieldValue[1];
                result[0].Set(td.td_yresolution);
                break;

            case TiffTag.PLANARCONFIG:
                result = new FieldValue[1];
                result[0].Set(td.td_planarconfig);
                break;

            case TiffTag.XPOSITION:
                result = new FieldValue[1];
                result[0].Set(td.td_xposition);
                break;

            case TiffTag.YPOSITION:
                result = new FieldValue[1];
                result[0].Set(td.td_yposition);
                break;

            case TiffTag.RESOLUTIONUNIT:
                result = new FieldValue[1];
                result[0].Set(td.td_resolutionunit);
                break;

            case TiffTag.PAGENUMBER:
                result = new FieldValue[2];
                result[0].Set(td.td_pagenumber[0]);
                result[1].Set(td.td_pagenumber[1]);
                break;

            case TiffTag.HALFTONEHINTS:
                result = new FieldValue[2];
                result[0].Set(td.td_halftonehints[0]);
                result[1].Set(td.td_halftonehints[1]);
                break;

            case TiffTag.COLORMAP:
                result = new FieldValue[3];
                result[0].Set(td.td_colormap[0]);
                result[1].Set(td.td_colormap[1]);
                result[2].Set(td.td_colormap[2]);
                break;

            case TiffTag.STRIPOFFSETS:
            case TiffTag.TILEOFFSETS:
                result = new FieldValue[1];
                result[0].Set(td.td_stripoffset);
                break;

            case TiffTag.STRIPBYTECOUNTS:
            case TiffTag.TILEBYTECOUNTS:
                result = new FieldValue[1];
                result[0].Set(td.td_stripbytecount);
                break;

            case TiffTag.MATTEING:
                result = new FieldValue[1];
                result[0].Set((td.td_extrasamples == 1 && td.td_sampleinfo[0] == ExtraSample.ASSOCALPHA));
                break;

            case TiffTag.EXTRASAMPLES:
                result = new FieldValue[2];
                result[0].Set(td.td_extrasamples);
                result[1].Set(td.td_sampleinfo);
                break;

            case TiffTag.TILEWIDTH:
                result = new FieldValue[1];
                result[0].Set(td.td_tilewidth);
                break;

            case TiffTag.TILELENGTH:
                result = new FieldValue[1];
                result[0].Set(td.td_tilelength);
                break;

            case TiffTag.TILEDEPTH:
                result = new FieldValue[1];
                result[0].Set(td.td_tiledepth);
                break;

            case TiffTag.DATATYPE:
                switch (td.td_sampleformat)
                {
                case SampleFormat.UINT:
                    result = new FieldValue[1];
                    result[0].Set(DATATYPE_UINT);
                    break;

                case SampleFormat.INT:
                    result = new FieldValue[1];
                    result[0].Set(DATATYPE_INT);
                    break;

                case SampleFormat.IEEEFP:
                    result = new FieldValue[1];
                    result[0].Set(DATATYPE_IEEEFP);
                    break;

                case SampleFormat.VOID:
                    result = new FieldValue[1];
                    result[0].Set(DATATYPE_VOID);
                    break;
                }
                break;

            case TiffTag.SAMPLEFORMAT:
                result = new FieldValue[1];
                result[0].Set(td.td_sampleformat);
                break;

            case TiffTag.IMAGEDEPTH:
                result = new FieldValue[1];
                result[0].Set(td.td_imagedepth);
                break;

            case TiffTag.SUBIFD:
                result = new FieldValue[2];
                result[0].Set(td.td_nsubifd);
                result[1].Set(td.td_subifd);
                break;

            case TiffTag.YCBCRPOSITIONING:
                result = new FieldValue[1];
                result[0].Set(td.td_ycbcrpositioning);
                break;

            case TiffTag.YCBCRSUBSAMPLING:
                result = new FieldValue[2];
                result[0].Set(td.td_ycbcrsubsampling[0]);
                result[1].Set(td.td_ycbcrsubsampling[1]);
                break;

            case TiffTag.TRANSFERFUNCTION:
                result = new FieldValue[3];
                result[0].Set(td.td_transferfunction[0]);
                if (td.td_samplesperpixel - td.td_extrasamples > 1)
                {
                    result[1].Set(td.td_transferfunction[1]);
                    result[2].Set(td.td_transferfunction[2]);
                }
                break;

            case TiffTag.REFERENCEBLACKWHITE:
                if (td.td_refblackwhite != null)
                {
                    result = new FieldValue[1];
                    result[0].Set(td.td_refblackwhite);
                }
                break;

            case TiffTag.INKNAMES:
                result = new FieldValue[1];
                result[0].Set(td.td_inknames);
                break;

            default:
                // This can happen if multiple images are open with
                // different codecs which have private tags. The global tag
                // information table may then have tags that are valid for
                // one file but not the other. If the client tries to get a
                // tag that is not valid for the image's codec then we'll
                // arrive here.
                TiffFieldInfo fip = tif.FindFieldInfo(tag, TiffType.ANY);
                if (fip == null || fip.Bit != FieldBit.Custom)
                {
                    Tiff.ErrorExt(tif, tif.m_clientdata, "_TIFFVGetField",
                                  "{0}: Invalid {1}tag \"{2}\" (not supported by codec)",
                                  tif.m_name, Tiff.isPseudoTag(tag) ? "pseudo-" : string.Empty,
                                  fip != null ? fip.Name : "Unknown");
                    result = null;
                    break;
                }

                // Do we have a custom value?
                result = null;
                for (int i = 0; i < td.td_customValueCount; i++)
                {
                    TiffTagValue tv = td.td_customValues[i];
                    if (tv.info.Tag != tag)
                    {
                        continue;
                    }

                    if (fip.PassCount)
                    {
                        result = new FieldValue[2];

                        if (fip.ReadCount == TiffFieldInfo.Variable2)
                        {
                            result[0].Set(tv.count);
                        }
                        else
                        {
                            // Assume TiffFieldInfo.Variable
                            result[0].Set(tv.count);
                        }

                        result[1].Set(tv.value);
                    }
                    else
                    {
                        if ((fip.Type == TiffType.ASCII ||
                             fip.ReadCount == TiffFieldInfo.Variable ||
                             fip.ReadCount == TiffFieldInfo.Variable2 ||
                             fip.ReadCount == TiffFieldInfo.Spp ||
                             tv.count > 1) && fip.Tag != TiffTag.PAGENUMBER &&
                            fip.Tag != TiffTag.HALFTONEHINTS &&
                            fip.Tag != TiffTag.YCBCRSUBSAMPLING &&
                            fip.Tag != TiffTag.DOTRANGE)
                        {
                            result = new FieldValue[1];
                            byte[] value = tv.value;

                            if (fip.Type == TiffType.ASCII &&
                                tv.value.Length > 0 &&
                                tv.value[tv.value.Length - 1] == 0)
                            {
                                // cut unwanted zero at the end
                                value = new byte[Math.Max(tv.value.Length - 1, 0)];
                                Buffer.BlockCopy(tv.value, 0, value, 0, value.Length);
                            }

                            result[0].Set(value);
                        }
                        else
                        {
                            result = new FieldValue[tv.count];
                            byte[] val    = tv.value;
                            int    valPos = 0;
                            for (int j = 0; j < tv.count; j++, valPos += Tiff.dataSize(tv.info.Type))
                            {
                                switch (fip.Type)
                                {
                                case TiffType.BYTE:
                                case TiffType.UNDEFINED:
                                case TiffType.SBYTE:
                                    result[j].Set(val[valPos]);
                                    break;

                                case TiffType.SHORT:
                                case TiffType.SSHORT:
                                    result[j].Set(BitConverter.ToInt16(val, valPos));
                                    break;

                                case TiffType.LONG:
                                case TiffType.IFD:
                                case TiffType.SLONG:
                                    result[j].Set(BitConverter.ToInt32(val, valPos));
                                    break;

                                case TiffType.RATIONAL:
                                case TiffType.SRATIONAL:
                                case TiffType.FLOAT:
                                    result[j].Set(BitConverter.ToSingle(val, valPos));
                                    break;

                                case TiffType.DOUBLE:
                                    result[j].Set(BitConverter.ToDouble(val, valPos));
                                    break;

                                default:
                                    result = null;
                                    break;
                                }
                            }
                        }
                    }
                    break;
                }
                break;
            }

            return(result);
        }