2004.11.03 19:51 "[Tiff] [Patch] TIFFStreamOpen()", by Edward Lam

Hi,

These changes have been sitting in our baseline for quite a while (since 3.4) now and so I might as well submit them as others might find it useful. And if it's gets accepted, it saves me work the next time I upgrade. :)

The patch was created against CVS HEAD. It modifies tiffio.h and adds a new file, tif_stream.C. It adds two new functions to support reading/writing tiff files via C++ streams. tiffio.h is modified to include the two new prototypes like so:

#if defined(c_plusplus) || defined(__cplusplus)
   #include <iostream.h>
   extern       TIFF* TIFFStreamOpen(const char*, ostream *);
   extern       TIFF* TIFFStreamOpen(const char*, istream *);
+#endif

The first version allows one to write a tiff file to the given ostream using the name given in the first parameter. The second one allows you to read from the given istream. They were written to provide an easy way in C++ to read and write tiff images embedded in other files. These are implemented in the new tif_stream.C file.

Thanks,

-Edward

Index: tiffio.h
===================================================================
RCS file: /cvs/maptools/cvsroot/libtiff/libtiff/tiffio.h,v
retrieving revision 1.36
diff -u -d -p -r1.36 tiffio.h
--- tiffio.h    24 Sep 2004 15:18:57 -0000      1.36
+++ tiffio.h    3 Nov 2004 19:39:26 -0000
@@ -492,6 +492,13 @@ extern  void TIFFSetClientInfo( TIFF *,
 #if defined(__cplusplus)
 }
 #endif
+
+#if defined(c_plusplus) || defined(__cplusplus)
+#include <iostream.h>
+extern TIFF* TIFFStreamOpen(const char*, ostream *);
+extern TIFF* TIFFStreamOpen(const char*, istream *);
+#endif
+
 #endif /* _TIFFIO_ */

 /* vim: set ts=8 sts=8 sw=8 noet: */
--- /dev/null   Wed Nov 03 14:39:44 2004
+++ tif_stream.C        Wed Nov 03 11:38:00 2004
@@ -0,0 +1,214 @@
+
+/*
+ * Copyright (c) 1988-1996 Sam Leffler
+ * Copyright (c) 1991-1996 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library UNIX-specific Routines.
+ */
+#include <iostream.h>
+#include "tiffiop.h"
+
+class tiffis_data
+{
+public:
+    istream    *myIS;
+    long        myStreamStartPos;
+};
+
+static tsize_t
+_tiffosReadProc(thandle_t, tdata_t, tsize_t)
+{
+    return 0;
+}
+
+static tsize_t
+_tiffisReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+    tiffis_data        *data = (tiffis_data *)fd;
+
+    data->myIS->read((char *)buf, size);
+
+    return data->myIS->gcount();
+}
+
+static tsize_t
+_tiffosWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+    ostream    *os = (ostream *)fd;
+    int                 pos = os->tellp();
+
+    os->write((const char *)buf, size);
+
+    return ((int)os->tellp()) - pos;
+}
+
+static tsize_t
+_tiffisWriteProc(thandle_t, tdata_t, tsize_t)
+{
+    return 0;
+}
+
+static toff_t
+_tiffosSeekProc(thandle_t fd, toff_t off, int whence)
+{
+    ostream    *os = (ostream *)fd;
+
+    switch( whence )
+    {
+       case SEEK_SET:
+           os->seekp(off, ios::beg);
+           break;
+       case SEEK_CUR:
+           os->seekp(off, ios::cur);
+           break;
+       case SEEK_END:
+           os->seekp(off, ios::end);
+           break;
+    }
+
+    return os->tellp();
+}
+
+static toff_t
+_tiffisSeekProc(thandle_t fd, toff_t off, int whence)
+{
+    tiffis_data        *data = (tiffis_data *)fd;
+
+    switch( whence )
+    {
+       case SEEK_SET:
+           data->myIS->seekg(data->myStreamStartPos + off, ios::beg);
+           break;
+       case SEEK_CUR:
+           data->myIS->seekg(off, ios::cur);
+           break;
+       case SEEK_END:
+           data->myIS->seekg(off, ios::end);
+           break;
+    }
+
+    return ((long)data->myIS->tellg()) - data->myStreamStartPos;
+}
+
+static toff_t
+_tiffosSizeProc(thandle_t fd)
+{
+    ostream    *os = (ostream *)fd;
+    int                 pos = os->tellp();
+    int                 len;
+
+    os->seekp(0, ios::end);
+    len = os->tellp();
+    os->seekp(pos);
+
+    return len;
+}
+
+static toff_t
+_tiffisSizeProc(thandle_t fd)
+{
+    tiffis_data        *data = (tiffis_data *)fd;
+    int                 pos = data->myIS->tellg();
+    int                 len;
+
+    data->myIS->seekg(0, ios::end);
+    len = data->myIS->tellg();
+    data->myIS->seekg(pos);
+
+    return len;
+}
+
+static int
+_tiffosCloseProc(thandle_t fd)
+{
+    // Our stream was not allocated by us, so it shouldn't be closed by us.
+    return 0;
+}
+
+static int
+_tiffisCloseProc(thandle_t fd)
+{
+    // Our stream was not allocated by us, so it shouldn't be closed by us.
+    delete (tiffis_data *)fd;
+    return 0;
+}
+
+static int
+_tiffDummyMapProc(thandle_t , tdata_t* , toff_t* )
+{
+       return (0);
+}
+
+static void
+_tiffDummyUnmapProc(thandle_t , tdata_t , toff_t )
+{
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+static TIFF*
+_tiffStreamOpen(const char* name, const char* mode, void *fd)
+{
+       TIFF*       tif;
+
+       if( strchr(mode, 'w') )
+       {
+           // Open for writing.
+           tif = TIFFClientOpen(name, mode,
+               (thandle_t) fd,
+               _tiffosReadProc, _tiffosWriteProc,
+               _tiffosSeekProc, _tiffosCloseProc, _tiffosSizeProc,
+               _tiffDummyMapProc, _tiffDummyUnmapProc);
+       }
+       else
+       {
+           tiffis_data *data = new tiffis_data;
+           data->myIS = (istream *)fd;
+           data->myStreamStartPos = data->myIS->tellg();
+           // Open for reading.
+           tif = TIFFClientOpen(name, mode,
+               (thandle_t) data,
+               _tiffisReadProc, _tiffisWriteProc,
+               _tiffisSeekProc, _tiffisCloseProc, _tiffisSizeProc,
+               _tiffDummyMapProc, _tiffDummyUnmapProc);
+       }
+
+       return (tif);
+}
+
+TIFF*
+TIFFStreamOpen(const char* name, ostream *os)
+{
+       // NB: We don't support mapped files with streams
+       return _tiffStreamOpen(name, "wm", os);
+}
+
+TIFF*
+TIFFStreamOpen(const char* name, istream *is)
+{
+       // NB: We don't support mapped files with streams
+       return _tiffStreamOpen(name, "rm", is);
+}
+