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