ftp.nice.ch/pub/next/unix/graphics/imtools.2.0.N.bs.tar.gz#/imtools/src/imcopy.c

This is imcopy.c in view mode; [Download] [Up]

/**
 **	$Header: /import/dev-vis/image/imtools/v2.0/imtools/src/RCS/imcopy.c,v 1.1 91/10/03 13:19:44 nadeau Exp $
 **	Copyright (c) 1989, 1990  San Diego Supercomputer Center (SDSC)
 **		San Diego, California, USA
 **
 **	Users and possessors of this source code are hereby granted a
 **	nonexclusive, royalty-free copyright and design patent license to
 **	use this code in individual software.  License is not granted for
 **	commercial resale, in whole or in part, without prior written
 **	permission from SDSC.  This source is provided "AS IS" without express
 **	or implied warranty of any kind.
 **
 **	For further information contact:
 **		E-Mail:		info@sds.sdsc.edu
 **
 **		Surface Mail:	Information Center
 **				San Diego Supercomputer Center
 **				P.O. Box 85608
 **				San Diego, CA  92138-5608
 **				(619) 534-5000
 **/

#define HEADER	"    $Header: /import/dev-vis/image/imtools/v2.0/imtools/src/RCS/imcopy.c,v 1.1 91/10/03 13:19:44 nadeau Exp $"

/**
 **  FILE
 **	imcopy.c	-  Copy a part of an image
 **
 **  PROJECT
 **	IM		-  Image Manipulation Tools
 **
 **  DESCRIPTION
 **	imcopy copies a piece of an image into a new file.
 **
 **  PUBLIC CONTENTS
 **			d =defined constant
 **			f =function
 **			m =defined macro
 **			t =typedef/struct/union
 **			v =variable
 **			? =other
 **
 **	main		f  main program
 **
 **  PRIVATE CONTENTS
 **	toolCommand	v  tool-specific tool info
 **	toolHelp	v  tool-specific help
 **	toolOptions	v  tool-specific options
 **	toolEquivs	v  tool-specific equivalent keywords
 **
 **	toolInFilename	v  the name of the input file (could be 'stdin')
 **	toolOutFilename	v  the name of the output file (could be 'stdout')
 **
 **	toolInFormat	v  the name of the input file's format (could be '\0')
 **	toolOutFormat	v  the name of the output file's format (could be '\0')
 **
 **	toolInTable	v  a table for the storage of data read in
 **	toolFlagsTable	v  a table for the storage of read/write flags
 **
 **	toolPosX	v  X image position
 **	toolPosY	v  Y image position
 **	toolCenterX	v  Flag X direction centering
 **	toolCenterY	v  Flag Y direction centering
 **	toolSizeW	v  Image width
 **	toolSizeH	v  Image height
 **
 **	toolInit	f  initialize things for the tool
 **
 **  HISTORY
 **	$Log:	imcopy.c,v $
 **	Revision 1.1  91/10/03  13:19:44  nadeau
 **	Initial revision
 **	
 **
 **/

#include "imtools.h"


extern void toolInit( );		/* Initialize things		*/





/*
 *  GLOBALS
 *	toolCommand		-  tool-specific tool info
 *	toolHelp		-  tool-specific help
 *	toolOptions		-  tool-specific options
 *	toolEquivs		-  tool-specific equivalent keywords
 *
 *  DESCRIPTION
 *	toolCommand describes the command to the arg package.
 *
 *	toolHelp is the tool-specific help for the tool.  It will be
 *	concatenated with the generic image tools help message and
 *	added to the toolCommand structure as the help string to be
 *	printed after the option listing.
 *
 *	toolOptions is the tool-specific option list.  It will be merged
 *	with the generic image tools options, and the list of image file
 *	format names supported by the library.  This larger option list
 *	is then used as the list of options supported by the tool.
 *
 *	toolEquivs is the tool-specific option equivalent keyword list.
 *	It will be merged with the generic image tools equivs.  This large
 *	equivs list is then used as the list of equivs supported by the tool.
 */

private ArgCommand toolCommand =
{
	/* command name */		"imcopy",

	/* major version # */		IMTOOLSMAJOR,
	/* minor version # */		IMTOOLSMINOR,
	/* subminor version # */	IMTOOLSSUBMINOR,

	/* -help pre-option list information				*/
"%command copies a portion of an input image into a new file.  Input and\n\
output files may have different image file formats.\n\
",
	/* -help post-option list information				*/
	NULL,				/* filled in later on		*/

	/* -fullhelp pre-option list information			*/
	NULL,				/* Use same message as for -help*/
	/* -fullhelp post-option list information			*/
	NULL,				/* filled in later on		*/

	ARGFNONE,			/* No special flags		*/
	"[options...] infilename outfilename",
	"[options...] infilename outfilename",
	"SDSC Image Tools, October 1991.",
	"Copyright (c) 1989-1991  San Diego Supercomputer Center (SDSC), CA, USA",
	NULL,				/* filled in later on		*/
	NULL,				/* filled in later on		*/
};

private char *toolHelp = "\n\
Typical Invocations:\n\
    Clip out a 100x100 pixel image whose upper-left corner is at (10,20),\n\
    and save the clipped piece into an HDF file:\n\
        %command infile.pix -xpos 10 -ypos 20 -xsize 100 -ysize 100 outfile.hdf\n\
    Clip out the top 5 scanlines and save them in a Compuserve GIF file:\n\
        %command infile.pix -ypos 0 -ysize 5 outfile.gif\n\
    Clip out a centered 100x100 pixel region and save it as a TIFF file:\n\
        %command infile.hdf -xsize 100 -ysize 100 outfile.tiff\n\
";

private char *toolFullHelp = "\n\
Files:\n\
    -infile selects the file whose images are to be copied.  -outfile\n\
    selects the file into which to write the resulting image copies.  The\n\
    input file is unaltered.\n\
\n\
Copying:\n\
    A region of each image in the input file is copied out into a new image\n\
    and placed into the output file.\n\
\n\
    -xsize and -ysize select the size of the region to copy.  Both default to\n\
    the full width and height of the image.\n\
\n\
    -xposition and -yposition select the upper-left corner of the region to\n\
    copy and must both be within the bounds of the source image.  (0,0) is\n\
    upper-left corner of the image.  Both default to a position that centers\n\
    the copy region within the source image.\n\
";

private char *toolNote = "\n\
Additional Help:\n\
    This is an abbreviated help listing.  For a full listing of options,\n\
    including a list of image file formats supported, type:\n\
        %command -fullhelp\n\
";

#define TOOLNOPTIONS	7
private ArgOption toolOptions[TOOLNOPTIONS] =
{
	{ "infile", "image_filename", "Specify an input image file name",
	  ARGFREQUIRED | ARGFIMPKEYWORD, 1, 1, ARGTSTRING },

	{ "outfile", "image_filename", "Specify an output image file name",
	  ARGFREQUIRED | ARGFIMPKEYWORD, 1, 1, ARGTSTRING },

	{ "xposition", "x", "Specify left edge of copy region",
	  ARGFNONE, 1, 1, ARGTINT },

	{ "yposition", "y", "Specify top edge of copy region",
	  ARGFNONE, 1, 1, ARGTINT },

	{ "xsize", "x", "Specify width of copy region in pixels",
	  ARGFNONE, 1, 1, ARGTINT },

	{ "ysize", "y", "Specify height of copy region in pixels",
	  ARGFNONE, 1, 1, ARGTINT },

	{ "verbose", NULL, "Be verbose",
	  ARGFFULLHELP, 0, 0, ARGTNONE },
};

#define TOOLNEQUIVS	0
#if TOOLNEQUIVS == 0
private ArgEquiv *toolEquivs;
#else
private ArgEquiv toolEquivs[TOOLNEQUIVS] =
{
};
#endif





/*
 *  GLOBALS
 *	toolInFilename	-  the name of the input file (could be 'stdin')
 *	toolOutFilename	-  the name of the output file (could be 'stdout')
 *
 *	toolInFormat	-  the name of the input file's format (could be NULL)
 *	toolOutFormat	-  the name of the output file's format (could be NULL)
 *
 *	toolInTable	-  a table for the storage of data read in
 *	toolFlagsTable	-  a table for the storage of read/write flags
 *
 *	toolPosX	-  X image position
 *	toolPosY	-  Y image position
 *	toolCenterX	-  Flag X direction centering
 *	toolCenterY	-  Flag Y direction centering
 *	toolSizeW	-  Image width
 *	toolSizeH	-  Image height
 *
 *  DESCRIPTION
 *	Data held by these variables is used throughout the tool.
 */

private char      toolInFilename[1024];	/* Input file name		*/
private char      toolInFormat[1024];	/* Input file's format name	*/

private char      toolOutFilename[1024];/* Output file name		*/
private char      toolOutFormat[1024];	/* Output file's format name	*/

private TagTable *toolInTable;	/* Data tag table		*/
private TagTable *toolFlagsTable;	/* Flags tag table		*/

private int	  toolPosX;		/* X Position			*/
private int	  toolPosY;		/* Y Position			*/
private boolean   toolCenterX;		/* Center in X			*/
private boolean   toolCenterY;		/* Center in Y			*/
private int	  toolSizeW;		/* Width			*/
private int	  toolSizeH;		/* Height			*/





/*
 *  FUNCTION
 *	main	-  main program
 *
 *  DESCRIPTION
 *	Control things:
 *		-  Initialize things (parse arguments and set up tables).
 *		-  Read in the input file (put data into data table).
 *		-  Copy part of each image.
 *		-  Replace the data table images with their smaller copy pieces.
 *		-  Write out the output file (get data from data table).
 *	That's about it.
 *
 *  NOTES
 *	This 'main' is pretty much the same for each of the image tools.
 *	Differences between tools include:
 *		-  the number of input files read in
 *		-  the number of output files written out
 *		-  the actions taken on the data between read and write
 */

main( argc, argv )
	int argc;			/* Argument count		*/
	char *argv[];			/* Argument vector		*/
{
	int         nInVfb;		/* Number of images in file	*/
	int         i;			/* Counter			*/

	TagEntry   *dataEntry;		/* Entry from data table	*/

	ImVfb      *sourceVfb;		/* Source image			*/
	ImVfb      *regionVfb;		/* Region image			*/
	int         regionFields;	/* Region fields		*/
	int	    regionW;		/* Region width			*/
	int	    regionH;		/* Region height		*/


	/*
	 *  Initialize things:
	 *	-  Prepare the arg parsing data, then parse the command-line.
	 *	-  Prepare the flags table based upon command-line args.
	 *	-  Determine the file formats for input and output files.
	 */
	toolInit( argc, argv );


	/*
	 *  Read in the input file.
	 *	-  Open the file (or stdin) and read data into the data table.
	 */
	ImToolsFileRead( toolInFilename, toolInFormat, toolFlagsTable,
		toolInTable );


	/*
	 *  Check for errors
	 *	-  no input images
	 */
	nInVfb = TagTableQNEntry( toolInTable, "image vfb" );
	if ( nInVfb == 0 )
	{
		fprintf( stderr, "%s: Input file contains no images!\n",
			ImToolsProgram );
		exit( 1 );
	}


	/*
	 *  Copy!
	 *	-  Walk the data table looking for images.  For each one found,
	 *	   get the VFB, copy the region out of it, and replace the
	 *	   original with the copy back in the same data table.
	 */
	for ( i = 0; i < nInVfb; i++ )
	{
		/*
		 *  Get the next image out of the data table.
		 */
		dataEntry = TagTableQDirect( toolInTable, "image vfb", i );
		TagEntryQValue( dataEntry, &sourceVfb );


		/*
		 *  Compute the copy region position if asked to center.
		 */
		if ( toolCenterX )
		{
			if ( toolSizeW == -1 )
				toolPosX = 0;
			else
				toolPosX = (ImVfbQWidth( sourceVfb ) - toolSizeW) / 2;
		}
		else if ( toolPosX > ImVfbQWidth( sourceVfb ) )
		{
			fprintf( stderr, "%s: Copy position is out of bounds for image %d of %d.\n",
				ImToolsProgram, i+1, nInVfb );
			fprintf( stderr, "%s: Entire image copied.\n",
				ImToolsProgram );
			continue;
		}

		if ( toolCenterY )
		{
			if ( toolSizeH == -1 )
				toolPosY = 0;
			else
				toolPosY = (ImVfbQHeight( sourceVfb ) - toolSizeH) / 2;
		}
		else if ( toolPosY > ImVfbQHeight( sourceVfb ) )
		{
			fprintf( stderr, "%s: Copy position is out of bounds for image %d of %d.\n",
				ImToolsProgram, i+1, nInVfb );
			fprintf( stderr, "%s: Entire image copied.\n",
				ImToolsProgram );
			continue;
		}


		/*
		 *  Determine the dimensions of the region to copy.
		 */
		if ( toolSizeW == -1 )
		{
			/*
			 *  No region given on the command-line.  Take
			 *  everything from the starting position up to the
			 *  right edge of the image.
			 */
			regionW = ImVfbQWidth( sourceVfb )  - toolPosX;
		}
		else
		{
			/*
			 *  Region size was given on the command-line.
			 *  Clip it to the edge of this image.
			 */
			regionW = toolSizeW;
			if ( regionW > ImVfbQWidth( sourceVfb ) - toolPosX )
				regionW = ImVfbQWidth( sourceVfb ) - toolPosX;
		}
		if ( toolSizeH == -1 )
		{
			/*
			 *  No region given on the command-line.  Take
			 *  everything from the starting position up to the
			 *  bottom edge of the image.
			 */
			regionH = ImVfbQHeight( sourceVfb ) - toolPosY;
		}
		else
		{
			/*
			 *  Region size was given on the command-line.
			 *  Clip it to the edge of this image.
			 */
			regionH = toolSizeH;
			if ( regionH > ImVfbQHeight( sourceVfb ) - toolPosY )
				regionH = ImVfbQHeight( sourceVfb ) - toolPosY;
		}
		regionFields = ImVfbQFields( sourceVfb );


		/*
		 *  Check that the resulting copy region is reasonable.
		 */
		if ( regionW <= 0 || regionH <= 0 )
		{
			fprintf( stderr, "%s: Copy size is zero for image %d of %d.\n",
				ImToolsProgram, i+1, nInVfb );
			fprintf( stderr, "%s: Entire image copied.\n",
				ImToolsProgram );
			continue;
		}


		/*
		 *  Copy the region into a new VFB.  Give it the same CLT
		 *  (if any) as the source image.
		 */
		if ( ImToolsVerbose )
			fprintf( stderr, "%s: Copying region at (%d,%d) of size (%d,%d) for image %d of %d\n",
				ImToolsProgram,
				toolPosX, toolPosY, regionW, regionH,
				i + 1, nInVfb );
		regionVfb = ImVfbCopy( sourceVfb,	/* Use this VFB	*/
			toolPosX, toolPosY,		/* Start here	*/
			regionW, regionH, regionFields,	/* Take this much*/
			IMVFBNEW,			/* Make a new VFB*/
			0, 0 );				/* Put it here	*/
		if ( regionVfb == IMVFBNULL )
		{
			ImPError( ImToolsProgram );
			fprintf( stderr, "%s: Couldn't copy image region for image %d of %d.\n",
				ImToolsProgram, i + 1, nInVfb );
			fprintf( stderr, "%s: Entire image copied.\n",
				ImToolsProgram );
			continue;
		}
		ImVfbSClt( regionVfb, ImVfbQClt( sourceVfb ) );


		/*
		 *  Replace the source image with the region image in the same
		 *  data table.
		 */
		TagTableReplace( toolInTable,
			TagEntryQNthEntry( dataEntry ),
			TagEntryAlloc( "image vfb", POINTER, &regionVfb ) );


		/*
		 *  Destroy the source VFB.
		 */
		ImVfbFree( sourceVfb );
	}


	/*
	 *  Write out the output file.
	 *	-  Open the file (or stdout) and write the data in the data
	 *	   table.  Upon failure, remove the bad output file.
	 */
	ImToolsFileWrite( toolOutFilename, toolOutFormat, toolFlagsTable,
		toolInTable );


	exit( 0 );
}





/*
 *  FUNCTION
 *	toolInit	-  initialize things for the tool
 *
 *  DESCRIPTION
 *	The tool's argument parsing data structures are set up to include:
 *		- the full help message (generic help + tool-specific help)
 *		- the full option list (generic options + tool-specific options)
 *		- the full equivs list (generic equivs + tool-specific equivs)
 *
 *	Command-line arguments are then parsed.  The results are used to
 *	set up the flags table (the generic -out* options).
 *
 *	Input and output file's names and formats are determined from the
 *	command-line arguments.
 *
 *  NOTES
 *	This function is included in most of the image tools and differs
 *	only in slight ways.  Typical differences include:
 *		-  the number of input and output file names found
 *		-  the number of input and output file formats found
 *		-  the number of command-line arg flags checked for
 */

private void				/* Returns nothing		*/
toolInit( argc, argv )
	int argc;			/* Argument count		*/
	char *argv[ ];			/* Argument vector		*/
{
	int	    i;			/* Counter			*/
	int	    noccur;		/* Number of option occurrences	*/
	int         nOpt;		/* Number of options		*/
	int         nEquiv;		/* Number of equivalences	*/
	ArgOption  *options1;		/* Argument options		*/
	ArgOption  *options;		/* Argument options		*/
	ArgEquiv   *equivs1;		/* Argument equivalent keywords	*/
	ArgEquiv   *equivs;		/* Argument equivalent keywords	*/

	char       *tmp;		/* Temporary string holder	*/
	char       *tmpFormat;		/* Tmp format name		*/


	/*
	 *  Save the name of the program, as invoked.
	 */
	ImToolsProgram = argv[0];


	/*
	 *  Make a data table to hold the incomming data.
	 */
	if ( (toolInTable = TagTableAlloc( )) == TAGTABLENULL )
	{
		TagPError( ImToolsProgram );
		exit( 1 );
	}


	/*
	 *  Use the standard Image Tools user registration and feedback forms.
	 */
	toolCommand.arg_register = ImToolsRegister;
	toolCommand.arg_feedback = ImToolsFeedback;


	/*
	 *  Allocate space for the total help string for the tool.  Copy the
	 *  tool-specific help in, then concatenate on the generic help text
	 *  used by most of the image tools.
	 */
	if ( (tmp = (char *)malloc( sizeof( char ) * (strlen( toolNote ) +
		strlen( toolHelp ) + 1) )) == NULL )
	{
		perror( ImToolsProgram );
		exit( 1 );
	}
	strcpy( tmp, toolHelp );
	strcat( tmp, toolNote );
	toolCommand.arg_help2 = tmp;

	if ( (tmp = (char *)malloc( sizeof( char ) * (strlen( ImToolsBaseHelp) +
		strlen( toolHelp ) + strlen( toolFullHelp ) + 1) )) == NULL )
	{
		perror( ImToolsProgram );
		exit( 1 );
	}
	strcpy( tmp, toolHelp );
	strcat( tmp, toolFullHelp );
	strcat( tmp, ImToolsBaseHelp );
	toolCommand.arg_fullhelp2 = tmp;


	/*
	 *  Build up an option list by merging the tool-specific options,
	 *  the standard (base) tool options, and those for the various
	 *  image file formats.
	 */
	nOpt = ImToolsMergeOptions( TOOLNOPTIONS, toolOptions,
		IMTOOLSNBASEOPTIONS, ImToolsBaseOptions, &options1 );
	if ( (nOpt = ImFileFormatOptions( nOpt, options1, &options )) == -1)
	{
		ImPError( ImToolsProgram );
		exit( 1 );
	}


	/*
	 *  Build up an equivalent keyword list by merging the tool-specific
	 *  equivalences, the standard (base) tool equivalences, and those
	 *  for the various image file formats.
	 */
	nEquiv = ImToolsMergeEquivs( TOOLNEQUIVS, toolEquivs,
		 IMTOOLSNBASEEQUIVS, ImToolsBaseEquivs, &equivs1 );
	if ( (nEquiv = ImFileFormatEquivs( nEquiv, equivs1, &equivs )) == -1)
	{
		ImPError( ImToolsProgram );
		exit( 1 );
	}


	/*
	 *  Parse the command line!
	 */
	nOpt = ArgParse( argc, argv, &toolCommand, nOpt, options,
		nEquiv, equivs );
	if ( ArgQNOccur( "verbose" ) != 0 )
		ImToolsVerbose = TRUE;


	/*
	 *  Get the image position and size selections.
	 */
	toolPosX = toolPosY = 0;
	toolCenterX = toolCenterY = TRUE;
	if ( ArgQNOccur( "xposition" ) != 0 )
	{
		toolPosX = ArgQValue( "xposition", 0, 0 )->arg_i;
		if ( toolPosX < 0 )
		{
			fprintf( stderr, "%s: -xposition must be positive\n",
				ImToolsProgram );
			exit( 1 );
		}
		toolCenterX = FALSE;
	}
	if ( ArgQNOccur( "yposition" ) != 0 )
	{
		toolPosY = ArgQValue( "yposition", 0, 0 )->arg_i;
		if ( toolPosY < 0 )
		{
			fprintf( stderr, "%s: -yposition must be positive\n",
				ImToolsProgram );
			exit( 1 );
		}
		toolCenterY = FALSE;
	}

	toolSizeW = toolSizeH = -1;
	if ( ArgQNOccur( "xsize" ) != 0 )
	{
		toolSizeW = ArgQValue( "xsize", 0, 0 )->arg_i;
		if ( toolSizeW <= 0 )
		{
			fprintf( stderr, "%s: -xsize must be positive\n",
				ImToolsProgram );
			exit( 1 );
		}
	}
	if ( ArgQNOccur( "ysize" ) != 0 )
	{
		toolSizeH = ArgQValue( "ysize", 0, 0 )->arg_i;
		if ( toolSizeH <= 0 )
		{
			fprintf( stderr, "%s: -ysize must be positive\n",
				ImToolsProgram );
			exit( 1 );
		}
	}


	/*
	 *  Set up the flags table based upon command-line arguments.
	 *  This is primarily derived from the -out* directives part of the
	 *  standard image tool option set (see ImToolsBaseOptions above).
	 *  Also included are flags to direct error messages to stderr and
	 *  a flag giving the program's name for later use in error messages.
	 */
	toolFlagsTable = ImToolsBuildFlagsTable( );


	/*
	 *  Get the input file's name (-infile), and search backwards in the
	 *  command-line option list to find the last format selection (if
	 *  any).  Stop the search on the beginning of the command-line, or
	 *  on -outfile.
	 */
	strcpy( toolInFilename, ArgQValue( "infile", 0, 0 )->arg_s );
	tmpFormat = NULL;
	for ( i = ArgQOccurOpt( "infile", 0 ) - 1; i >= 0; i-- )
	{
		tmp = ArgQOpt( i, &noccur );


		/*
		 *  Stop looking backward when we reach any other file name
		 *  argument.
		 */
		if ( strcmp( tmp, "outfile" ) == 0 )
			break;


		/*
		 *  Skip it if it isn't the name of a file format.
		 */
		if ( !ImToolsIsFormat( tmp ) )
			continue;


		if ( tmpFormat != NULL )
		{
			fprintf( stderr, "%s:  Only 1 file format selection may precede -infile.\n",
				ImToolsProgram );
			exit( 1 );
		}
		tmpFormat = tmp;
	}
	if ( tmpFormat == NULL )
		*toolInFormat = '\0';
	else
		strcpy( toolInFormat, tmpFormat );


	/*
	 *  Get the output file's name (-outfile), and search backwards in the
	 *  command-line option list to find the last format selection (if
	 *  any).  Stop the search on the beginning of the command-line, or
	 *  on -infile.
	 */
	strcpy( toolOutFilename, ArgQValue( "outfile", 0, 0 )->arg_s );
	tmpFormat = NULL;
	for ( i = ArgQOccurOpt( "outfile", 0 ) - 1; i >= 0; i-- )
	{
		tmp = ArgQOpt( i, &noccur );


		/*
		 *  Stop looking backward when we reach any other file name
		 *  argument.
		 */
		if ( strcmp( tmp, "infile" ) == 0 )
			break;


		/*
		 *  Skip it if it isn't the name of a file format.
		 */
		if ( !ImToolsIsFormat( tmp ) )
			continue;


		if ( tmpFormat != NULL )
		{
			fprintf( stderr, "%s:  Only 1 file format selection may precede -outfile.\n",
				ImToolsProgram );
			exit( 1 );
		}
		tmpFormat = tmp;
	}
	if ( tmpFormat == NULL )
		*toolOutFormat = '\0';
	else
		strcpy( toolOutFormat, tmpFormat );
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.