#include "MagickWand/studio.h"
#include "MagickWand/MagickWand.h"
#include "MagickWand/magick-wand-private.h"
+#include "MagickWand/magick-cli-private.h"
+#include "MagickWand/magick-cli.h"
+#include "MagickWand/operation.h"
#include "MagickCore/memory_.h"
#include "MagickCore/string-private.h"
-#include "MagickWand/operation.h"
#include "MagickCore/utility-private.h"
#include "MagickCore/version.h"
\f
+/* verbose debugging,
+ 1 - option type
+ 2 - source of option
+ 3 - mnemonic lookup */
#define MagickCommandDebug 0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetScriptToken() is fairly general, finite state token parser. That will
-% divide a input file stream into tokens, in a way that is almost identical
-% to a UNIX shell.
-%
-% It returns 'MagickTrue' if a token was found. Even in the special case of
-% a empty token followed immediatally by a EOF. For example: ''{EOF}
-%
-% A token is returned immediatally the end of token is found. That is
-% parsing is purely character by character, and not line-by-line. This
-% should allow for mixed stream of tokens (options), and other data (images)
-% without problems. Assuming the other data has a well defined End-Of-Data
-% handling (see complex example below).
+% divide a input file stream into tokens, in a way that is as close to a
+% UNIX shell, as is feasable. Only shell variable, and command
+% substitutions will not be performed.
%
% Tokens are white space separated, and may be quoted, or even partially
% quoted by either single or double quotes, or the use of backslashes,
%
% For example: This\ is' a 'single" token"
%
+% A token is returned immediatally the end of token is found. That is as soon
+% as a ending white-space or EOF condition was determined. That is to say
+% the file stream is parsed purely character-by-character, regardless any
+% buffering constraints set by the system.
+%
+% The function will return 'MagickTrue' if a valid token was found, while
+% the token status will be set accordingally to 'OK' or 'EOF', according to
+% the cause of the end of token. The token may be an empty string if the
+% input was a quoted empty string. Other error conditions return a value of
+% MagickFalse, indicating any token found was incomplete due to the error
+% condition.
+%
% Single quotes will preserve all characters including backslashes. Double
% quotes will also preserve backslashes unless escaping a double quote,
% or another backslashes. Other shell meta-characters are not treated as
% For example Quoting the quote chars:
% \' "'" \" '"' "\"" \\ '\' "\\"
%
-% Comments start with a '#' character at the start of a new token (generally
-% at start of a line, or after a unquoted white space charcater) and continue
-% to the end of line. The are simply ignored. You can escape a comment '#'
-% character to return a token that starts with such a character.
-%
-% More complex example...
-% Sending a PGM image in the middle of a standard input script.
+% Outside quotes, backslash characters will make spaces, tabs and quotes part
+% of a token returned. However a backslash at the end of a line (and outside
+% quotes) will cause the newline to be completely ignored (as per the shell
+% line continuation).
%
-% magick -script - <<END
-% # read a stdin in-line image...
-% "pgm:-[0]" P2 2 2 3 0 1 1 2
-% # continue processing that image
-% -resize 100x100
-% -write enlarged.png
-% END
-%
-% Only a single space character separates the 'image read' from the
-% 'image data' after which the next operation is read. This only works
-% for image data formats with a well defined length or End-of-Data marker
-% such as MIFF, and PbmPlus file formats.
+% Comments start with a '#' character at the start of a new token, will be
+% completely ignored upto the end of line, regardless of any backslash at the
+% end of the line. You can escape a comment '#', using quotes or backlsashes
+% just as you can in a shell.
%
% The format of the MagickImageCommand method is:
%
SaveChar('\\');
break;
}
+ if (c == '\n')
+ switch (state)
+ {
+ case IN_COMMENT:
+ state=IN_WHITE; /* end comment */
+ case IN_WHITE:
+ case IN_TOKEN:
+ continue; /* line continuation (outside quotes and comment) */
+ }
switch (state)
{
case IN_WHITE:
% %
% %
% %
-+ P r o c e s s S p e c i a l O p t i o n %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% ProcessSpecialOption() Apply certian options that are specific to Shell
-% API interface. Specifically reading images and handling image and
-% image_info (settings) stacks.
-%
-% The format of the ProcessSpecialOption method is:
-%
-% void ProcessSpecialOption(MagickWand *wand,const char *option,
-% const char *arg, ProcessOptionFlags process_flags )
-%
-% A description of each parameter follows:
-%
-% o wand: the main CLI Wand to use.
-%
-% o option: The special option (with any switch char) to process
-%
-% o arg: Argument for option, if required
-%
-% o process_flags: Wether to process specific options or not.
-%
-*/
-WandExport void ProcessSpecialOption(MagickWand *wand,
- const char *option, const char *arg, ProcessOptionFlags process_flags)
-{
- if ( LocaleCompare("-read",option) == 0 )
- {
- Image *
- new_images;
-
- CopyMagickString(wand->image_info->filename,arg,MaxTextExtent);
- if (wand->image_info->ping != MagickFalse)
- new_images=PingImages(wand->image_info,wand->exception);
- else
- new_images=ReadImages(wand->image_info,wand->exception);
- AppendImageToList(&wand->images, new_images);
- return;
- }
- if (LocaleCompare("-sans",option) == 0)
- return;
- if (LocaleCompare("-sans0",option) == 0)
- return;
- if (LocaleCompare("-sans2",option) == 0)
- return;
- if (LocaleCompare("-noop",option) == 0)
- return;
-
-#if 0
- if (LocaleCompare(option,"(") == 0)
- // push images/settings
- if (LocaleCompare(option,")") == 0)
- // pop images/settings
- if (LocaleCompare(option,"respect_parenthesis") == 0)
- // adjust stack handling
- // Other 'special' options this should handle
- // "region" "clone" "list" "version"
- // It does not do "exit" however as due to its side-effect requirements
-
- if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
- MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);
-#endif
-}
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
+ P r o c e s s S c r i p t O p t i o n s %
% %
% %
%
% The format of the ProcessScriptOptions method is:
%
-% void ProcessScriptOptions(MagickWand *wand,int argc,char **argv)
+% void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv)
%
% A description of each parameter follows:
%
-% o wand: the main CLI Wand to use.
+% o cli_wand: the main CLI Wand to use.
%
% o argc: the number of elements in the argument vector.
%
%
*/
#define MagickExceptionScript(severity,tag,arg,line,col) \
- (void) ThrowMagickException(wand->exception,GetMagickModule(),severity,tag, \
- "'%s' : Line %u Column %u of script \"%s\"", arg, line, col, wand->name);
+ (void) ThrowMagickException(cli_wand->wand.exception,GetMagickModule(), \
+ severity,tag, "'%s' : Line %u Column %u of script \"%s\"", \
+ arg, line, col, cli_wand->wand.name);
-WandExport void ProcessScriptOptions(MagickWand *wand,int argc,
- char **argv)
+WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv)
{
char
*option,
file_opened;
assert(argc>0 && argv[argc-1] != (char *)NULL);
- assert(wand != (MagickWand *) NULL);
- assert(wand->signature == WandSignature);
- assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
- if (wand->debug != MagickFalse)
- (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+ assert(cli_wand != (MagickCLI *) NULL);
+ assert(cli_wand->signature == WandSignature);
+ if (cli_wand->wand.debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
/* Initialize variables */
/* FUTURE handle file opening for '-' 'fd:N' or script filename */
file_opened=MagickFalse;
if ( LocaleCompare(argv[0],"-") == 0 )
{
- CopyMagickString(wand->name,"stdin",MaxTextExtent);
+ CopyMagickString(cli_wand->wand.name,"stdin",MaxTextExtent);
token_info.stream=stdin;
file_opened=MagickFalse;
}
else
{
- GetPathComponent(argv[0],TailPath,wand->name);
+ GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
token_info.stream=fopen(argv[0], "r");
file_opened=MagickTrue;
}
if ( file_opened != MagickFalse )
fclose(token_info.stream);
MagickExceptionScript(ResourceLimitError,"MemoryAllocationFailed","",0,0);
- (void) ThrowMagickException(wand->exception,GetMagickModule(),
+ (void) ThrowMagickException(cli_wand->wand.exception,GetMagickModule(),
ResourceLimitError,"MemoryAllocationFailed","script token buffer");
return;
}
option_line=token_info.token_line;
option_column=token_info.token_column;
-#if MagickCommandDebug
+#if MagickCommandDebug >=2
(void) FormatLocaleFile(stderr, "Script Option Token: %u,%u: \"%s\"\n",
option_line, option_column, option );
#endif
{ const OptionInfo *option_info = GetCommandOptionInfo(option);
count=option_info->type;
option_type=option_info->flags;
-#if MagickCommandDebug >= 2
+#if MagickCommandDebug >= 3
(void) FormatLocaleFile(stderr, "option \"%s\" matched \"%s\"\n",
option, option_info->mnemonic );
#endif
if ( IsCommandOption(option) == MagickFalse)
{
/* non-option -- treat as a image read */
- ProcessSpecialOption(wand,"-read",option,MagickScriptReadFlags);
+ CLISpecialOperator(cli_wand,"-read",option);
count = 0;
- continue;
}
- MagickExceptionScript(OptionFatalError,"UnrecognizedOption",
- option,option_line,option_column);
- break;
+ else
+ MagickExceptionScript(OptionFatalError,"UnrecognizedOption",
+ option,option_line,option_column);
+
+ // FUTURE: '-regard_warning' causes IM to exit more prematurely!
+ // Note pipelined options may like more control over this level
+ if (cli_wand->wand.exception->severity > ErrorException)
+ {
+ if (cli_wand->wand.exception->severity > ErrorException)
+ //(regard_warnings != MagickFalse))
+ break; /* FATAL - caller handles exception */
+ CatchException(cli_wand->wand.exception); /* output warnings and clear!!! */
+ }
+ continue;
}
plus_alt_op = MagickFalse;
/* handle script special options */
//either continue processing command line
// or making use of the command line options.
- //ProcessCommandOptions(wand,count+1,argv, MagickScriptArgsFlags);
+ //CLICommandOptions(cli_wand,count+1,argv, MagickScriptArgsFlags);
#if MagickCommandDebug
(void) FormatLocaleFile(stderr,
if ( LocaleCompare(option,"-exit") == 0 )
break;
/* No "-script" from script at this time */
- ProcessSpecialOption(wand,option,arg1,MagickScriptReadFlags);
+ CLISpecialOperator(cli_wand,option,arg1);
}
if ( (option_type & SettingOptionFlags) != 0 )
{
- WandSettingOptionInfo(wand, option+1, arg1);
+ CLISettingOptionInfo(cli_wand, option+1, arg1);
// FUTURE: Sync Specific Settings into Images
}
if ( (option_type & SimpleOperatorOptionFlag) != 0)
- WandSimpleOperatorImages(wand, plus_alt_op, option+1, arg1, arg2);
+ CLISimpleOperatorImages(cli_wand, plus_alt_op, option+1, arg1, arg2);
if ( (option_type & ListOperatorOptionFlag) != 0 )
- WandListOperatorImages(wand, plus_alt_op, option+1, arg1, arg2);
+ CLIListOperatorImages(cli_wand, plus_alt_op, option+1, arg1, arg2);
// FUTURE: '-regard_warning' causes IM to exit more prematurely!
// Note pipelined options may like more control over this level
- if (wand->exception->severity > ErrorException)
+ if (cli_wand->wand.exception->severity > ErrorException)
{
- if (wand->exception->severity > ErrorException)
+ if (cli_wand->wand.exception->severity > ErrorException)
//(regard_warnings != MagickFalse))
break; /* FATAL - caller handles exception */
- CatchException(wand->exception); /* output warnings and clear!!! */
+ CatchException(cli_wand->wand.exception); /* output warnings and clear!!! */
}
}
#if MagickCommandDebug
%
% The format of the ProcessCommandOptions method is:
%
-% int ProcessCommandOptions(MagickWand *wand,int argc,char **argv,
+% int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
% int *index, ProcessOptionFlags process_flags )
%
% A description of each parameter follows:
%
-% o wand: the main CLI Wand to use.
+% o cli_wand: the main CLI Wand to use.
%
% o argc: the number of elements in the argument vector.
%
*/
/* FUTURE: correctly identify option... CLI arg, Script line,column */
#define MagickExceptionContinue(severity,tag,arg,index) \
- (void) ThrowMagickException(wand->exception,GetMagickModule(),severity,tag, \
+ (void) ThrowMagickException(cli_wand->wand.exception,GetMagickModule(),severity,tag, \
"'%s' : CLI Arg #%d", arg, (int) index); \
#define MagickExceptionReturn(severity,tag,option,arg) \
return; \
}
-WandExport void ProcessCommandOptions(MagickWand *wand,int argc,
+WandExport void ProcessCommandOptions(MagickCLI *cli_wand,int argc,
char **argv, ProcessOptionFlags process_flags )
{
const char
option_type;
assert(argc>0 && argv[argc-1] != (char *)NULL);
- assert(wand != (MagickWand *) NULL);
- assert(wand->signature == WandSignature);
- assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
- if (wand->debug != MagickFalse)
- (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+ assert(cli_wand != (MagickCLI *) NULL);
+ assert(cli_wand->signature == WandSignature);
+ if (cli_wand->wand.debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
/*
Parse command-line options.
for (i=0; i < end; i += count +1)
{
#if MagickCommandDebug >= 2
- (void) FormatLocaleFile(stderr, "index= %d\n", i );
+ (void) FormatLocaleFile(stderr, "index= %d option="%s\"\n", i, argv[i]);
#endif
/* Finished processing one option? */
if ( ( process_flags & ProcessOneOptionOnly ) != 0 && i != 0 )
{ const OptionInfo *option_info = GetCommandOptionInfo(argv[i]);
count=option_info->type;
option_type=option_info->flags;
-#if MagickCommandDebug >= 2
+#if MagickCommandDebug >= 3
(void) FormatLocaleFile(stderr, "option \"%s\" matched \"%s\"\n",
argv[i], option_info->mnemonic );
#endif
#if MagickCommandDebug
(void) FormatLocaleFile(stderr, "CLI Non-Option: \"%s\"\n", option);
#endif
- if ( IsCommandOption(option) != MagickFalse )
+ if ( ( IsCommandOption(option) == MagickFalse ) &&
+ ( (process_flags & ProcessNonOptionImageRead) != 0 ) )
{
- if ( ( process_flags & ProcessNonOptionImageRead ) != 0 )
- {
- /* non-option -- treat as a image read */
- ProcessSpecialOption(wand,"-read",option,process_flags);
- count = 0;
- }
+ /* non-option -- treat as a image read */
+ CLISpecialOperator(cli_wand,"-read",option);
+ count = 0;
}
- else if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
+ else if ( (process_flags & ProcessUnknownOptionError) != 0 )
+ MagickExceptionReturn(OptionFatalError,"UnrecognizedOption",
+ option,i);
+
+ // FUTURE: '-regard_warning' causes IM to exit more prematurely!
+ // Note pipelined options may like more control over this level
+ if (cli_wand->wand.exception->severity > ErrorException)
{
- MagickExceptionReturn(OptionFatalError,"UnrecognizedOption",
- option,i);
- return;
+ if (cli_wand->wand.exception->severity > ErrorException)
+ //(regard_warnings != MagickFalse))
+ break; /* FATAL - caller handles exception */
+ CatchException(cli_wand->wand.exception); /* output warnings and clear!!! */
}
continue;
}
+
if ( (option_type & DeprecateOptionFlag) != 0 )
MagickExceptionContinue(OptionWarning,"DeprecatedOption",option,i);
/* continue processing option anyway */
{
// Unbalanced Parenthesis if stack not empty
// Call Script, with a filename as a zeroth argument
- ProcessScriptOptions(wand,argc-(i+1),argv+(i+1));
+ ProcessScriptOptions(cli_wand,argc-(i+1),argv+(i+1));
return;
}
- ProcessSpecialOption(wand,option,arg1,process_flags);
+ CLISpecialOperator(cli_wand,option,arg1);
}
if ( (option_type & SettingOptionFlags) != 0 )
{
- WandSettingOptionInfo(wand, option+1, arg1);
+ CLISettingOptionInfo(cli_wand, option+1, arg1);
// FUTURE: Sync Specific Settings into Images
}
if ( (option_type & SimpleOperatorOptionFlag) != 0)
- WandSimpleOperatorImages(wand, plus_alt_op, option+1, arg1, arg2);
+ CLISimpleOperatorImages(cli_wand, plus_alt_op, option+1, arg1, arg2);
if ( (option_type & ListOperatorOptionFlag) != 0 )
- WandListOperatorImages(wand, plus_alt_op, option+1, arg1, arg2);
+ CLIListOperatorImages(cli_wand, plus_alt_op, option+1, arg1, arg2);
// FUTURE: '-regard_warning' causes IM to exit more prematurely!
// Note pipelined options may like more control over this level
- if (wand->exception->severity > ErrorException)
+ if (cli_wand->wand.exception->severity > ErrorException)
{
- if (wand->exception->severity > ErrorException)
+ if (cli_wand->wand.exception->severity > ErrorException)
//(regard_warnings != MagickFalse))
return; /* FATAL - caller handles exception */
- CatchException(wand->exception); /* output warnings and clear!!! */
+ CatchException(cli_wand->wand.exception); /* output warnings and clear!!! */
}
}
assert(end==argc-1);
/*
- Write out final image!
+ Implicit Write of images to final CLI argument
*/
option=argv[i];
/* FUTURE: Better Error - Output Filename not Found */
MagickExceptionReturn(OptionError,"MissingOutputFilename",option,i);
- /* If no images in MagickWand */
- if ( wand->images == (Image *) NULL )
+ /* If no images in MagickCLI */
+ if ( cli_wand->wand.images == (Image *) NULL )
{
/* a "null:" output coder with no images is not an error! */
if ( LocaleCompare(option,"null:") == 0 )
MagickExceptionReturn(OptionError,"NoImagesForFinalWrite",option,i);
}
- //WandListOperatorImages(wand,MagickFalse,"write",option,(const char *)NULL);
- (void) SyncImagesSettings(wand->image_info,wand->images,wand->exception);
- (void) WriteImages(wand->image_info,wand->images,option,wand->exception);
-
+#if 0
+ WandListOperatorImages(cli_wand,MagickFalse,"write",option,(const char *)NULL);
+#else
+ (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
+ cli_wand->wand.exception);
+ (void) WriteImages(cli_wand->wand.image_info,cli_wand->wand.images,option,
+ cli_wand->wand.exception);
+#endif
return;
}
\f
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MagickImageCommand() Handle special use CLI arguments and prepare a
-% CLI MagickWand to process the command line or directly specified script.
+% CLI MagickCLI to process the command line or directly specified script.
%
% This is essentualy interface function between the MagickCore library
-% initialization function MagickCommandGenesis(), and the option MagickWand
+% initialization function MagickCommandGenesis(), and the option MagickCLI
% processing functions ProcessCommandOptions() or ProcessScriptOptions()
%
% The format of the MagickImageCommand method is:
WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info,
int argc,char **argv,char **metadata,ExceptionInfo *exception)
{
- MagickWand
- *wand;
+ MagickCLI
+ *cli_wand;
const char
*option;
#if 0
/* FUTURE: This does not make sense! Remove it.
- Only implied 'image read' needs to expand file name glob patterns
+ Only a 'image read' needs to expand file name glob patterns
*/
status=ExpandFilenames(&argc,&argv);
if (status == MagickFalse)
GetExceptionMessage(errno));
#endif
- /* Special hidden option for 'delegates' - no wand needed */
+ /* Special option (hidden) for delegate usage - no wand needed */
if (LocaleCompare("-concatenate",argv[1]) == 0)
return(ConcatenateImages(argc,argv,exception));
/* Initialize special "CLI Wand" to hold images and settings (empty) */
/* FUTURE: add this to 'operations.c' */
- wand=NewMagickWand();
- wand->image_info=DestroyImageInfo(wand->image_info);
- wand->image_info=image_info;
- wand->exception=DestroyExceptionInfo(wand->exception);
- wand->exception=exception;
- wand->draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
- wand->quantize_info=AcquireQuantizeInfo(image_info);
-
- if (LocaleCompare("-list",argv[1]) == 0)
- /* Special option - list argument constants and other information */
- /* FUTURE - this really should be a direct MagickCore Function */
- WandSettingOptionInfo(wand, argv[1]+1, argv[2]);
- else if (LocaleCompare("-script",argv[1]) == 0)
+ cli_wand=AcquireMagickCLI(image_info,exception);
+
+ if (LocaleCompare("-script",argv[1]) == 0)
{
- /* Start processing from script, no pre-script options */
- GetPathComponent(argv[2],TailPath,wand->name);
- ProcessScriptOptions(wand,argc-2,argv+2);
+ /* Start processing directly from script, no pre-script options
+ Replace wand command name with script name
+ */
+ GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
+ ProcessScriptOptions(cli_wand,argc-2,argv+2);
}
+ else if (LocaleCompare("-list",argv[1]) == 0)
+ /* Special option, list information and exit
+ FUTURE: this should be a MagickCore option, no wand is actually needed
+ */
+
+ CLISpecialOperator(cli_wand, argv[1]+1, argv[2]);
else
- {
- /* Processing Command line, assuming output file as last option */
- ProcessCommandOptions(wand,argc-1,argv+1,MagickCommandOptionFlags);
- }
+ /* Processing Command line, assuming output file as last option */
+ ProcessCommandOptions(cli_wand,argc-1,argv+1,MagickCommandOptionFlags);
- assert(wand->exception == exception);
- assert(wand->image_info == image_info);
+
+ /* recover original image_info - check we get the right image_info */
+ while (cli_wand->image_info_stack != (Stack *)NULL)
+ CLISpecialOperator(cli_wand,"}",(const char *)NULL);
+ assert(cli_wand->wand.image_info == image_info);
+ assert(cli_wand->wand.exception == exception);
/* Handle metadata for ImageMagickObject COM object for Windows VBS */
if (metadata != (char **) NULL)
format="%w,%h,%m"; // Get this from image_info Option splaytree
- text=InterpretImageProperties(image_info,wand->images,format,exception);
+ text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
+ exception);
if (text == (char *) NULL)
ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
"MemoryAllocationFailed","`%s'", GetExceptionMessage(errno));
text=DestroyString(text);
}
}
-
/* Destroy the special CLI Wand */
- wand->exception = (ExceptionInfo *)NULL;
- wand->image_info = (ImageInfo *)NULL;
- wand=DestroyMagickWand(wand);
+ cli_wand->wand.image_info = (ImageInfo *)NULL; /* not these */
+ cli_wand->wand.exception = (ExceptionInfo *)NULL;
+ cli_wand=DestroyMagickCLI(cli_wand);
return((exception->severity > ErrorException) ? MagickFalse : MagickTrue);
}
#include "MagickWand/studio.h"
#include "MagickWand/MagickWand.h"
#include "MagickWand/magick-wand-private.h"
+#include "MagickWand/magick-cli-private.h"
#include "MagickWand/operation.h"
+#include "MagickWand/wand.h"
#include "MagickCore/monitor-private.h"
#include "MagickCore/thread-private.h"
#include "MagickCore/string-private.h"
*/
static MagickBooleanType MonitorProgress(const char *text,
const MagickOffsetType offset,const MagickSizeType extent,
- void *wand_unused(client_data))
+ void *wand_unused(cli_wandent_data))
{
char
message[MaxTextExtent],
specifications (or direct floating point numbers). The number of floats
needed to represent a color varies depending on teh current channel
setting.
+
+ This really should be in MagickCore, so that other API's can make use of it.
*/
static Image *SparseColorOption(const Image *image,
const SparseColorMethod method,const char *arguments,
number_arguments=x;
if ( error ) {
(void) ThrowMagickException(exception,GetMagickModule(),
- OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
+ OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
"Invalid number of Arguments");
return( (Image *)NULL);
}
if ( token[0] == '\0' ) break;
if ( isalpha((int) token[0]) || token[0] == '#' ) {
(void) ThrowMagickException(exception,GetMagickModule(),
- OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
+ OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
"Color found, instead of X-coord");
error = MagickTrue;
break;
if ( token[0] == '\0' ) break;
if ( isalpha((int) token[0]) || token[0] == '#' ) {
(void) ThrowMagickException(exception,GetMagickModule(),
- OptionError, "InvalidArgument", "`%s': %s", "sparse-color",
+ OptionError, "InvalidArgument", "'%s': %s", "sparse-color",
"Color found, instead of Y-coord");
error = MagickTrue;
break;
}
if ( number_arguments != x && !error ) {
(void) ThrowMagickException(exception,GetMagickModule(),OptionError,
- "InvalidArgument","`%s': %s","sparse-color","Argument Parsing Error");
+ "InvalidArgument","'%s': %s","sparse-color","Argument Parsing Error");
sparse_arguments=(double *) RelinquishMagickMemory(sparse_arguments);
return( (Image *)NULL);
}
% %
% %
% %
-+ W a n d S e t t i n g O p t i o n I n f o %
++ A c q u i r e W a n d C L I %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
+% Wand). The given image_info and exception is included as is if provided.
+%
+% Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
+% needed.
+%
+% The format of the NewMagickWand method is:
+%
+% MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
+% ExceptionInfo *exception)
+%
+*/
+WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
+ ExceptionInfo *exception)
+{
+ MagickCLI
+ *cli_wand;
+
+ /* precaution - as per NewMagickWand() */
+ {
+ size_t depth = MAGICKCORE_QUANTUM_DEPTH;
+ const char *quantum = GetMagickQuantumDepth(&depth);
+ if (depth != MAGICKCORE_QUANTUM_DEPTH)
+ ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
+ }
+
+ /* allocate memory for MgaickCLI */
+ cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
+ if (cli_wand == (MagickCLI *) NULL)
+ {
+ ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
+ GetExceptionMessage(errno));
+ return((MagickCLI *)NULL);
+ }
+
+ /* Initialize Wand Part of MagickCLI
+ FUTURE: this is a repeat of code from NewMagickWand()
+ However some parts may be given fro man external source!
+ */
+ cli_wand->wand.id=AcquireWandId();
+ (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
+ "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
+ cli_wand->wand.images=NewImageList();
+ if ( image_info == (ImageInfo *)NULL)
+ cli_wand->wand.image_info=AcquireImageInfo();
+ else
+ cli_wand->wand.image_info=image_info;
+ if ( exception == (ExceptionInfo *)NULL)
+ cli_wand->wand.exception=AcquireExceptionInfo();
+ else
+ cli_wand->wand.exception=exception;
+ cli_wand->wand.debug=IsEventLogging();
+ cli_wand->wand.signature=WandSignature;
+
+ /* Initialize CLI Part of MagickCLI */
+ cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
+ cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
+ cli_wand->image_list_stack=(Stack *)NULL;
+ cli_wand->image_info_stack=(Stack *)NULL;
+ cli_wand->signature=WandSignature;
+
+ if (cli_wand->wand.debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+ return(cli_wand);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
++ D e s t r o y W a n d C L I %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% WandSettingOptionInfo() applies a single settings option into a CLI wand
+% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
+% and any exceptions, if still present in the wand.
+%
+% The format of the NewMagickWand method is:
+%
+% MagickWand *DestroyMagickCLI()
+% Exception *exception)
+%
+*/
+WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
+{
+ Stack
+ *node;
+
+ assert(cli_wand != (MagickCLI *) NULL);
+ assert(cli_wand->signature == WandSignature);
+ assert(cli_wand->wand.signature == WandSignature);
+ if (cli_wand->wand.debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+
+ /* Destroy CLI part of MagickCLI */
+ if (cli_wand->draw_info != (DrawInfo *) NULL )
+ cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
+ if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
+ cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
+ while(cli_wand->image_list_stack != (Stack *)NULL)
+ {
+ node=cli_wand->image_list_stack;
+ cli_wand->image_list_stack=node->next;
+ (void) DestroyImageList((Image *)node->data);
+ (void) RelinquishMagickMemory(node);
+ }
+ while(cli_wand->image_info_stack != (Stack *)NULL)
+ {
+ node=cli_wand->image_info_stack;
+ cli_wand->image_info_stack=node->next;
+ (void) DestroyImageInfo((ImageInfo *)node->data);
+ (void) RelinquishMagickMemory(node);
+ }
+ cli_wand->signature=(~WandSignature);
+
+ /* Destroy Wand part MagickCLI */
+ cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
+ if (cli_wand->wand.image_info != (ImageInfo *) NULL )
+ cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
+ if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
+ cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
+ RelinquishWandId(cli_wand->wand.id);
+ cli_wand->wand.signature=(~WandSignature);
+
+ return((MagickCLI *)NULL);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
++ C L I S e t t i n g O p t i o n I n f o %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% CLISettingOptionInfo() applies a single settings option into a CLI wand
% holding the image_info, draw_info, quantize_info structures that will be
-% used when processing the images also found within the wand.
+% used when processing the images.
%
-% These options do no require images to be present in the wand for them to be
-% able to be set, in which case they will be applied to
+% These options do no require images to be present in the CLI wand for them
+% to be able to be set, in which case they will generally be applied to image
+% that are read in later
%
% Options handled by this function are listed in CommandOptions[] of
% "option.c" that is one of "SettingOptionFlags" option flags.
%
% The format of the WandSettingOptionInfo method is:
%
-% void WandSettingOptionInfo(MagickWand *wand,const char *option,
+% void CLISettingOptionInfo(MagickCLI *cli_wand,const char *option,
% const char *arg)
%
% A description of each parameter follows:
%
-% o wand: structure holding settings to be applied
+% o cli_wand: structure holding settings to be applied
%
% o option: The option string to be set
%
%
% Example usage...
%
-% WandSettingOptionInfo(wand, "background", MagickTrue, "Red");
-% WandSettingOptionInfo(wand, "adjoin", "true");
-% WandSettingOptionInfo(wand, "adjoin", NULL);
+% CLISettingOptionInfo(cli_wand, "background", MagickTrue, "Red");
+% CLISettingOptionInfo(cli_wand, "adjoin", "true");
+% CLISettingOptionInfo(cli_wand, "adjoin", NULL);
%
% Or for handling command line arguments EG: +/-option ["arg"]
%
% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
% if ( (flags & SettingOptionFlags) != 0 )
-% WandSettingOptionInfo(wand, argv[i]+1,
+% CLISettingOptionInfo(cli_wand, argv[i]+1,
% (((*argv[i])!='-') ? (char *)NULL
% : (count>0) ? argv[i+1] : "true") );
% i += count+1;
%
*/
-WandExport void WandSettingOptionInfo(MagickWand *wand,const char *option,
+WandExport void CLISettingOptionInfo(MagickCLI *cli_wand,const char *option,
const char *arg)
{
- assert(wand != (MagickWand *) NULL);
- assert(wand->signature == WandSignature);
- assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
- if (wand->debug != MagickFalse)
- (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
-
-#define image_info (wand->image_info)
-#define draw_info (wand->draw_info)
-#define quantize_info (wand->quantize_info)
-#define exception (wand->exception)
+ assert(cli_wand != (MagickCLI *) NULL);
+ assert(cli_wand->signature == WandSignature);
+ assert(cli_wand->wand.signature == WandSignature);
+ if (cli_wand->wand.debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+
+#define image_info (cli_wand->wand.image_info)
+#define exception (cli_wand->wand.exception)
+#define draw_info (cli_wand->draw_info)
+#define quantize_info (cli_wand->quantize_info)
#define IfSetOption (arg!=(char *)NULL)
#define ArgOption(def) (IfSetOption?arg:(const char *)(def))
#define ArgBoolean (IfSetOption?MagickTrue:MagickFalse)
if (LocaleCompare("box",option) == 0)
{
/* DEPRECIATED - now "undercolor" */
- WandSettingOptionInfo(wand,"undercolor",arg);
+ CLISettingOptionInfo(cli_wand,"undercolor",arg);
break;
}
break;
}
if (LocaleCompare("channel",option) == 0)
{
- /* This is applied to images in SimpleImageOperator!!!
- FUTURE: move it to SyncImageSettings() - or alternative
+ /* FUTURE: -channel mask {vaules}
+ This is applied to images in SimpleImageOperator!!!
+ Move it to SyncImageSettings() - or alternative
*/
image_info->channel=(ChannelType) (
IfSetOption ? ParseChannelOption(arg) : DefaultChannels );
/* SyncImageSettings() used to set per-image attribute. */
(void) SetLogEventMask(ArgOption("none"));
image_info->debug=IsEventLogging(); /* extract logging*/
- wand->debug=IsEventLogging();
+ cli_wand->wand.debug=IsEventLogging();
break;
}
if (LocaleCompare("define",option) == 0)
(void) SetImageOption(image_info,option,ArgOption(NULL));
break;
}
- if (LocaleCompare("list",option) == 0)
- {
- ssize_t
- list;
-
- /* FUTURE: This is not really a Setting Option, but a Special
- * The bulk of this should be turned into a MagickCore function
- */
- list=ParseCommandOption(MagickListOptions,MagickFalse,
- ArgOption("list"));
- switch (list)
- {
- case MagickCoderOptions:
- {
- (void) ListCoderInfo((FILE *) NULL,exception);
- break;
- }
- case MagickColorOptions:
- {
- (void) ListColorInfo((FILE *) NULL,exception);
- break;
- }
- case MagickConfigureOptions:
- {
- (void) ListConfigureInfo((FILE *) NULL,exception);
- break;
- }
- case MagickDelegateOptions:
- {
- (void) ListDelegateInfo((FILE *) NULL,exception);
- break;
- }
- case MagickFontOptions:
- {
- (void) ListTypeInfo((FILE *) NULL,exception);
- break;
- }
- case MagickFormatOptions:
- {
- (void) ListMagickInfo((FILE *) NULL,exception);
- break;
- }
- case MagickLocaleOptions:
- {
- (void) ListLocaleInfo((FILE *) NULL,exception);
- break;
- }
- case MagickLogOptions:
- {
- (void) ListLogInfo((FILE *) NULL,exception);
- break;
- }
- case MagickMagicOptions:
- {
- (void) ListMagicInfo((FILE *) NULL,exception);
- break;
- }
- case MagickMimeOptions:
- {
- (void) ListMimeInfo((FILE *) NULL,exception);
- break;
- }
- case MagickModuleOptions:
- {
- (void) ListModuleInfo((FILE *) NULL,exception);
- break;
- }
- case MagickPolicyOptions:
- {
- (void) ListPolicyInfo((FILE *) NULL,exception);
- break;
- }
- case MagickResourceOptions:
- {
- (void) ListMagickResourceInfo((FILE *) NULL,exception);
- break;
- }
- case MagickThresholdOptions:
- {
- (void) ListThresholdMaps((FILE *) NULL,exception);
- break;
- }
- default:
- {
- (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
- exception);
- break;
- }
- }
- break;
- }
if (LocaleCompare("log",option) == 0)
{
if (IfSetOption)
draw_info->render= IfSetOption ? MagickFalse : MagickTrue;
break;
}
+ if (LocaleCompare("respect-parenthesis",option) == 0)
+ {
+ (void) SetImageOption(image_info,option,ArgOption(NULL));
+ break;
+ }
break;
}
case 's':
break;
}
#undef image_info
+#undef exception
#undef draw_info
#undef quantize_info
-#undef exception
#undef IfSetOption
#undef ArgOption
#undef ArgBoolean
% %
% %
% %
-+ W a n d S i m p l e O p e r a t o r I m a g e s %
++ C L I S i m p l e O p e r a t o r I m a g e s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% WandSimpleOperatorImages() applys one simple image operation given to all
-% the images in the current wand, with the settings that are saved in the
-% CLI wand.
+% the images in the CLI wand, with the settings that was previously saved in
+% the CLI wand.
%
% It is assumed that any per-image settings are up-to-date with respect to
-% extra settings that have been saved in the wand.
+% extra settings that were already saved in the wand.
%
% The format of the WandSimpleOperatorImage method is:
%
-% void WandSimpleOperatorImages(MagickWand *wand,
+% void CLISimpleOperatorImages(MagickCLI *cli_wand,
% const MagickBooleanType plus_alt_op, const char *option,
% const char *arg1, const char *arg2)
%
% A description of each parameter follows:
%
-% o wand: structure holding settings to be applied
+% o cli_wand: structure holding settings and images to be operated on
%
% o plus_alt_op: request the 'plus' or alturnative form of the operation
%
%
% Example usage...
%
-% WandSimpleOperatorImages(wand, MagickFalse,"crop","100x100+20+30",NULL);
-% WandSimpleOperatorImages(wand, MagickTrue, "repage",NULL,NULL);
-% WandSimpleOperatorImages(wand, MagickTrue, "distort","SRT","45");
-% if ( wand->exception->severity != UndefinedException ) {
+% CLISimpleOperatorImages(cli_wand, MagickFalse,"crop","100x100+20+30",NULL);
+% CLISimpleOperatorImages(cli_wand, MagickTrue, "repage",NULL,NULL);
+% CLISimpleOperatorImages(cli_wand, MagickTrue, "distort","SRT","45");
+% if ( cli_wand->wand.exception->severity != UndefinedException ) {
% CatchException(exception);
% exit(1);
% }
%
% Or for handling command line arguments EG: +/-option ["arg"]
%
+% cli_wand
% argc,argv
% i=index in argv
%
% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
% if ( (flags & SimpleOperatorOptionFlag) != 0 )
-% WandSimpleOperatorImages(wand,
+% CLISimpleOperatorImages(cli_wand,
% ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
% count>=1 ? argv[i+1] : (char *)NULL,
% count>=2 ? argv[i+2] : (char *)NULL );
/*
Internal subrountine to apply one simple image operation to the current
- image pointed to by the wand.
+ image pointed to by the CLI wand.
The image in the list may be modified in three different ways...
* directly modified (EG: -negate, -gamma, -level, -annotate, -draw),
also change. GetFirstImageInList() should be used by caller if they wish
return the Image pointer to the first image in list.
*/
-static void WandSimpleOperatorImage(MagickWand *wand,
+static void CLISimpleOperatorImage(MagickCLI *cli_wand,
const MagickBooleanType plus_alt_op, const char *option,
const char *arg1, const char *arg2)
{
MagickStatusType
flags;
-#define image_info (wand->image_info)
-#define draw_info (wand->draw_info)
-#define quantize_info (wand->quantize_info)
-#define image (wand->images)
-#define exception (wand->exception)
+#define image_info (cli_wand->wand.image_info)
+#define image (cli_wand->wand.images)
+#define exception (cli_wand->wand.exception)
+#define draw_info (cli_wand->draw_info)
+#define quantize_info (cli_wand->quantize_info)
#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
- assert(image_info != (const ImageInfo *) NULL);
- assert(image_info->signature == MagickSignature);
- assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
- assert(image != (Image *) NULL); /* there is an image */
- assert(image->signature == MagickSignature); /* and is a valid image */
-
- if (wand->debug != MagickFalse)
- (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+ assert(cli_wand != (MagickCLI *) NULL);
+ assert(cli_wand->signature == WandSignature);
+ assert(cli_wand->wand.signature == WandSignature);
+ assert(image != (Image *) NULL); /* an image must be present */
+ if (cli_wand->wand.debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
SetGeometryInfo(&geometry_info);
(void) ClampImage(image,exception);
break;
}
- if (LocaleCompare("clip",option) == 0)
+ if (LocaleCompare("cli_wandp",option) == 0)
{
if (plus_alt_op == MagickFalse)
(void) ClipImage(image,exception);
- else /* "+clip" remove the write mask */
+ else /* "+mask" remove the write mask */
(void) SetImageMask(image,(Image *) NULL,exception);
break;
}
- if (LocaleCompare("clip-mask",option) == 0)
+ if (LocaleCompare("cli_wandp-mask",option) == 0)
{
CacheView
*mask_view;
y;
if (plus_alt_op != MagickFalse)
- { /* "+clip-mask" Remove the write mask */
+ { /* "+cli_wandp-mask" Remove the write mask */
(void) SetImageMask(image,(Image *) NULL,exception);
break;
}
if (SetImageStorageClass(mask_image,DirectClass,exception)
== MagickFalse)
break;
- /* Create a write mask from clip-mask image */
+ /* Create a write mask from cli_wandp-mask image */
/* FUTURE: use Alpha operations instead and create a Grey Image */
mask_view=AcquireCacheView(mask_image);
for (y=0; y < (ssize_t) mask_image->rows; y++)
mask_image=DestroyImage(mask_image);
break;
}
- if (LocaleCompare("clip-path",option) == 0)
+ if (LocaleCompare("cli_wandp-path",option) == 0)
{
(void) ClipImagePath(image,arg1,
(MagickBooleanType)(!(int)plus_alt_op),exception);
if (LocaleCompare("separate",option) == 0)
{
/* WARNING: This can generate multiple images! */
+ /* FUTURE - this may be replaced by a "-channel" method */
new_image=SeparateImages(image,exception);
break;
}
#undef normal_op
}
-WandExport void WandSimpleOperatorImages(MagickWand *wand,
+WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand,
const MagickBooleanType plus_alt_op, const char *option,
const char *arg1, const char *arg2)
{
size_t
- n;
-
- register ssize_t
+ n,
i;
- assert(wand->image_info != (const ImageInfo *) NULL);
- assert(wand->image_info->signature == MagickSignature);
- assert(wand->draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
- assert(wand->images != (Image *) NULL); /* there is one image */
+ assert(cli_wand != (MagickCLI *) NULL);
+ assert(cli_wand->signature == WandSignature);
+ assert(cli_wand->wand.signature == WandSignature);
+ assert(cli_wand->wand.images != (Image *) NULL); /* images must be present */
+ if (cli_wand->wand.debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
i=0;
- n=GetImageListLength(wand->images);
- (void) n;
- wand->images=GetFirstImageInList(wand->images);
- for ( ; ; )
+ n=GetImageListLength(cli_wand->wand.images);
+ cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
+ while (1)
{
- WandSimpleOperatorImage(wand, plus_alt_op, option, arg1, arg2);
- if ( wand->images->next == (Image *) NULL )
- break;
- wand->images=wand->images->next;
i++;
+ CLISimpleOperatorImage(cli_wand, plus_alt_op, option, arg1, arg2);
+ if ( cli_wand->wand.images->next == (Image *) NULL )
+ break;
+ cli_wand->wand.images=cli_wand->wand.images->next;
}
- wand->images=GetFirstImageInList(wand->images);
+ assert( i == n );
+ cli_wand->wand.images=GetFirstImageInList(cli_wand->wand.images);
return;
}
\f
% %
% %
% %
-+ W a n d L i s t O p e r a t o r I m a g e s %
++ C L I L i s t O p e r a t o r I m a g e s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% WandListOperatorImages() applies a single operation that is apply to the
+% CLIListOperatorImages() applies a single operation that is apply to the
% entire image list as a whole. The result is often a complete replacment
% of the image list with a completely new list, or just a single image.
%
% The format of the MogrifyImage method is:
%
-% void WandListOperatorImages(MagickWand *wand,
+% void CLIListOperatorImages(MagickCLI *cli_wand,
% const MagickBooleanType plus_alt_op,const char *option,
% const char *arg1, const char *arg2)
%
% A description of each parameter follows:
%
-% o wand: structure holding settings to be applied
+% o cli_wand: structure holding settings to be applied
%
% o plus_alt_op: request the 'plus' or alturnative form of the operation
%
%
% Example usage...
%
-% WandListOperatorImages(wand,MagickFalse,"duplicate", "3", NULL);
-% WandListOperatorImages(wand,MagickTrue, "append", NULL, NULL);
-% if ( wand->exception->severity != UndefinedException ) {
+% CLIListOperatorImages(cli_wand,MagickFalse,"duplicate", "3", NULL);
+% CLIListOperatorImages(cli_wand,MagickTrue, "append", NULL, NULL);
+% if ( cli_wand->wand.exception->severity != UndefinedException ) {
% CatchException(exception);
% exit(1);
% }
%
% Or for handling command line arguments EG: +/-option ["arg"]
%
+% cli_wand
% argc,argv
% i=index in argv
%
% count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
% flags=GetCommandOptionFlags(MagickCommandOptions,MagickFalse,argv[i]);
% if ( (flags & ListOperatorOptionFlag) != 0 )
-% WandListOperatorImages(wand,
+% CLIListOperatorImages(cli_wand,
% ((*argv[i])=='+')?MagickTrue:MagickFalse,argv[i]+1,
% count>=1 ? argv[i+1] : (char *)NULL,
% count>=2 ? argv[i+2] : (char *)NULL );
% i += count+1;
%
*/
-WandExport void WandListOperatorImages(MagickWand *wand,
+WandExport void CLIListOperatorImages(MagickCLI *cli_wand,
const MagickBooleanType plus_alt_op,const char *option,
const char *arg1, const char *arg2)
{
Image
*new_images;
-#define image_info (wand->image_info)
-#define draw_info (wand->draw_info)
-#define quantize_info (wand->quantize_info)
-#define images (wand->images)
-#define exception (wand->exception)
+#define image_info (cli_wand->wand.image_info)
+#define images (cli_wand->wand.images)
+#define exception (cli_wand->wand.exception)
+#define draw_info (cli_wand->draw_info)
+#define quantize_info (cli_wand->quantize_info)
#define normal_op (plus_alt_op?MagickFalse:MagickTrue)
- assert(image_info != (const ImageInfo *) NULL);
- assert(image_info->signature == MagickSignature);
- assert(draw_info != (DrawInfo *) NULL); /* ensure it is a CLI wand */
- assert(images != (Image *) NULL); /* there is an image */
- assert(images->signature == MagickSignature); /* and is a valid image */
-
- if (wand->debug != MagickFalse)
- (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name);
+ assert(cli_wand != (MagickCLI *) NULL);
+ assert(cli_wand->signature == WandSignature);
+ assert(cli_wand->wand.signature == WandSignature);
+ assert(images != (Image *) NULL); /* images must be present */
+ if (cli_wand->wand.debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
(void) SyncImagesSettings(image_info,images,exception);
if (LocaleCompare("average",option) == 0)
{
/* DEPRECIATED - use -evaluate-sequence Mean */
- WandListOperatorImages(wand,plus_alt_op,"evaluate-sequence","Mean",
+ CLIListOperatorImages(cli_wand,plus_alt_op,"evaluate-sequence","Mean",
NULL);
break;
}
}
if (LocaleCompare("combine",option) == 0)
{
+ /* FUTURE - this may be replaced by a 'channel' method */
new_images=CombineImages(images,exception);
break;
}
if (LocaleCompare("deconstruct",option) == 0)
{
/* DEPRECIATED - use -layers CompareAny */
- WandListOperatorImages(wand,plus_alt_op,"layer","CompareAny",NULL);
+ CLIListOperatorImages(cli_wand,plus_alt_op,"layer","CompareAny",NULL);
break;
}
if (LocaleCompare("delete",option) == 0)
if (LocaleCompare("flatten",option) == 0)
{
/* DEPRECIATED use -layers mosaic instead */
- WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
+ CLIListOperatorImages(cli_wand,plus_alt_op,"layer",option,NULL);
break;
}
if (LocaleCompare("fx",option) == 0)
insert_image=RemoveLastImageFromList(&images);
if (plus_alt_op == MagickFalse)
index=(ssize_t) StringToLong(arg1);
+ index_image=insert_image;
if (index == 0)
PrependImageToList(&images,insert_image);
+ else if (index == (ssize_t) GetImageListLength(images))
+ AppendImageToList(&images,insert_image);
else
- if (index == (ssize_t) GetImageListLength(images))
- AppendImageToList(&images,insert_image);
- else
- {
- index_image=GetImageFromList(images,index-1);
- if (index_image == (Image *) NULL)
- {
- (void) ThrowMagickException(exception,GetMagickModule(),
- OptionError,"NoSuchImage","`%s'",arg1);
- break;
- }
- InsertImageInList(&index_image,insert_image);
- }
+ {
+ index_image=GetImageFromList(images,index-1);
+ if (index_image == (Image *) NULL)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"NoSuchImage","'%s'",arg1);
+ break;
+ }
+ InsertImageInList(&index_image,insert_image);
+ }
images=GetFirstImageInList(index_image);
break;
}
if (LocaleCompare("mosaic",option) == 0)
{
/* DEPRECIATED use -layers mosaic instead */
- WandListOperatorImages(wand,plus_alt_op,"layer",option,NULL);
+ CLIListOperatorImages(cli_wand,plus_alt_op,"layer",option,NULL);
break;
}
break;
if ((p == (Image *) NULL) || (q == (Image *) NULL))
{
(void) ThrowMagickException(exception,GetMagickModule(),
- OptionError,"NoSuchImage","`%s'",images->filename);
+ OptionError,"NoSuchImage","'%s'",images->filename);
break;
}
if (p == q)
if (images != (Image *) NULL)
images=DestroyImageList(images);
- images=new_images;
+ images=GetFirstImageInList(new_images);
return;
#undef image_info
+#undef images
+#undef exception
#undef draw_info
#undef quantize_info
+#undef normal_op
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
++ C L I S p e c i a l O p e r a t i o n s %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% CLISpecialOption() Applies operations that may involve empty image lists
+% and or stacks of image lists or image_info settings.
+%
+% Note: inlike other Operators, these may involve other special 'option'
+% character prefixes, other than simply '-' or '+' and as such the full
+% original otpion must be passed.
+%
+% The format of the CLISpecialOption method is:
+%
+% void CLISpecialOption(MagickCLI *cli_wand,const char *option,
+% const char *arg)
+%
+% A description of each parameter follows:
+%
+% o cli_wand: the main CLI Wand to use.
+%
+% o option: The special option (with any switch char) to process
+%
+% o arg: Argument for option, if required
+%
+*/
+
+#define MaxImageStackDepth 32
+
+WandExport void CLISpecialOperator(MagickCLI *cli_wand,
+ const char *option, const char *arg)
+{
+#define exception (cli_wand->wand.exception)
+
+ assert(cli_wand != (MagickCLI *) NULL);
+ assert(cli_wand->signature == WandSignature);
+ assert(cli_wand->wand.signature == WandSignature);
+ if (cli_wand->wand.debug != MagickFalse)
+ (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
+
+ if (LocaleCompare(option,"(") == 0)
+ {
+ /* stack 'push' images */
+ Stack
+ *node;
+
+ size_t
+ size;
+
+ const char*
+ value;
+
+ size=0;
+ node=cli_wand->image_list_stack;
+ for ( ; node != (Stack *)NULL; node=node->next)
+ size++;
+ if ( size >= MaxImageStackDepth )
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"ParenthesisNestedTooDeeply", option);
+ return;
+ }
+ node=(Stack *) AcquireMagickMemory(sizeof(*node));
+ if (node == (Stack *) NULL)
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ ResourceLimitFatalError,"MemoryAllocationFailed", "PushImages");
+ return;
+ }
+ node->data = (void *)cli_wand->wand.images;
+ cli_wand->wand.images = NewImageList();
+ node->next = cli_wand->image_list_stack;
+ cli_wand->image_list_stack = node;
+
+ /* handle respect-parenthesis */
+ value=GetImageOption(cli_wand->wand.image_info,"respect-parenthesis");
+ if (value != (const char *) NULL)
+ option="{";
+ else
+ return;
+ }
+ if (LocaleCompare(option,"{") == 0)
+ {
+ /* stack 'push' of image_info settings */
+ Stack
+ *node;
+
+ size_t
+ size;
+
+ size=0;
+ node=cli_wand->image_info_stack;
+ for ( ; node != (Stack *)NULL; node=node->next)
+ size++;
+ if ( size >= MaxImageStackDepth )
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"ParenthesisNestedTooDeeply", option);
+ return;
+ }
+ node=(Stack *) AcquireMagickMemory(sizeof(*node));
+ if (node == (Stack *) NULL)
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
+ return;
+ }
+
+ node->data = (void *)cli_wand->wand.image_info;
+ cli_wand->wand.image_info = CloneImageInfo(cli_wand->wand.image_info);
+ if (cli_wand->wand.image_info == (ImageInfo *)NULL)
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ ResourceLimitFatalError,"MemoryAllocationFailed", "PushSettings");
+ cli_wand->wand.image_info = (ImageInfo *)node->data;
+ node = (Stack *)RelinquishMagickMemory(node);
+ return;
+ }
+
+ node->next = cli_wand->image_info_stack;
+ cli_wand->image_info_stack = node;
+
+ return;
+ }
+ if (LocaleCompare(option,")") == 0)
+ {
+ /* pop images from stack */
+ Stack
+ *node;
+
+ const char*
+ value;
+
+ node = (void *)cli_wand->image_list_stack;
+ if ( node == (Stack *)NULL)
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"UnbalancedParenthesis", option);
+ return;
+ }
+ cli_wand->image_list_stack = node->next;
+
+ AppendImageToList((Image **)&node->data,cli_wand->wand.images);
+ cli_wand->wand.images= (Image *)node->data;
+ node = (Stack *)RelinquishMagickMemory(node);
+
+ /* handle respect-parenthesis - of the previous 'push' settings */
+ node = cli_wand->image_info_stack;
+ if ( node != (Stack *)NULL)
+ {
+ value=GetImageOption((ImageInfo *)node->data,"respect-parenthesis");
+ if (value != (const char *) NULL)
+ option="}";
+ else
+ return;
+ }
+ else
+ return;
+ }
+ if (LocaleCompare(option,"}") == 0)
+ {
+ /* pop image_info settings from stack */
+ Stack
+ *node;
+
+ node = (void *)cli_wand->image_info_stack;
+ if ( node == (Stack *)NULL)
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"UnbalancedParenthesis", option);
+ return;
+ }
+ cli_wand->image_info_stack = node->next;
+
+ (void) DestroyImageInfo(cli_wand->wand.image_info);
+ cli_wand->wand.image_info = (ImageInfo *)node->data;
+ node = (Stack *)RelinquishMagickMemory(node);
+
+ GetDrawInfo(cli_wand->wand.image_info, cli_wand->draw_info);
+ cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
+ cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
+
+ return;
+ }
+ if (LocaleCompare(option+1,"clone") == 0)
+ {
+ Image
+ *new_images;
+
+ if (*option == '+')
+ arg="-1";
+ if (IsSceneGeometry(arg,MagickFalse) == MagickFalse)
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"InvalidArgument", "'%s': %s", option, arg);
+ return;
+ }
+ if ( cli_wand->image_list_stack == (Stack *)NULL)
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"UnableToCloneImage", option);
+ return;
+ }
+ new_images = (Image *)cli_wand->image_list_stack->data;
+ if (new_images == (Image *) NULL)
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"UnableToCloneImage", option);
+ return;
+ }
+ new_images=CloneImages(new_images,arg,exception);
+ if (new_images == (Image *) NULL)
+ {
+ ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"NoSuchImage",option);
+ return;
+ }
+ AppendImageToList(&cli_wand->wand.images,new_images);
+ return;
+ }
+ if ( LocaleCompare("-read",option) == 0 )
+ {
+#if 1
+ Image *
+ new_images;
+
+ CopyMagickString(cli_wand->wand.image_info->filename,arg,MaxTextExtent);
+ if (cli_wand->wand.image_info->ping != MagickFalse)
+ new_images=PingImages(cli_wand->wand.image_info,exception);
+ else
+ new_images=ReadImages(cli_wand->wand.image_info,exception);
+ AppendImageToList(&cli_wand->wand.images, new_images);
+#else
+ /* read images using MagickWand method - no ping */
+ /* This is not working! - it locks up in a CPU loop! */
+ MagickSetLastIterator(&cli_wand->wand);
+ MagickReadImage(&cli_wand->wand,arg);
+ MagickSetFirstIterator(&cli_wand->wand);
+#endif
+ return;
+ }
+ if (LocaleCompare("-noop",option) == 0)
+ return;
+ if (LocaleCompare("-sans",option) == 0)
+ return;
+ if (LocaleCompare("-sans0",option) == 0)
+ return;
+ if (LocaleCompare("-sans2",option) == 0)
+ return;
+ if (LocaleCompare("-list",option) == 0)
+ {
+ /* FUTURE: This should really be built into the MagickCore
+ It does not actually require any wand or images at all!
+ */
+ ssize_t
+ list;
+
+ list=ParseCommandOption(MagickListOptions,MagickFalse, arg);
+ switch (list)
+ {
+ case MagickCoderOptions:
+ {
+ (void) ListCoderInfo((FILE *) NULL,exception);
+ break;
+ }
+ case MagickColorOptions:
+ {
+ (void) ListColorInfo((FILE *) NULL,exception);
+ break;
+ }
+ case MagickConfigureOptions:
+ {
+ (void) ListConfigureInfo((FILE *) NULL,exception);
+ break;
+ }
+ case MagickDelegateOptions:
+ {
+ (void) ListDelegateInfo((FILE *) NULL,exception);
+ break;
+ }
+ case MagickFontOptions:
+ {
+ (void) ListTypeInfo((FILE *) NULL,exception);
+ break;
+ }
+ case MagickFormatOptions:
+ (void) ListMagickInfo((FILE *) NULL,exception);
+ break;
+ case MagickLocaleOptions:
+ (void) ListLocaleInfo((FILE *) NULL,exception);
+ break;
+ case MagickLogOptions:
+ (void) ListLogInfo((FILE *) NULL,exception);
+ break;
+ case MagickMagicOptions:
+ (void) ListMagicInfo((FILE *) NULL,exception);
+ break;
+ case MagickMimeOptions:
+ (void) ListMimeInfo((FILE *) NULL,exception);
+ break;
+ case MagickModuleOptions:
+ (void) ListModuleInfo((FILE *) NULL,exception);
+ break;
+ case MagickPolicyOptions:
+ (void) ListPolicyInfo((FILE *) NULL,exception);
+ break;
+ case MagickResourceOptions:
+ (void) ListMagickResourceInfo((FILE *) NULL,exception);
+ break;
+ case MagickThresholdOptions:
+ (void) ListThresholdMaps((FILE *) NULL,exception);
+ break;
+ default:
+ (void) ListCommandOptions((FILE *) NULL,(CommandOption) list,
+ exception);
+ break;
+ }
+ return;
+ }
+
+#if 0
+ // adjust stack handling
+ // Other 'special' options this should handle
+ // "region" "list" "version"
+ // It does not do "exit" however as due to its side-effect requirements
+#endif
+#if 0
+ if ( ( process_flags & ProcessUnknownOptionError ) != 0 )
+ MagickExceptionReturn(OptionError,"InvalidUseOfOption",option);
+#endif
+
+#undef image_info
#undef images
#undef exception
-#undef normal_op
}