roentgen b75cab
/******************************************************************************
roentgen b75cab
 * $Id: tiffset.c,v 1.17 2012-07-29 15:45:30 tgl Exp $
roentgen b75cab
 *
roentgen b75cab
 * Project:  libtiff tools
roentgen b75cab
 * Purpose:  Mainline for setting metadata in existing TIFF files.
roentgen b75cab
 * Author:   Frank Warmerdam, warmerdam@pobox.com
roentgen b75cab
 *
roentgen b75cab
 ******************************************************************************
roentgen b75cab
 * Copyright (c) 2000, Frank Warmerdam
roentgen b75cab
 *
roentgen b75cab
 * Permission to use, copy, modify, distribute, and sell this software and 
roentgen b75cab
 * its documentation for any purpose is hereby granted without fee, provided
roentgen b75cab
 * that (i) the above copyright notices and this permission notice appear in
roentgen b75cab
 * all copies of the software and related documentation, and (ii) the names of
roentgen b75cab
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
roentgen b75cab
 * publicity relating to the software without the specific, prior written
roentgen b75cab
 * permission of Sam Leffler and Silicon Graphics.
roentgen b75cab
 * 
roentgen b75cab
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
roentgen b75cab
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
roentgen b75cab
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
roentgen b75cab
 * 
roentgen b75cab
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
roentgen b75cab
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
roentgen b75cab
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
roentgen b75cab
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
roentgen b75cab
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
roentgen b75cab
 * OF THIS SOFTWARE.
roentgen b75cab
 ******************************************************************************
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
roentgen b75cab
#include <stdio.h></stdio.h>
roentgen b75cab
#include <string.h></string.h>
roentgen b75cab
#include <stdlib.h></stdlib.h>
roentgen b75cab
roentgen b75cab
#include "tiffio.h"
roentgen b75cab
roentgen b75cab
static char* usageMsg[] = {
roentgen b75cab
"usage: tiffset [options] filename",
roentgen b75cab
"where options are:",
roentgen b75cab
" -s <tagname> [count] <value>...   set the tag value",</value></tagname>
roentgen b75cab
" -d <dirno> set the directory",</dirno>
roentgen b75cab
" -sd <diroff> set the subdirectory",</diroff>
roentgen b75cab
" -sf <tagname> <filename>  read the tag value from file (for ASCII tags only)",</filename></tagname>
roentgen b75cab
NULL
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
usage(void)
roentgen b75cab
{
roentgen b75cab
	int i;
roentgen b75cab
	for (i = 0; usageMsg[i]; i++)
roentgen b75cab
		fprintf(stderr, "%s\n", usageMsg[i]);
roentgen b75cab
	exit(-1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static const TIFFField *
roentgen b75cab
GetField(TIFF *tiff, const char *tagname)
roentgen b75cab
{
roentgen b75cab
    const TIFFField *fip;
roentgen b75cab
roentgen b75cab
    if( atoi(tagname) > 0 )
roentgen b75cab
        fip = TIFFFieldWithTag(tiff, (ttag_t)atoi(tagname));
roentgen b75cab
    else
roentgen b75cab
        fip = TIFFFieldWithName(tiff, tagname);
roentgen b75cab
roentgen b75cab
    if (!fip) {
roentgen b75cab
        fprintf( stderr, "Field name \"%s\" is not recognised.\n", tagname );
roentgen b75cab
        return (TIFFField *)NULL;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
    return fip;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
int
roentgen b75cab
main(int argc, char* argv[])
roentgen b75cab
{
roentgen b75cab
    TIFF *tiff;
roentgen b75cab
    int  arg_index;
roentgen b75cab
roentgen b75cab
    if (argc < 2)
roentgen b75cab
        usage();
roentgen b75cab
roentgen b75cab
    tiff = TIFFOpen(argv[argc-1], "r+");
roentgen b75cab
    if (tiff == NULL)
roentgen b75cab
        return 2;
roentgen b75cab
roentgen b75cab
    for( arg_index = 1; arg_index < argc-1; arg_index++ ) {
roentgen b75cab
	if (strcmp(argv[arg_index],"-d") == 0 && arg_index < argc-2) {
roentgen b75cab
	    arg_index++;
roentgen b75cab
	    if( TIFFSetDirectory(tiff, atoi(argv[arg_index]) ) != 1 )
roentgen b75cab
            {
roentgen b75cab
               fprintf( stderr, "Failed to set directory=%s\n", argv[arg_index] );
roentgen b75cab
               return 6;
roentgen b75cab
            }
roentgen b75cab
	    arg_index++;
roentgen b75cab
	}
roentgen b75cab
	if (strcmp(argv[arg_index],"-sd") == 0 && arg_index < argc-2) {
roentgen b75cab
	    arg_index++;
roentgen b75cab
	    if( TIFFSetSubDirectory(tiff, atoi(argv[arg_index]) ) != 1 )
roentgen b75cab
            {
roentgen b75cab
               fprintf( stderr, "Failed to set sub directory=%s\n", argv[arg_index] );
roentgen b75cab
               return 7;
roentgen b75cab
            }
roentgen b75cab
	    arg_index++;
roentgen b75cab
	}
roentgen b75cab
        if (strcmp(argv[arg_index],"-s") == 0 && arg_index < argc-3) {
roentgen b75cab
            const TIFFField *fip;
roentgen b75cab
            const char *tagname;
roentgen b75cab
roentgen b75cab
            arg_index++;
roentgen b75cab
            tagname = argv[arg_index];
roentgen b75cab
            fip = GetField(tiff, tagname);
roentgen b75cab
roentgen b75cab
            if (!fip)
roentgen b75cab
                return 3;
roentgen b75cab
roentgen b75cab
            arg_index++;
roentgen b75cab
            if (TIFFFieldDataType(fip) == TIFF_ASCII) {
roentgen b75cab
                if (TIFFSetField(tiff, TIFFFieldTag(fip), argv[arg_index]) != 1)
roentgen b75cab
                    fprintf( stderr, "Failed to set %s=%s\n",
roentgen b75cab
                             TIFFFieldName(fip), argv[arg_index] );
roentgen b75cab
            } else if (TIFFFieldWriteCount(fip) > 0
roentgen b75cab
		       || TIFFFieldWriteCount(fip) == TIFF_VARIABLE) {
roentgen b75cab
                int     ret = 1;
roentgen b75cab
                short   wc;
roentgen b75cab
roentgen b75cab
                if (TIFFFieldWriteCount(fip) == TIFF_VARIABLE)
roentgen b75cab
                        wc = atoi(argv[arg_index++]);
roentgen b75cab
                else
roentgen b75cab
                        wc = TIFFFieldWriteCount(fip);
roentgen b75cab
roentgen b75cab
                if (argc - arg_index < wc) {
roentgen b75cab
                    fprintf( stderr,
roentgen b75cab
                             "Number of tag values is not enough. "
roentgen b75cab
                             "Expected %d values for %s tag, got %d\n",
roentgen b75cab
                             wc, TIFFFieldName(fip), argc - arg_index);
roentgen b75cab
                    return 4;
roentgen b75cab
                }
roentgen b75cab
                    
roentgen b75cab
                if (wc > 1) {
roentgen b75cab
                        int     i, size;
roentgen b75cab
                        void    *array;
roentgen b75cab
roentgen b75cab
                        switch (TIFFFieldDataType(fip)) {
roentgen b75cab
                                /*
roentgen b75cab
                                 * XXX: We can't use TIFFDataWidth()
roentgen b75cab
                                 * to determine the space needed to store
roentgen b75cab
                                 * the value. For TIFF_RATIONAL values
roentgen b75cab
                                 * TIFFDataWidth() returns 8, but we use 4-byte
roentgen b75cab
                                 * float to represent rationals.
roentgen b75cab
                                 */
roentgen b75cab
                                case TIFF_BYTE:
roentgen b75cab
                                case TIFF_ASCII:
roentgen b75cab
                                case TIFF_SBYTE:
roentgen b75cab
                                case TIFF_UNDEFINED:
roentgen b75cab
				default:
roentgen b75cab
                                    size = 1;
roentgen b75cab
                                    break;
roentgen b75cab
roentgen b75cab
                                case TIFF_SHORT:
roentgen b75cab
                                case TIFF_SSHORT:
roentgen b75cab
                                    size = 2;
roentgen b75cab
                                    break;
roentgen b75cab
roentgen b75cab
                                case TIFF_LONG:
roentgen b75cab
                                case TIFF_SLONG:
roentgen b75cab
                                case TIFF_FLOAT:
roentgen b75cab
                                case TIFF_IFD:
roentgen b75cab
                                case TIFF_RATIONAL:
roentgen b75cab
                                case TIFF_SRATIONAL:
roentgen b75cab
                                    size = 4;
roentgen b75cab
                                    break;
roentgen b75cab
roentgen b75cab
                                case TIFF_DOUBLE:
roentgen b75cab
                                    size = 8;
roentgen b75cab
                                    break;
roentgen b75cab
                        }
roentgen b75cab
roentgen b75cab
                        array = _TIFFmalloc(wc * size);
roentgen b75cab
                        if (!array) {
roentgen b75cab
                                fprintf(stderr, "No space for %s tag\n",
roentgen b75cab
                                        tagname);
roentgen b75cab
                                return 4;
roentgen b75cab
                        }
roentgen b75cab
roentgen b75cab
                        switch (TIFFFieldDataType(fip)) {
roentgen b75cab
                            case TIFF_BYTE:
roentgen b75cab
                                for (i = 0; i < wc; i++)
roentgen b75cab
                                    ((uint8 *)array)[i] = atoi(argv[arg_index+i]);
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_SHORT:
roentgen b75cab
                                for (i = 0; i < wc; i++)
roentgen b75cab
                                    ((uint16 *)array)[i] = atoi(argv[arg_index+i]);
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_SBYTE:
roentgen b75cab
                                for (i = 0; i < wc; i++)
roentgen b75cab
                                    ((int8 *)array)[i] = atoi(argv[arg_index+i]);
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_SSHORT:
roentgen b75cab
                                for (i = 0; i < wc; i++)
roentgen b75cab
                                    ((int16 *)array)[i] = atoi(argv[arg_index+i]);
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_LONG:
roentgen b75cab
                                for (i = 0; i < wc; i++)
roentgen b75cab
                                    ((uint32 *)array)[i] = atol(argv[arg_index+i]);
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_SLONG:
roentgen b75cab
                            case TIFF_IFD:
roentgen b75cab
                                for (i = 0; i < wc; i++)
roentgen b75cab
                                    ((uint32 *)array)[i] = atol(argv[arg_index+i]);
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_DOUBLE:
roentgen b75cab
                                for (i = 0; i < wc; i++)
roentgen b75cab
                                    ((double *)array)[i] = atof(argv[arg_index+i]);
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_RATIONAL:
roentgen b75cab
                            case TIFF_SRATIONAL:
roentgen b75cab
                            case TIFF_FLOAT:
roentgen b75cab
                                for (i = 0; i < wc; i++)
roentgen b75cab
                                    ((float *)array)[i] = (float)atof(argv[arg_index+i]);
roentgen b75cab
                                break;
roentgen b75cab
                            default:
roentgen b75cab
                                break;
roentgen b75cab
                        }
roentgen b75cab
                
roentgen b75cab
                        if (TIFFFieldPassCount(fip)) {
roentgen b75cab
                                ret = TIFFSetField(tiff, TIFFFieldTag(fip),
roentgen b75cab
                                                   wc, array);
roentgen b75cab
                        } else if (TIFFFieldTag(fip) == TIFFTAG_PAGENUMBER
roentgen b75cab
				   || TIFFFieldTag(fip) == TIFFTAG_HALFTONEHINTS
roentgen b75cab
				   || TIFFFieldTag(fip) == TIFFTAG_YCBCRSUBSAMPLING
roentgen b75cab
				   || TIFFFieldTag(fip) == TIFFTAG_DOTRANGE) {
roentgen b75cab
       				if (TIFFFieldDataType(fip) == TIFF_BYTE) {
roentgen b75cab
					ret = TIFFSetField(tiff, TIFFFieldTag(fip),
roentgen b75cab
						((uint8 *)array)[0], ((uint8 *)array)[1]);
roentgen b75cab
				} else if (TIFFFieldDataType(fip) == TIFF_SHORT) {
roentgen b75cab
					ret = TIFFSetField(tiff, TIFFFieldTag(fip),
roentgen b75cab
						((uint16 *)array)[0], ((uint16 *)array)[1]);
roentgen b75cab
				}
roentgen b75cab
			} else {
roentgen b75cab
                                ret = TIFFSetField(tiff, TIFFFieldTag(fip),
roentgen b75cab
                                                   array);
roentgen b75cab
                        }
roentgen b75cab
roentgen b75cab
                        _TIFFfree(array);
roentgen b75cab
                } else {
roentgen b75cab
                        switch (TIFFFieldDataType(fip)) {
roentgen b75cab
                            case TIFF_BYTE:
roentgen b75cab
                            case TIFF_SHORT:
roentgen b75cab
                            case TIFF_SBYTE:
roentgen b75cab
                            case TIFF_SSHORT:
roentgen b75cab
                                ret = TIFFSetField(tiff, TIFFFieldTag(fip),
roentgen b75cab
                                                   atoi(argv[arg_index++]));
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_LONG:
roentgen b75cab
                            case TIFF_SLONG:
roentgen b75cab
                            case TIFF_IFD:
roentgen b75cab
                                ret = TIFFSetField(tiff, TIFFFieldTag(fip),
roentgen b75cab
                                                   atol(argv[arg_index++]));
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_DOUBLE:
roentgen b75cab
                                ret = TIFFSetField(tiff, TIFFFieldTag(fip),
roentgen b75cab
                                                   atof(argv[arg_index++]));
roentgen b75cab
                                break;
roentgen b75cab
                            case TIFF_RATIONAL:
roentgen b75cab
                            case TIFF_SRATIONAL:
roentgen b75cab
                            case TIFF_FLOAT:
roentgen b75cab
                                ret = TIFFSetField(tiff, TIFFFieldTag(fip),
roentgen b75cab
                                                   (float)atof(argv[arg_index++]));
roentgen b75cab
                                break;
roentgen b75cab
                            default:
roentgen b75cab
                                break;
roentgen b75cab
                        }
roentgen b75cab
                }
roentgen b75cab
roentgen b75cab
                if (ret != 1)
roentgen b75cab
                    fprintf(stderr, "Failed to set %s\n", TIFFFieldName(fip));
roentgen b75cab
                arg_index += wc;
roentgen b75cab
            }
roentgen b75cab
        } else if (strcmp(argv[arg_index],"-sf") == 0 && arg_index < argc-3) {
roentgen b75cab
            FILE    *fp;
roentgen b75cab
            const TIFFField *fip;
roentgen b75cab
            char    *text;
roentgen b75cab
            size_t  len;
roentgen b75cab
roentgen b75cab
            arg_index++;
roentgen b75cab
            fip = GetField(tiff, argv[arg_index]);
roentgen b75cab
roentgen b75cab
            if (!fip)
roentgen b75cab
                return 3;
roentgen b75cab
roentgen b75cab
            if (TIFFFieldDataType(fip) != TIFF_ASCII) {
roentgen b75cab
                fprintf( stderr,
roentgen b75cab
                         "Only ASCII tags can be set from file. "
roentgen b75cab
                         "%s is not ASCII tag.\n", TIFFFieldName(fip) );
roentgen b75cab
                return 5;
roentgen b75cab
            }
roentgen b75cab
roentgen b75cab
            arg_index++;
roentgen b75cab
            fp = fopen( argv[arg_index], "rt" );
roentgen b75cab
            if(fp == NULL) {
roentgen b75cab
                perror( argv[arg_index] );
roentgen b75cab
                continue;
roentgen b75cab
            }
roentgen b75cab
roentgen b75cab
            text = (char *) malloc(1000000);
roentgen b75cab
            len = fread( text, 1, 999999, fp );
roentgen b75cab
            text[len] = '\0';
roentgen b75cab
roentgen b75cab
            fclose( fp );
roentgen b75cab
roentgen b75cab
            if(TIFFSetField( tiff, TIFFFieldTag(fip), text ) != 1) {
roentgen b75cab
                fprintf(stderr, "Failed to set %s from file %s\n", 
roentgen b75cab
                        TIFFFieldName(fip), argv[arg_index]);
roentgen b75cab
            }
roentgen b75cab
roentgen b75cab
            _TIFFfree( text );
roentgen b75cab
            arg_index++;
roentgen b75cab
        } else {
roentgen b75cab
            fprintf(stderr, "Unrecognised option: %s\n",
roentgen b75cab
                    argv[arg_index]);
roentgen b75cab
            usage();
roentgen b75cab
        }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
    TIFFRewriteDirectory(tiff);
roentgen b75cab
    TIFFClose(tiff);
roentgen b75cab
    return 0;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/* vim: set ts=8 sts=8 sw=8 noet: */
roentgen b75cab
/*
roentgen b75cab
 * Local Variables:
roentgen b75cab
 * mode: c
roentgen b75cab
 * c-basic-offset: 8
roentgen b75cab
 * fill-column: 78
roentgen b75cab
 * End:
roentgen b75cab
 */