2003.09.12 16:04 "[Tiff] writing out custom tags", by Chris Padwick

2003.09.15 07:45 "[Tiff] writing out custom tags", by Andrey Kiselev

I'm trying to copy a custom tag from an input file to an output file. I'm using version 3.6.0 of the tiff library, grabbed from cvs last night. First, tiffcp doesn't copy the tag I'm interested in. The input file is tiled and has 5 directories and each directory has a private tag. Here is a tiffdump of the first directory:

Tiffdump:

Magic: 0x4d4d <big-endian> Version: 0x2a
Directory 0: offset 881328152 (0x34880018) next 881437232 (0x3489aa30)
ImageWidth (256) SHORT (3) 1<6290>
ImageLength (257) SHORT (3) 1<6780>
<snip>
.
.
.
34595 (0x8723) LONG (4) 137<1769472 262144 65536 65537 262144 65536 6619141 589824 406664 222298118 65536 5256328 223870986 131072 341128 229113867 131072 341128 229507084 65536 7353480 229900301 65536 3683464...
<snip>

The tag I'm interested in is 34595. I can read this tag no problem, but when I go to write it out I get a segfault. Here is the code I'm using:

Chris,

You have made a few mistakes in your code:

  1. You forgot to set image parameters for the output file
  2. You shouldn't explicitly call TagExtender() function, it will be used in the libtiff internals when needed.
  3. You should provide total tag count to the TIFFSetField() function:

        TIFFSetField(outtif, TIFFTAG_PRIVATE, iCount, lng);

I have attached corrected code (with C++-zation removed). That code works for me:

$ tiffinfo inputfile.tif
TIFF Directory at offset 0x30008
  Subfile Type: (0 = 0x0)
  Image Width: 256 Image Length: 256
  Tile Width: 256 Tile Length: 256
  Resolution: 72, 72 pixels/inch
  Bits/Sample: 8
  Compression Scheme: None
  Photometric Interpretation: RGB color
  Document Name: "/home/dron/projects/tiff/bugs/test.tif"
  Image Description: "dron"
  Orientation: row 0 top, col 0 lhs
  Samples/Pixel: 3
  Planar Configuration: single image plane

$ tiffinfo outfile.tif
TIFFReadDirectory: Warning, outfile.tif: unknown field with tag 34595 (0x8723) encountered.
TIFF Directory at offset 0x30008
  Image Width: 256 Image Length: 256
  Tile Width: 256 Tile Length: 256
  Bits/Sample: 8
  Compression Scheme: None
  Orientation: row 0 top, col 0 lhs
  Samples/Pixel: 3
  Planar Configuration: single image plane
  Tag 34595: 10,20,30,40

Hope this helps.

Andrey

Andrey V. Kiselev
Home phone: +7 812 5274898 ICQ# 26871517

//=========================================================================
// test_write_tags.cpp : a function to test the writing of custom tags to
// tiff images.
//
//=========================================================================
//Includes
#include <stdio.h>
#include <stdlib.h>
#include <tiffio.h>

#define           TIFFTAG_PRIVATE         34595

static void TagExtender(TIFF *tiff)
{
    static const TIFFFieldInfo xtiffFieldInfo[] = {
        { TIFFTAG_PRIVATE, TIFF_VARIABLE, TIFF_VARIABLE, TIFF_LONG,
            FIELD_CUSTOM, 0, 1, "Private Tag" }
    };

    TIFFMergeFieldInfo( tiff, xtiffFieldInfo,
                    sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]) );
}

int main( int argc, char* argv[] )
{
      TIFF *intif=(TIFF*)0;
      TIFF *outtif=(TIFF*)0;
      int dir_count = 0;
      int dir_ndx;
      int result = 1;
      //unsigned long* lng;
      unsigned long lng[] = {10, 20, 30, 40};
      unsigned short iCount;

      intif=TIFFOpen("inputfile.tif","r");
      if (!intif)
      {
            fprintf( stderr, "Unable to open input file.  Quitting.\n" );
            return 1;
      }

      outtif = TIFFOpen("outfile.tif", "w");
      if( !outtif )
      {
            fprintf( stderr, "\n\nUnable to open output file.  Quitting\n"
);
            return( 1 );
      }

      do
      {
            dir_count++;
      } while( TIFFReadDirectory( intif ) );

      printf( "%d directories in input file\n", dir_count );

      TIFFSetTagExtender(TagExtender);

      for( dir_ndx = 0; dir_ndx < dir_count; dir_ndx++ )
      {
            tdata_t buf;
            uint32 tileWidth, tileLength, imageLength, imageWidth;
            uint32 x, y;

            TIFFSetDirectory( intif, dir_ndx );
            fprintf( stderr, "Processing directory %d ...\n", dir_ndx );

            TIFFGetField(intif, TIFFTAG_TILEWIDTH, &tileWidth);
            TIFFGetField(intif, TIFFTAG_TILELENGTH, &tileLength);
            TIFFGetField(intif, TIFFTAG_IMAGELENGTH, &imageLength);
            TIFFGetField(intif, TIFFTAG_IMAGEWIDTH, &imageWidth);

            TIFFCreateDirectory( outtif );
            TIFFSetDirectory( outtif, dir_ndx );
            TIFFSetField(outtif, TIFFTAG_IMAGEWIDTH, imageWidth);
            TIFFSetField(outtif, TIFFTAG_IMAGELENGTH, imageLength);
            TIFFSetField(outtif, TIFFTAG_BITSPERSAMPLE, 8);
            TIFFSetField(outtif, TIFFTAG_SAMPLESPERPIXEL, 3);
            TIFFSetField(outtif, TIFFTAG_TILEWIDTH, tileWidth);
            TIFFSetField(outtif, TIFFTAG_TILELENGTH, tileLength);
            TIFFSetField(outtif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
            TIFFSetField(outtif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);

            //result = TIFFGetField(intif, TIFFTAG_PRIVATE, &iCount, &lng);
            iCount = sizeof(lng)/sizeof(lng[0]);
            fprintf(stderr, "iCount=%d\n", iCount);
            if( result )
                result = TIFFSetField(outtif, TIFFTAG_PRIVATE, iCount, lng);


            buf = _TIFFmalloc(TIFFTileSize(intif));
            for (y = 0; y < imageLength; y += tileLength)
            {
                  for (x = 0; x < imageWidth; x += tileWidth)
                  {
                        TIFFReadTile(intif, buf, x, y, 0, 0);
                        TIFFWriteTile(outtif, buf, x, y, 0, 0);
                  }
            }

            TIFFWriteDirectory( outtif );
            _TIFFfree( buf );
      }

    TIFFClose(intif);
    TIFFClose(outtif);

      return( 0 );
}