Return-Path: owner-tiff@olympiakos.com
Return-Path: <owner-tiff@olympiakos.com>
Received: from localhost (localhost [127.0.0.1])
	by at1895.spb.edu (8.12.1/8.12.1/Debian -5) with ESMTP id g393TFWB021942
	for <dron@localhost>; Tue, 9 Apr 2002 07:34:52 +0400
Received: from eudoramail.com [209.185.123.45]
	by localhost with POP3 (fetchmail-5.9.0)
	for dron@localhost (single-drop); Tue, 09 Apr 2002 07:34:52 +0400 (MSD)
Received: from gate7.olympiakos.com ([64.32.199.150]) by shared1-mail.whowhere.com; Mon Apr  8 13:21:39 2002
Received: from localhost (daemon@localhost)
	by gate7.olympiakos.com (8.9.3/8.9.3) with SMTP id PAA11694;
	Mon, 8 Apr 2002 15:51:35 -0400
Received: by gate7.olympiakos.com (bulk_mailer v1.9); Mon, 8 Apr 2002 15:51:13 -0400
Received: (from majordom@localhost)
	by gate7.olympiakos.com (8.9.3/8.9.3) id PAA11678
	for tiff-outgoing; Mon, 8 Apr 2002 15:51:13 -0400
X-Authentication-Warning: gate7.olympiakos.com: majordom set sender to owner-tiff@olympiakos.com using -f
Received: from pixar.pixar.com (pixar.pixar.com [138.72.10.20])
	by gate7.olympiakos.com (8.9.3/8.9.3) with ESMTP id PAA11675
	for <tiff@olympiakos.com>; Mon, 8 Apr 2002 15:51:12 -0400
Received: from melete.pixar.com (melete.pixar.com [138.72.16.219])
	by pixar.pixar.com (8.9.3/8.9.3) with ESMTP id MAA17373;
	Mon, 8 Apr 2002 12:50:38 -0700 (PDT)
Received: (from mccoy@localhost)
	by melete.pixar.com (8.11.2/8.9.3) id g38Jodo20008;
	Mon, 8 Apr 2002 12:50:39 -0700
Date: Mon, 8 Apr 2002 12:50:39 -0700
From: Daniel McCoy <mccoy@pixar.com>
To: myia@is.elta.co.il
Cc: tiff@olympiakos.com
Subject: Re: writing tiff incrementally
Message-ID: <20020408195039.GD18937@melete.pixar.com>
References: <3CB1BB1D.76C146A6@is.elta.co.il>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <3CB1BB1D.76C146A6@is.elta.co.il>
User-Agent: Mutt/1.3.24i
Sender: owner-tiff@olympiakos.com
Precedence: bulk
Status: RO
Content-Length: 5468
Lines: 180

From: myia@is.elta.co.il
> Hi,
> 
> I would like to write a tiff image incrementally: I have a program that
> writes a tiff file, and I would like to allow users to view the tiles I
> wrote so far (using standard tiff viewers). Does the library support
> something like this?
> I tried TIFFFlush, but it doesn't allow me to go on writing tiles to the
> image. If the library does not support it, is there some standard or
> easy wat to do it?
> 
> Any suggestions are welcome.
> 
> Thanks,
> 
> Moshe

Here is a patch to the 3.5.7 tif_dirwrite to add TIFFCheckpointDirectory().
(You might want to also add an "extern" for it in tiffio.h,
right next to the one for TIFFWriteDirectory().)

Once this is in, you need only call TIFFCheckpointDirectory(tif)
to write out the current state of the tiff directory into the file
to make what is currently in the file readable.
Unlike TIFFWriteDirectory, TIFFCheckpointDirectory does not free
up the directory data structures in memory, so they can be updated
(as strips/tiles are written) and written again.

Reading such a partial file you will at worst get a tiff read error
for the first strip/tile encountered that is incomplete,
but you will at least get all the valid data in the file before that.

When the file is complete, just use TIFFWriteDirectory as usual
to finish it off cleanly.

(The changes are not really as extensive as it looks, a couple of sections
of code got pulled into conditionals so the indentation changed. 
Try a diff that ignores whitespace after the patch to see what really changed.)

Could someone else give this a try and merge it into the library?
(I've already spent more time on it than I'm supposed to at this point.)

Daniel McCoy    Pixar

*************Beginning of patch************************
--- tif_dirwrite.c	Mon Apr  8 12:29:59 2002
+++ tif_dirwrite.c.new	Mon Apr  8 12:30:06 2002
@@ -87,8 +87,8 @@
  * handle overwriting a directory with auxiliary
  * storage that's been changed.
  */
-int
-TIFFWriteDirectory(TIFF* tif)
+static int
+TIFFWriteDirectory1(TIFF* tif, int done)
 {
 	uint16 dircount;
 	toff_t diroff;
@@ -108,31 +108,34 @@
 	 * different characteristics get the right buffers
 	 * setup for them.
 	 */
-	if (tif->tif_flags & TIFF_POSTENCODE) {
-		tif->tif_flags &= ~TIFF_POSTENCODE;
-		if (!(*tif->tif_postencode)(tif)) {
-			TIFFError(tif->tif_name,
-			    "Error post-encoding before directory write");
-			return (0);
-		}
-	}
-	(*tif->tif_close)(tif);			/* shutdown encoder */
-	/*
-	 * Flush any data that might have been written
-	 * by the compression close+cleanup routines.
-	 */
-	if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) {
-		TIFFError(tif->tif_name,
-		    "Error flushing data before directory write");
-		return (0);
-	}
-	if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
-		_TIFFfree(tif->tif_rawdata);
-		tif->tif_rawdata = NULL;
-		tif->tif_rawcc = 0;
-                tif->tif_rawdatasize = 0;
+	if (done)
+	{
+	    if (tif->tif_flags & TIFF_POSTENCODE) {
+		    tif->tif_flags &= ~TIFF_POSTENCODE;
+		    if (!(*tif->tif_postencode)(tif)) {
+			    TIFFError(tif->tif_name,
+				"Error post-encoding before directory write");
+			    return (0);
+		    }
+	    }
+	    (*tif->tif_close)(tif);		/* shutdown encoder */
+	    /*
+	     * Flush any data that might have been written
+	     * by the compression close+cleanup routines.
+	     */
+	    if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) {
+		    TIFFError(tif->tif_name,
+			"Error flushing data before directory write");
+		    return (0);
+	    }
+	    if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
+		    _TIFFfree(tif->tif_rawdata);
+		    tif->tif_rawdata = NULL;
+		    tif->tif_rawcc = 0;
+		    tif->tif_rawdatasize = 0;
+	    }
+	    tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP);
 	}
-	tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP);
 
 	td = &tif->tif_dir;
 	/*
@@ -351,22 +354,48 @@
 		TIFFError(tif->tif_name, "Error writing directory link");
 		goto bad;
 	}
-	TIFFFreeDirectory(tif);
-	_TIFFfree(data);
-	tif->tif_flags &= ~TIFF_DIRTYDIRECT;
-	(*tif->tif_cleanup)(tif);
+	if (done) {
+		TIFFFreeDirectory(tif);
+		tif->tif_flags &= ~TIFF_DIRTYDIRECT;
+		(*tif->tif_cleanup)(tif);
 
-	/*
-	 * Reset directory-related state for subsequent
-	 * directories.
-	 */
-        TIFFCreateDirectory(tif);
+		/*
+		* Reset directory-related state for subsequent
+		* directories.
+		*/
+		TIFFCreateDirectory(tif);
+	}
+	_TIFFfree(data);
 	return (1);
 bad:
 	_TIFFfree(data);
 	return (0);
 }
 #undef WriteRationalPair
+
+int
+TIFFWriteDirectory(TIFF* tif)
+{
+	return TIFFWriteDirectory1(tif, 1);
+}
+
+/*
+ * Similar to TIFFWriteDirectory(), writes the directory out
+ * but leaves all data structures in memory so that it can be
+ * written again.  This will make a partially written TIFF file
+ * readable before it is successfully completed/closed.
+ */ 
+int
+TIFFCheckpointDirectory(TIFF* tif)
+{
+	int rc;
+	/* Setup the strips arrays, if they haven't already been. */
+	if (tif->tif_dir.td_stripoffset == NULL)
+	    (void) TIFFSetupStrips(tif);
+	rc = TIFFWriteDirectory1(tif, 0);
+	(void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
+	return rc;
+}
 
 /*
  * Process tags that are not special cased.
*************End of patch************************


To subscribe or unsubscribe email tiff-request@olympiakos.com with subscribe
or unsubscribe in the email body.  Libtiff home page: http://www.libtiff.org

