AWARE [SYSTEMS] Imaging expertise for the Delphi developer
AWare Systems, Imaging expertise for the Delphi developer, Home TIFF and LibTiff Mailing List Archive

LibTiff Mailing List

TIFF and LibTiff Mailing List Archive
January 2005

Previous Thread
Next Thread

Previous by Thread
Next by Thread

Previous by Date
Next by Date

Contact

The TIFF Mailing List Homepage
This list is run by Frank Warmerdam
Archive maintained by AWare Systems



Valid HTML 4.01!



Thread

2005.01.25 18:29 "issues with TIFFStreamOpen", by Michael Rinne
2005.01.27 19:45 "Re: issues with TIFFStreamOpen", by Edward Lam
2005.01.27 21:51 "Re: issues with TIFFStreamOpen", by Edward Lam
2005.01.28 10:28 "Re: issues with TIFFStreamOpen", by Michael Rinne
2005.01.28 16:24 "Re: issues with TIFFStreamOpen", by Edward Lam
2005.01.28 16:45 "Re: issues with TIFFStreamOpen", by Michael Rinne
2005.01.30 12:02 "Re: issues with TIFFStreamOpen", by Andrey Kiselev
2005.01.30 23:19 "Re: issues with TIFFStreamOpen", by Edward Lam
2005.01.31 21:20 "Re: issues with TIFFStreamOpen", by Michael Rinne
2005.01.28 19:58 "Re: issues with TIFFStreamOpen", by Frank Warmerdam

2005.01.25 18:29 "issues with TIFFStreamOpen", by Michael Rinne

Hi,

first of all, thanks to Edward Lam for adding C++ iostream support to
LibTIFF!

Unfortunately, I have got to report two issues for the iostream support.
However, I have got at least a fix for one issue.

1. LibTIFF currently overwrites any data already written to an ostream.

It looks like the LibTIFF uses the seek function right at the start in
order to seek to the beginning of the file. This happens in
TIFFClientOpen by a call to _tiffosSeekProc with off=0 and
whence=SEEK_SET. Therefore, any data written to the stream before
calling TIFFStreamOpen gets overwritten by the TIFF image.

The fix for this is straight forward, because it is analogous to the
implementation when reading a TIFF image from an istream. The modified
file tif_stream.cxx is attached to this mail.

2. LibTIFF is currently unable to write images to an ostringstream.

This might be Microsoft Visual C++ specific. I am using MS VC 7.1 . If
one calls tellp on a newly constructed ostringstream object it returns
the position -1. According to a posting to microsoft.public.vc.stl this
might be the correct behavior for the basic_ostream object, see

http://groups.google.de/groups?selm=uMWFsM4EBHA.1676%40tkmsftngp04&output=gplain

The LibTIFF dumps the error 'Error writing TIFF header.' in this case. I
tried to work around this issue by simply writing a few characters to
the ostringstream. This results almost in a valid stream, but it fails
at the end with the error message 'Error writing data for field
"BitsPerSample".'. I tracked it down to the macro SeekOK which gets
called in tif_dirwrite.c at line 1066. This macro calls _tiffosSeekProc
with an offset that seems to exceed the amount of data written to the
stream and therefore the ostream method returns a bad offset.

This behavior is the same for the original tif_stream.cxx file and the
patched version attached to this mail.

I hope this provides enough information for a TIFF guru to help overcome
this issue. Please give me a hint on how to fix this problem.

Thanks,
Michael

/* $Id: tif_stream.cxx,v 1.2 2004/11/13 11:19:15 dron Exp $ */

/*
 * 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>
#include "tiffiop.h"

using namespace std;

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, (int)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);
}

/* vim: set ts=8 sts=8 sw=8 noet: */