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
November 2008

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!



2008.11.24 19:40 "TIFFWriteScanline corrupts buffer when compression with predication is enabled", by William B Thompson

As best as I can tell, TIFFWriteScanline corrupts the input buffer in
the calling program with LZW and deflate (zip) compression when
horizontal prediction is enabled for integer values or floating point
prediction is enable for floating point values.  This occurs with both
libtiff 3.8.2 and 4.0.0beta2.  A test program for the 8 bit integer case
is included at the end of this message.

The declaration of TIFFWriteScanline does not include the "const"
qualifier for the buffer argument, so modifying values in the buffer is
not, strictly speaking, in violation of the specification.  It seems to
me, however, that it is bad practice.  It is certainly bad practice when
not described in the man page for TIFFWriteScanline.

One might argue that it is rare to rewrite or otherwise reuse an output
buffer that has just been written to a file.  I can testify from
personal experience that it might be rare, but it does occur (and is a
pain to track down when it happens).

	- Bill

/*
 * Run with and without -p flag.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <tiffio.h>

#define OUTPUT_NAME     "libtiff-prediction-test.tif"

int
main ( int argc, char *argv[] )
{
    TIFF        *output;
    uint8       *output_buffer;
    int         i;
    int         prediction_flag = 0;

    if ( ( argc == 2 ) && ( strcmp ( argv[1], "-p" ) == 0 ) ) {
        prediction_flag = 1;
    }

    output_buffer = (uint8 *) _TIFFmalloc ( 10 * sizeof ( uint8 ) );
    for ( i = 0; i < 10; i++ ) {
        output_buffer[i] = 10;
    }

    output = TIFFOpen ( OUTPUT_NAME , "w" );
    TIFFSetField ( output, TIFFTAG_IMAGEWIDTH, 10 );
    TIFFSetField ( output, TIFFTAG_IMAGELENGTH, 1 );
    TIFFSetField ( output, TIFFTAG_BITSPERSAMPLE, 8 );
    TIFFSetField ( output, TIFFTAG_SAMPLESPERPIXEL, 1 );
    TIFFSetField ( output, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
    if ( prediction_flag ) {
        printf ( "using horizontal prediction\n" );
        TIFFSetField ( output, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL );
    } else {
        printf ( "not using horizontal prediction\n" );
    }
    TIFFSetField ( output, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    TIFFSetField ( output, TIFFTAG_ROWSPERSTRIP,
            TIFFDefaultStripSize ( output, 0 ) );
    TIFFSetField ( output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
    TIFFSetField ( output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );

    printf ( "output buffer before call to TIFFWriteScanline:\n" );
    for ( i = 0; i < 10; i++ ) {
        printf ( "%4d", output_buffer[i] );
    }
    printf ( "\n" );

    TIFFWriteScanline ( output, output_buffer, 0, 0 );

    printf ( "output buffer after call to TIFFWriteScanline:\n" );
    for ( i = 0; i < 10; i++ ) {
        printf ( "%4d", output_buffer[i] );
    }
    printf ( "\n" );

    TIFFClose ( output );

    return ( EXIT_SUCCESS );    /* normal exit */
}