/**********************************************************************
 * Tcl Image Magick - a Tcl-only wrapper of imageMagick's Wand-API
 **********************************************************************
 * For a brief command description see "doc/TclMagick.txt"
 *
 * For a list of changes see "ChangeLog"
 **********************************************************************/

/* $Id: TclMagick.c,v 1.22.2.3 2005/01/22 19:35:05 bfriesen Exp $ */

#include <limits.h>
#include <string.h>
#include <stdlib.h>

#include "TclMagick.h"
#include <wand/magick_wand.h>

/**********************************************************************/
/* Workaround for bugs: */

#define MAGICK_NEW          /* new interfaces */
#ifdef MAGICK_NEW

#endif

/* Debug TclMagick */
#define MAGICK_DEBUG
/**********************************************************************/

struct {
    int             initialized; /* Whether module has been initialized */
    Tcl_HashTable   hashTable;   /* HasTable for MagickWand objects */
} TM
= {0};


static Tcl_ObjCmdProc    magickCmd;
static Tcl_CmdDeleteProc magickObjDeleteCmd;
static Tcl_ObjCmdProc    wandObjCmd;
static Tcl_ObjCmdProc    pixelObjCmd;
static Tcl_ObjCmdProc    drawObjCmd;

/*----------------------------------------------------------------------
 * Return Magick error description as a TCL result
 *----------------------------------------------------------------------
 */
int myMagickError(Tcl_Interp  *interp, MagickWand *wandPtr )
{
    char *description;

    ExceptionType severity;
    char msg[40];

    description = MagickGetException(wandPtr, &severity);
    if( (description == NULL) || (strlen(description) == 0) ) {
        Tcl_AppendResult(interp, MagickGetPackageName(), ": Unknown error", NULL);
    } else {
        sprintf(msg, "%s: #%d:", MagickGetPackageName(), severity);
        Tcl_AppendResult(interp, description, NULL);
    }
    if( description != NULL ) {
        MagickRelinquishMemory(description);
    }
    /*
     * if(severity < ErrorException) --> warning
     * return TCL_OK ???
     */
    return TCL_ERROR;
}

/*----------------------------------------------------------------------
 * Return the name of a TclMagickObj
 *----------------------------------------------------------------------
 */
char *getMagickObjName(TclMagickObj *mPtr)
{
    if( mPtr == NULL ) {
        return (char *)NULL;
    } else {
        return (char *)Tcl_GetHashKey(&TM.hashTable, mPtr->hashPtr);
    }
}

/*----------------------------------------------------------------------
 * Delete TclMagick objects
 *----------------------------------------------------------------------
 */
static void deleteMagickObj(TclMagickObj *mPtr)
{
    /*
     * Delete the Tcl command deletes also the object itself
     * by calling magickObjDeleteCmd()
     */
    if( mPtr->magickCmd != NULL ) {
        Tcl_DeleteCommandFromToken(mPtr->interp, mPtr->magickCmd);
        mPtr->magickCmd = NULL;
    }
}
static void magickObjDeleteCmd(ClientData clientData)
{
    TclMagickObj *mPtr = (TclMagickObj *)clientData;

    if( mPtr == NULL ) {
        return;
    }
    /*
     * Called before the Tcl command is deleted
     */
    if( mPtr->wandPtr != NULL ) {
        switch(mPtr->type) {
        case TM_TYPE_WAND:
            DestroyMagickWand(mPtr->wandPtr);
            break;
        case TM_TYPE_DRAWING:
            DestroyDrawingWand(mPtr->wandPtr);
            break;
        case TM_TYPE_PIXEL:
            DestroyPixelWand(mPtr->wandPtr);
            break;
        }
    }
    if( mPtr->hashPtr != NULL ) {
        Tcl_DeleteHashEntry(mPtr->hashPtr);
    }
    ckfree((char *)mPtr);
}

/*----------------------------------------------------------------------
 * Create TclMagick objects
 *----------------------------------------------------------------------
 */
TclMagickObj *newMagickObj(Tcl_Interp  *interp, int type, void *wandPtr, char *name)
{
    int isNew;
    char idString[16 + TCL_INTEGER_SPACE];
    TclMagickObj    *mPtr;
    Tcl_HashEntry   *hPtr;

    /*
     * Create the TclMagick object
     */
    mPtr = (TclMagickObj *)ckalloc(sizeof(TclMagickObj));
    if( mPtr == NULL ) {
        return NULL;
    }

    /*
     * if no wandPtr is specified create one
     */
    if( wandPtr == NULL ) {
        switch(type) {
        case TM_TYPE_WAND:
            wandPtr = NewMagickWand();
            break;
        case TM_TYPE_DRAWING:
            wandPtr = NewDrawingWand();
            break;
        case TM_TYPE_PIXEL:
            wandPtr = NewPixelWand();
            break;
        }
    }

    /*
     * if no creation ?name? is specified
     * create one from the MagickWand address
     */
    if( name == NULL ) {
        sprintf(idString, "magick%lX", (unsigned long)wandPtr );
        name = idString;
    }

    /*
     * Create the hash table entry
     * Delete already existing object
     */
    hPtr = Tcl_CreateHashEntry( &TM.hashTable, name, &isNew );
    if( ! isNew ) {
        deleteMagickObj(Tcl_GetHashValue(hPtr));
        hPtr = Tcl_CreateHashEntry( &TM.hashTable, name, &isNew );
    }
    Tcl_SetHashValue(hPtr, mPtr);

    /*
     * Initialize MagickObj fields
     * and create the Tcl command
     */
    mPtr->type    = type;
    mPtr->interp  = interp;
    mPtr->hashPtr = hPtr;
    mPtr->wandPtr = wandPtr;
    switch(type) {
    case TM_TYPE_WAND:
	mPtr->magickCmd = Tcl_CreateObjCommand(interp, name, wandObjCmd, (ClientData)mPtr, magickObjDeleteCmd);
	break;
    case TM_TYPE_DRAWING:
	mPtr->magickCmd = Tcl_CreateObjCommand(interp, name, drawObjCmd, (ClientData)mPtr, magickObjDeleteCmd);
	break;
    case TM_TYPE_PIXEL:
	mPtr->magickCmd = Tcl_CreateObjCommand(interp, name, pixelObjCmd,(ClientData)mPtr, magickObjDeleteCmd);
	break;
    }

    return mPtr;
}
static char *newWandObj(Tcl_Interp  *interp, MagickWand *wandPtr, char *name)
{
    TclMagickObj *mPtr = newMagickObj(interp, TM_TYPE_WAND, wandPtr, name);
    return getMagickObjName(mPtr);
}

#if 0     /* Currently not referenced, avoid gcc warnings */
static char *newDrawingObj(Tcl_Interp  *interp, DrawingWand *wandPtr, char *name)
{
    TclMagickObj *mPtr = newMagickObj(interp, TM_TYPE_DRAWING, wandPtr, name);
    return getMagickObjName(mPtr);
}
#endif

static char *newPixelObj(Tcl_Interp  *interp, PixelWand *wandPtr, char *name)
{
    TclMagickObj *mPtr = newMagickObj(interp, TM_TYPE_PIXEL, wandPtr, name);
    return getMagickObjName(mPtr);
}

/*----------------------------------------------------------------------
 * Check whether an empty object name is specified
 * - Should we extend this to use "none" alternatively to "" ?
 *   This reads better, but disallows "none" as an object name
 *----------------------------------------------------------------------
 */
static int noWandObj(const char *name)
{
    return (strlen(name) == 0);
}


 /*----------------------------------------------------------------------
 * Find TclMagick objects
 *----------------------------------------------------------------------
 */
TclMagickObj *findMagickObj(Tcl_Interp *interp, int type, char *name)
{
    Tcl_HashEntry *hPtr = Tcl_FindHashEntry( &TM.hashTable, name );
    TclMagickObj  *mPtr;

    if( hPtr == NULL ) {
        Tcl_AppendResult(interp, "Magick object '", name, "' not found", NULL);
        return (TclMagickObj *)NULL;
    } else {
        mPtr = (TclMagickObj *)Tcl_GetHashValue(hPtr);
        if( (type != TM_TYPE_ANY) && (mPtr->type != type) ) {
            Tcl_AppendResult(interp, "Magick object '", name, "' is not a ", objTypeNames[type], " object", NULL);
            return (TclMagickObj *)NULL;
        }
        return mPtr;
    }
}
static MagickWand *findMagickWand(Tcl_Interp *interp, char *name)
{
    TclMagickObj *mPtr = findMagickObj(interp, TM_TYPE_WAND, name);
    if( mPtr == NULL ) {
        return (MagickWand *)NULL;
    }
    return (MagickWand *)mPtr->wandPtr;
}
static DrawingWand *findDrawingWand(Tcl_Interp *interp, char *name)
{
    TclMagickObj *mPtr = findMagickObj(interp, TM_TYPE_DRAWING, name);
    if( mPtr == NULL ) {
        return (DrawingWand *)NULL;
    }
    return (DrawingWand *)mPtr->wandPtr;
}
static PixelWand *findPixelWand(Tcl_Interp *interp, char *name)
{
    TclMagickObj *mPtr = findMagickObj(interp, TM_TYPE_PIXEL, name);
    if( mPtr == NULL ) {
        return (PixelWand *)NULL;
    }
    return (PixelWand *)mPtr->wandPtr;
}

/*----------------------------------------------------------------------
 * encoding functions
 *----------------------------------------------------------------------
 */
static void SetResultAsExternalString(Tcl_Interp *interp, char *ext) {
    Tcl_DString extrep;
    Tcl_ExternalToUtfDString(NULL, ext, -1, &extrep);
    Tcl_DStringResult(interp, &extrep);
    Tcl_DStringFree(&extrep);
}


/*----------------------------------------------------------------------
 * magick command
 *----------------------------------------------------------------------
 *
 * magick create type ?name?
 * magick delete name name ...
 * magick names ?type?
 * magick type name
 * magick types
 * magick resourcelimit resource ?limit?
 * magick fonts pattern
 * magick formats pattern
 *
 *----------------------------------------------------------------------
 */

static int magickCmd(
    ClientData  clientData,         /* Unused */
    Tcl_Interp  *interp,            /* Interpreter containing image */
    int         objc,               /* Number of arguments */
    Tcl_Obj     *CONST objv[] )     /* List of arguments */
{
    int index, stat, result;

    static CONST char *subCmds[] = {
        "create",        "delete", "names",   "type",    "types",
        "resourcelimit", "fonts",  "formats", "version", "library",
        (char *) NULL};
    enum subIndex {
        TM_CREATE,   TM_DELETE, TM_NAMES,   TM_TYPE,    TM_TYPES,
        TM_RESOURCE, TM_FONTS,  TM_FORMATS, TM_VERSION, TM_LIBRARY
    };
    static CONST char *resourceNames[] = {
        "undefined", "area", "disk",
        "file",      "map",  "memory",
        (char *) NULL
    };
    static ResourceType resourceTypes[] = {
        UndefinedResource, AreaResource, DiskResource,
        FileResource,      MapResource,  MemoryResource
    };

    if( objc < 2 ) {
        Tcl_WrongNumArgs( interp, 1, objv, "subcmd ?args?" );
        return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subCmds, "subcmd", 0, &index) != TCL_OK) {
        return TCL_ERROR;
    }
    switch ((enum subIndex)index) {


    case TM_CREATE:    /* magick create type ?name? */
    {
	char *name;
	int   type;
	TclMagickObj *mPtr;

	if( (objc < 3) || (objc > 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "type ?name?");
	    return TCL_ERROR;
	}
	/*
	 * Get type parameter
	 * If no creation ?name? is specified, set name=NULL
	 */
	if (Tcl_GetIndexFromObj(interp, objv[2], objTypeNames, "type", 0, &type) != TCL_OK) {
	    return TCL_ERROR;
	}
	if( objc > 3 ) {
	    name = Tcl_GetString(objv[3]);
	} else {
	    name = NULL;
	}
	mPtr = newMagickObj(interp, type, NULL, name);
	name = getMagickObjName(mPtr);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_DELETE:    /* magick delete name name ...*/
    {
	int	 i;
	char *name;
	TclMagickObj *mPtr;

	for (i = 2; i < objc; i++) {
	    name = Tcl_GetString(objv[i]);
	    mPtr = findMagickObj(interp, TM_TYPE_ANY, name);
	    if (mPtr == NULL) {
		return TCL_ERROR;
	    }
	    deleteMagickObj(mPtr);
	}
	break;
    }

    case TM_NAMES:    /* magick names ?type? */
    {
	int type = TM_TYPE_ANY;
	TclMagickObj   *mPtr;
	Tcl_HashEntry  *hPtr;
	Tcl_HashSearch search;

	if( objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?type?");
	    return TCL_ERROR;
	}
	if( objc > 2 ) {
	    if (Tcl_GetIndexFromObj(interp, objv[2], objTypeNames, "type", 0, &type) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	hPtr = Tcl_FirstHashEntry(&TM.hashTable, &search);
	for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    mPtr = Tcl_GetHashValue(hPtr);
	    if( (type == TM_TYPE_ANY) || (type == mPtr->type) ) {
		Tcl_AppendElement(interp, getMagickObjName(mPtr));
	    }
	}
	break;
    }

    case TM_TYPE:    /* magick type name */
    {
	char *name;
	TclMagickObj *mPtr;

	if( objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	mPtr = findMagickObj(interp, TM_TYPE_ANY, name);
	if (mPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetResult(interp, (char *)objTypeNames[mPtr->type], TCL_VOLATILE);

	break;
    }

    case TM_TYPES:    /* magick types */
    {
	int type;

	if( objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	for ( type = 0; type < TM_TYPE_ANY; type++ ) {
	    Tcl_AppendElement(interp, objTypeNames[type]);
	}
	break;
    }

    case TM_RESOURCE:      /* resourcelimit resourceType ?limit? */
    {
        unsigned long limit;
        int  resourceIdx;

	if( (objc != 3) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "resourceType ?limit?");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], resourceNames,
				"resourceType", 0, &resourceIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set channel depth
	     */
	    if( (stat = Tcl_GetLongFromObj(interp, objv[3], &limit)) != TCL_OK ) {
		return stat;
	    }
	    result = MagickSetResourceLimit(resourceTypes[resourceIdx], limit);
	    if (!result) {
		return myMagickError(interp, NULL);
	    }
	} else {
	    /*
	     * Get channel depth
	     */
	    limit = MagickGetResourceLimit(resourceTypes[resourceIdx]);
	    Tcl_SetObjResult(interp, Tcl_NewLongObj((long)limit));
	}
	break;
    }

    case TM_FONTS:    /* fonts pattern */
    {
        int     i;
	long listLen = 0;
        Tcl_Obj *listPtr;
        char    *pattern = "*";
        char    **fonts;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
	    return TCL_ERROR;
	}
        if( objc > 2 ) {
            pattern = Tcl_GetString(objv[2]);
        }

	fonts = MagickQueryFonts(pattern, &listLen);
	if( (fonts != NULL) && (listLen > 0) ) {
            listPtr = Tcl_NewListObj(0, NULL);
	    for( i=0; i < listLen; i++ ) {
                Tcl_ListObjAppendElement(interp, listPtr,
					 Tcl_NewStringObj(fonts[i], (int)strlen(fonts[i])) );
            }
    	    Tcl_SetObjResult(interp, listPtr);
        }
	if (fonts != NULL)
	    MagickRelinquishMemory(fonts); /* Free TclMagick resource */

        break;
    }

    case TM_FORMATS:    /* formats pattern */
    {
        int     i;
	long listLen = 0;
        Tcl_Obj *listPtr;
        char    *pattern = "*";
        char    **fonts;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?pattern?");
	    return TCL_ERROR;
	}
        if( objc > 2 ) {
            pattern = Tcl_GetString(objv[2]);
        }

	fonts = MagickQueryFormats(pattern, &listLen);
	if( (fonts != NULL) && (listLen > 0) ) {
            listPtr = Tcl_NewListObj(0, NULL);
	    for( i=0; i < listLen; i++ ) {
                Tcl_ListObjAppendElement(interp, listPtr,
					 Tcl_NewStringObj(fonts[i], (int)strlen(fonts[i])) );
            }
    	    Tcl_SetObjResult(interp, listPtr);
        }
	if (fonts != NULL)
	    MagickRelinquishMemory(fonts); /* Free TclMagick resource */

        break;
    }

    case TM_VERSION:    /* magick version */
    {
	if( objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	Tcl_SetResult(interp, VERSION, TCL_VOLATILE);

	break;
    }

    case TM_LIBRARY:    /* magick library ?-option? */
    {
	static CONST char *options[] = {
	    "-copyright",  "-date",    "-name",       "-quantumdepth", 
	    "-url",        "-version", "-versionstr", "-maxrgb",
	    (char *) NULL
	};
        char  buf[40];
        const char *str;
        unsigned long depth=0, version=0, maxrgb=0;

        if( objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-option?");
	    return TCL_ERROR;
	}
	/*
	 * If called without parameters, return a list of
	 * -option value -option value ...
	 */
	if( objc == 2 ) {
	    Tcl_Obj *listPtr = Tcl_NewListObj(0, NULL);

            str = MagickGetCopyright();
	    Tcl_ListObjAppendElement(
		interp, listPtr,
		Tcl_NewStringObj(options[0], -1));
	    Tcl_ListObjAppendElement(
		interp, listPtr, Tcl_NewStringObj(str, -1));

            str = MagickGetReleaseDate();
	    Tcl_ListObjAppendElement(
		interp, listPtr,
		Tcl_NewStringObj(options[1], -1));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(str, -1));

            str = MagickGetPackageName();
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(options[2], -1));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(str, -1));

            str = MagickGetQuantumDepth(&depth);
            maxrgb = (1 << depth) - 1;
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(options[3], -1));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj((signed long)depth));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(options[7], -1));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj((signed long)maxrgb));

            str = MagickGetHomeURL();
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(options[4], -1));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(str, -1));

            str = MagickGetVersion(&version);
            sprintf( buf, "%ld.%ld.%ld", version >> 8, (version >> 4) & 0x0F, version & 0x0F);
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(options[5], -1));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(buf, -1));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(options[6], -1));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(str, -1));


            Tcl_SetObjResult(interp, listPtr);
        } else {
            int idx;

            if (Tcl_GetIndexFromObj(interp, objv[2], options, "-option", 0, &idx) != TCL_OK) {
	        return TCL_ERROR;
            }
            switch( idx ) {
            case 0: /* -copyright */
                str = MagickGetCopyright();
                Tcl_SetObjResult(interp, Tcl_NewStringObj(str, -1));
                break;
            case 1: /* -date */
                str = MagickGetReleaseDate();
                Tcl_SetObjResult(interp, Tcl_NewStringObj(str, -1));
                break;
            case 2: /* -name */
                str = MagickGetPackageName();
                Tcl_SetObjResult(interp, Tcl_NewStringObj(str, -1));
                break;
            case 3: /* -quantumdepth */
                MagickGetQuantumDepth(&depth);
                Tcl_SetObjResult(interp, Tcl_NewLongObj((signed long)depth));
                break;
            case 4: /* -url */
                str = MagickGetHomeURL();
                Tcl_SetObjResult(interp, Tcl_NewStringObj(str, -1));
                break;
            case 5: /* -version */
                MagickGetVersion(&version);
                sprintf( buf, "%ld.%ld.%ld", version >> 8, (version >> 4) & 0x0F, version & 0x0F);
                Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
                break;
            case 6: /* -versionstr */
                str = MagickGetVersion(&version);
                Tcl_SetObjResult(interp, Tcl_NewStringObj(str, -1));
                break;
            case 7: /* -maxrgb */
                MagickGetQuantumDepth(&depth);
		maxrgb = (1 << depth) - 1;
                Tcl_SetObjResult(interp, Tcl_NewLongObj((signed long)maxrgb));
                break;
            default:
                break;
            }

        }

	break;
    }

    } /* switch(index) */

    return(TCL_OK);
}


/*----------------------------------------------------------------------
 * MagickWand object command
 *----------------------------------------------------------------------
 *
 * MagickWand subcmd ?args?
 *
 *----------------------------------------------------------------------
 */
static int wandObjCmd(
    ClientData  clientData,         /* MagickWand pointer */
    Tcl_Interp  *interp,            /* Interpreter containing image */
    int         objc,               /* Number of arguments */
    Tcl_Obj     *CONST objv[] )     /* List of arguments */
{
    static CONST char *subCmds[] = {
        "adaptivethreshold","AdaptiveThresholdImage",
        "add",              "AddImage",
        "addnoise",         "AddNoiseImage",
        "affinetransform",  "AffineTransformImage",
        "annotate",         "AnnotateImage",
        "append",           "AppendImages",
        "average",          "AverageImages",
        "blackthreshold",   "BlackThresholdImage",
        "blur",             "BlurImage",
        "border",           "BorderImage",
        "charcoal",         "CharcoalImage",
        "chop",             "ChopImage",
        "clip",             "ClipImage",
        "clippath",         "ClipPathImage",
        "clone",            "CloneWand",
        "coalesce",         "CoalesceImages",
        "colorfloodfill",   "ColorFloodfillImage",
        "colorize",         "ColorizeImage",
        "comment",          "CommentImage",
        "comparechannels",  "CompareImageChannels",
        "compare",          "CompareImages",
        "composite",        "CompositeImage",
        "contrast",         "ContrastImage",
        "convolve",         "ConvolveImage",
        "crop",             "CropImage",
        "cyclecolormap",    "CycleColormapImage",
        "deconstruct",      "DeconstructImages",
        "describe",         "DescribeImage",
        "despeckle",        "DespeckleImage",
        "draw",             "DrawImage",
        "edge",             "EdgeImage",
        "emboss",           "EmbossImage",
        "enhance",          "EnhanceImage",
        "equalize",         "EqualizeImage",
        "flatten",          "FlattenImages",
        "flip",             "FlipImage",
        "flop",             "FlopImage",
        "frame",            "FrameImage",
        "fx",               "FxImage",
        "fxchannel",        "FxImageChannel",
        "gammaimage",       "GammaImage",
        "gammachannel",     "GammaImageChannel",
        "filename",         "GetFilename",          "SetFilename",
        "backgroundcolor",  "GetBackgroundColor",   "SetBackgroundColor",
        "blueprimary",      "GetBluePrimary",       "SetBluePrimary",
        "bordercolor",      "GetBorderColor",       "SetBorderColor",
        "channeldepth",     "GetChannelDepth",      "SetChannelDepth",
        "channelextrema",   "GetChannelExtrema",
        "channelmean",      "GetChannelMean",
        "colormapcolor",    "GetColormapColor",     "SetColormapColor",
        "colors",           "GetColors",
        "colorspace",       "GetColorspace",        "SetColorspace",
        "compose",          "GetCompose",           "SetCompose",
        "compression",      "GetCompression",       "SetCompression",
        "delay",            "GetDelay",             "SetDelay",
        "depth",            "GetDepth",             "SetDepth",
        "dispose",          "GetDispose",           "SetDispose",
        "extrema",          "GetExtrema",
        "format",           "GetFormat",
        "getimage",         "GetImage",
        "imagefilename",    "GetImageFilename",     "SetImageFilename",
        "gamma",            "GetGamma",             "SetGamma",
        "greenprimary",     "GetGreenPrimary",      "SetGreenPrimary",
        "height",           "GetHeight",
        "index",            "GetIndex",             "SetIndex",
        "interlace",        "GetInterlaceScheme",   "SetInterlaceScheme",
        "iterations",       "GetIterations",        "SetIterations",
        "mattecolor",       "GetMatteColor",        "SetMatteColor",
        "pixels",           "GetPixels",            "SetPixels",
        "profile",          "GetProfile",           "SetProfile",
        "ProfileImage",     "RemoveProfile",
        "redprimary",       "GetRedPrimary",        "SetRedPrimary",
        "renderingintent",  "GetRenderingIntent",   "SetRenderingIntent",
        "resolution",       "GetResolution",        "SetResolution",
        "scene",            "GetScene",             "SetScene",
        "signature",        "GetSignature",
        "imagesize",        "GetImageSize",
        "imagetype",        "GetImageType",         "SetImageType",
        "imageunits",       "GetImageUnits",        "SetImageUnits",
        "virtualpixelmethod","GetVirtualPixelMethod","SetVirtualPixelMethod",
        "whitepoint",       "GetWhitePoint",        "SetWhitePoint",
        "width",            "GetWidth",
        "number",           "GetNumberImages",
        "samplingfactors",  "GetSamplingFactors",   "SetSamplingFactors",
        "size",             "GetSize",              "SetSize",
        "hasnext",          "HasNext",
        "hasprevious",      "HasPrevious",
        "implode",          "ImplodeImage",
        "label",            "LabelImage",
        "level",            "LevelImage",
        "levelchannel",     "LevelImageChannel",
        "magnify",          "MagnifyImage",
        "map",              "MapImage",
        "mattefloodfill",   "MatteFloodfillImage",
        "medianfilter",     "MedianFilterImage",
        "minify",           "MinifyImage",
        "modulate",         "ModulateImage",
        "montage",          "MontageImage",
        "morph",            "MorphImages",
        "mosaic",           "MosaicImages",
        "motionblur",       "MotionBlurImage",
        "negate",           "NegateImage",
        "negatechannel",    "NegateImageChannel",
        "next",             "NextImage",
        "normalize",        "NormalizeImage",
        "oilpaint",         "OilPaintImage",
        "opaque",           "OpaqueImage",
        "ping",             "PingImage",
        "preview",          "PreviewImages",
        "previous",         "PreviousImage",
        "quantize",         "QuantizeImage",        "QuantizeImages",
        "queryfontmetrics", "QueryFontMetrics",
        "raise",            "RaiseImage",
        "read",             "ReadImage",
        "readblob",         "ReadImageBlob",
        "reducenoise",      "ReduceNoiseImage",
        "remove",           "RemoveImage",
        "resetiterator",    "ResetIterator",
        "resample",         "ResampleImage",
        "resize",           "ResizeImage",
        "roll",             "RollImage",
        "rotate",           "RotateImage",
        "sample",           "SampleImage",
        "scale",            "ScaleImage",
        "separate",         "SeparateImageChannel",
        "setimage",         "SetImage",
        "setoption",        "SetOption",
        "passphrase",       "SetPassphrase",
        "sharpen",          "SharpenImage",
        "shave",            "ShaveImage",
        "shear",            "ShearImage",
        "solarize",         "SolarizeImage",
        "spread",           "SpreadImage",
        "stegano",          "SteganoImage",
        "stereo",           "StereoImage",
        "strip",            "StripImage",
        "swirl",            "SwirlImage",
        "texture",          "TextureImage",
        "threshold",        "ThresholdImage",
        "thresholdchannel", "ThresholdImageChannel",
        "tint",             "TintImage",
        "transform",        "TransformImage",
        "transparent",      "TransparentImage",
        "trim",             "TrimImage",
        "unsharpmask",      "UnsharpMaskImage",
        "wave",             "WaveImage",
        "whitethreshold",   "WhiteThresholdImage",
        "write",            "WriteImage",           "WriteImages",
        "writeblob",        "WriteImageBlob",
        (char *) NULL
    };
    enum subIndex {
        TM_ADAPTIVE,        TM_ADAPTIVE_THRESHOLD_IMAGE,
        TM_ADD,             TM_ADD_IMAGE,
        TM_ADDNOISE,        TM_ADD_NOISE_IMAGE,
        TM_AFFINE_TRANSFORM,TM_AFFINE_TRANSFORM_IMAGE,
        TM_ANNOTATE,        TM_ANNOTATE_IMAGE,
        TM_APPEND,          TM_APPEND_IMAGES,
        TM_AVERAGE,         TM_AVERAGE_IMAGES,
        TM_BLACK_THRESHOLD, TM_BLACK_THRESHOLD_IMAGE,
        TM_BLUR,            TM_BLUR_IMAGE,
        TM_BORDER,          TM_BORDER_IMAGE,
        TM_CHARCOAL,        TM_CHARCOAL_IMAGE,
        TM_CHOP,            TM_CHOP_IMAGE,
        TM_CLIP,            TM_CLIP_IMAGE,
        TM_CLIP_PATH,       TM_CLIP_PATH_IMAGE,
        TM_CLONE,           TM_CLONE_WAND,
        TM_COALESCE,        TM_COALESCE_IMAGES,
        TM_COLOR_FLOODFILL, TM_COLOR_FLOODFILL_IMAGE,
        TM_COLORIZE,        TM_COLORIZE_IMAGE,
        TM_COMMENT,         TM_COMMENT_IMAGE,
        TM_COMPARE_CHANNELS,TM_COMPARE_IMAGE_CHANNELS,
        TM_COMPARE,         TM_COMPARE_IMAGES,
        TM_COMPOSITE,       TM_COMPOSITE_IMAGE,
        TM_CONTRAST,        TM_CONTRAST_IMAGE,
        TM_CONVOLVE,        TM_CONVOLVE_IMAGE,
        TM_CROP,            TM_CROP_IMAGE,
        TM_CYCLE_COLORMAP,  TM_CYCLE_COLORMAP_IMAGE,
        TM_DECONSTRUCT,     TM_DECONSTRUCT_IMAGES,
        TM_DESCRIBE,        TM_DESCRIBE_IMAGE,
        TM_DESPECKLE,       TM_DESPECKLE_IMAGE,
        TM_DRAW,            TM_DRAW_IMAGE,
        TM_EDGE,            TM_EDGE_IMAGE,
        TM_EMBOSS,          TM_EMBOSS_IMAGE,
        TM_ENHANCE,         TM_ENHANCE_IMAGE,
        TM_EQUALIZE,        TM_EQUALIZE_IMAGE,
        TM_FLATTEN,         TM_FLATTEN_IMAGES,
        TM_FLIP,            TM_FLIP_IMAGE,
        TM_FLOP,            TM_FLOP_IMAGE,
        TM_FRAME,           TM_FRAME_IMAGE,
        TM_FX,              TM_FX_IMAGE,
        TM_FX_CHANNEL,      TM_FX_IMAGE_CHANNEL,
        TM_GAMMAIMAGE,      TM_GAMMA_IMAGE,
        TM_GAMMACHANNEL,    TM_GAMMA_IMAGE_CHANNEL,
        TM_FILENAME,        TM_GET_FILENAME,            TM_SET_FILENAME,
        TM_BACKGROUND_COLOR,TM_GET_BACKGROUND_COLOR,    TM_SET_BACKGROUND_COLOR,
        TM_BLUE_PRIMARY,    TM_GET_BLUE_PRIMARY,        TM_SET_BLUE_PRIMARY,
        TM_BORDER_COLOR,    TM_GET_BORDER_COLOR,        TM_SET_BORDER_COLOR,
        TM_CHANNEL_DEPTH,   TM_GET_CHANNEL_DEPTH,       TM_SET_CHANNEL_DEPTH,
        TM_CHANNEL_EXTREMA, TM_GET_CHANNEL_EXTREMA,
        TM_CHANNEL_MEAN,    TM_GET_CHANNEL_MEAN,
        TM_COLORMAP_COLOR,  TM_GET_COLORMAP_COLOR,      TM_SET_COLORMAP_COLOR,
        TM_COLORS,          TM_GET_COLORS,
        TM_COLORSPACE,      TM_GET_COLORSPACE,          TM_SET_COLORSPACE,
        TM_COMPOSE,         TM_GET_COMPOSE,             TM_SET_COMPOSE,
        TM_COMPRESSION,     TM_GET_COMPRESSION,         TM_SET_COMPRESSION,
        TM_DELAY,           TM_GET_DELAY,               TM_SET_DELAY,
        TM_DEPTH,           TM_GET_DEPTH,               TM_SET_DEPTH,
        TM_DISPOSE,         TM_GET_DISPOSE,             TM_SET_DISPOSE,
        TM_EXTREMA,         TM_GET_EXTREMA,
        TM_FORMAT,          TM_GET_FORMAT,
        TM_GETIMAGE,        TM_GET_IMAGE,
        TM_IMAGE_FILENAME,  TM_GET_IMAGE_FILENAME,      TM_SET_IMAGE_FILENAME,
        TM_GAMMA,           TM_GET_GAMMA,               TM_SET_GAMMA,
        TM_GREEN_PRIMARY,   TM_GET_GREEN_PRIMARY,       TM_SET_GREEN_PRIMARY,
	TM_HEIGHT,          TM_GET_HEIGHT,
        TM_INDEX,           TM_GET_INDEX,               TM_SET_INDEX,
        TM_INTERLACE,       TM_GET_INTERLACE,           TM_SET_INTERLACE,
        TM_ITERATIONS,      TM_GET_ITERATIONS,          TM_SET_ITERATIONS,
        TM_MATTE_COLOR,     TM_GET_MATTE_COLOR,         TM_SET_MATTE_COLOR,
        TM_PIXELS,          TM_GET_PIXELS,              TM_SET_PIXELS,
        TM_PROFILE,         TM_GET_PROFILE,             TM_SET_PROFILE,
        TM_PROFILE_IMAGE,   TM_REMOVE_PROFILE,
        TM_RED_PRIMARY,     TM_GET_RED_PRIMARY,         TM_SET_RED_PRIMARY,
        TM_RENDERING,       TM_GET_RENDERING,           TM_SET_RENDERING,
        TM_RESOLUTION,      TM_GET_RESOLUTION,          TM_SET_RESOLUTION,
        TM_SCENE,           TM_GET_SCENE,               TM_SET_SCENE,
        TM_SIGNATURE,       TM_GET_SIGNATURE,
        TM_IMAGE_SIZE,      TM_GET_IMAGE_SIZE,
        TM_IMAGE_TYPE,      TM_GET_IMAGE_TYPE,          TM_SET_IMAGE_TYPE,
        TM_IMAGE_UNITS,     TM_GET_IMAGE_UNITS,         TM_SET_IMAGE_UNITS,
        TM_VIRTUALPIXEL,    TM_GET_VIRTUALPIXEL,        TM_SET_VIRTUALPIXEL,
        TM_WHITE_POINT,     TM_GET_WHITE_POINT,         TM_SET_WHITE_POINT,
	TM_WIDTH,           TM_GET_WIDTH,
        TM_NUMBER,          TM_GET_NUMBER_IMAGES,
        TM_SAMPLING_FACTORS,TM_GET_SAMPLING_FACTORS,    TM_SET_SAMPLING_FACTORS,
        TM_SIZE,            TM_GET_SIZE,                TM_SET_SIZE,
	TM_HASNEXT,         TM_HAS_NEXT_IMAGE,
	TM_HASPREVIOUS,     TM_HAS_PREVIOUS_IMAGE,
        TM_IMPLODE,         TM_IMPLODE_IMAGE,
        TM_LABEL,           TM_LABEL_IMAGE,
        TM_LEVEL,           TM_LEVEL_IMAGE,
        TM_LEVEL_CHANNEL,   TM_LEVEL_IMAGE_CHANNEL,
        TM_MAGNIFY,         TM_MAGNIFY_IMAGE,
        TM_MAP,             TM_MAP_IMAGE,
        TM_MATTE_FLOODFILL, TM_MATTE_FLOODFILL_IMAGE,
        TM_MEDIANFILTER,    TM_MEDIANFILTER_IMAGE,
        TM_MINIFY,          TM_MINIFY_IMAGE,
        TM_MODULATE,        TM_MODULATE_IMAGE,
        TM_MONTAGE,         TM_MONTAGE_IMAGE,
        TM_MORPH,           TM_MORPH_IMAGES,
        TM_MOSAIC,          TM_MOSAIC_IMAGES,
        TM_MOTIONBLUR,      TM_MOTIONBLUR_IMAGE,
        TM_NEGATE,          TM_NEGATE_IMAGE,
        TM_NEGATE_CHANNEL,  TM_NEGATE_IMAGE_CHANNEL,
        TM_NEXT,            TM_NEXT_IMAGE,
        TM_NORMALIZE,       TM_NORMALIZE_IMAGE,
        TM_OILPAINT,        TM_OILPAINT_IMAGE,
        TM_OPAQUE,          TM_OPAQUE_IMAGE,
        TM_PING,            TM_PING_IMAGE,
        TM_PREVIEW,         TM_PREVIEW_IMAGES,
        TM_PREVIOUS,        TM_PREVIOUS_IMAGE,
        TM_QUANTIZE,        TM_QUANTIZE_IMAGE,      TM_QUANTIZE_IMAGES,
        TM_QUERYFONTMETRICS,TM_QUERY_FONT_METRICS,
        TM_RAISE,           TM_RAISE_IMAGE,
        TM_READ,            TM_READ_IMAGE,
        TM_READ_BLOB,       TM_READ_IMAGE_BLOB,
        TM_REDUCENOISE,     TM_REDUCENOISE_IMAGE,
        TM_REMOVE,          TM_REMOVE_IMAGE,
        TM_RESETITERATOR,   TM_RESET_ITERATOR,
        TM_RESAMPLE,        TM_RESAMPLE_IMAGE,
        TM_RESIZE,          TM_RESIZE_IMAGE,
        TM_ROLL,            TM_ROLL_IMAGE,
        TM_ROTATE,          TM_ROTATE_IMAGE,
        TM_SAMPLE,          TM_SAMPLE_IMAGE,
        TM_SCALE,           TM_SCALE_IMAGE,
        TM_SEPARATE,        TM_SEPARATE_CHANNEL,
        TM_SETIMAGE,        TM_SET_IMAGE,
        TM_SETOPTION,       TM_SET_OPTION,
        TM_PASSPHRASE,      TM_SET_PASSPHRASE,
        TM_SHARPEN,         TM_SHARPEN_IMAGE,
        TM_SHAVE,           TM_SHAVE_IMAGE,
        TM_SHEAR,           TM_SHEAR_IMAGE,
        TM_SOLARIZE,        TM_SOLARIZE_IMAGE,
        TM_SPREAD,          TM_SPREAD_IMAGE,
        TM_STEGANO,         TM_STEGANO_IMAGE,
        TM_STEREO,          TM_STEREO_IMAGE,
        TM_STRIP,           TM_STRIP_IMAGE,
        TM_SWIRL,           TM_SWIRL_IMAGE,
        TM_TEXTURE,         TM_TEXTURE_IMAGE,
        TM_THRESHOLD,       TM_THRESHOLD_IMAGE,
        TM_THRESHOLDCHANNEL,TM_THRESHOLD_IMAGE_CHANNEL,
        TM_TINT,            TM_TINT_IMAGE,
        TM_TRANSFORM,       TM_TRANSFORM_IMAGE,
        TM_TRANSPARENT,     TM_TRANSPARENT_IMAGE,
        TM_TRIM,            TM_TRIM_IMAGE,
        TM_UNSHARPMASK,     TM_UNSHARPMASK_IMAGE,
        TM_WAVE,            TM_WAVE_IMAGE,
        TM_WHITE_THRESHOLD, TM_WHITE_THRESHOLD_IMAGE,
        TM_WRITE,           TM_WRITE_IMAGE,         TM_WRITE_IMAGES,
        TM_WRITE_BLOB,      TM_WRITE_IMAGE_BLOB,
        TM_END_OF_TABLE
    };
    static CONST char *filterNames[] = {
        "undefined", "point",   "box",      "triangle", "hermite",
        "hanning",   "hamming", "blackman", "gaussian", "quadratic",
        "cubic",     "catrom",  "mitchell", "lanczos",  "bessel",
        "sinc",
        (char *) NULL
    };
    static FilterTypes filterTypes[] = {
        UndefinedFilter, PointFilter,   BoxFilter,      TriangleFilter, HermiteFilter,
        HanningFilter,   HammingFilter, BlackmanFilter, GaussianFilter, QuadraticFilter,
        CubicFilter,     CatromFilter,  MitchellFilter, LanczosFilter,  BesselFilter,
        SincFilter
    };
    static CONST char *chanNames[] = {
        "undefined", "red",    "cyan",    "green", "magenta",
        "blue",      "yellow", "opacity", "black", "matte",
        "index",
        (char *) NULL
    };
    static ChannelType chanTypes[] = {
        UndefinedChannel, RedChannel, CyanChannel, GreenChannel, MagentaChannel,
        BlueChannel, YellowChannel, OpacityChannel, BlackChannel, MatteChannel,
        IndexChannel
    };
    static CONST char *metricNames[] = {
        "meanabsoluteerror",       "meansquarederror",    "peakabsoluteerror",
        "peaksignaltonoiseratio",  "rootmeansquarederror",
        (char *) NULL
    };
    static ChannelType metricTypes[] = {
        MeanAbsoluteErrorMetric, MeanSquaredErrorMetric,  PeakAbsoluteErrorMetric,
        PeakSignalToNoiseRatioMetric, RootMeanSquaredErrorMetric
    };
    static CONST char *csNames[] = {
        "undefined", "RGB",   "GRAY",  "transparent",
        "OHTA",      "LAB",   "XYZ",   "YCbCr",
        "YCC",       "YIQ",   "YPbPr", "YUV",
        "CMYK",      "sRGB",  "HSL",   "HWB",
        (char *) NULL
    };
    static ColorspaceType csTypes[] = {
        UndefinedColorspace, RGBColorspace,   GRAYColorspace,  TransparentColorspace,
        OHTAColorspace,      LABColorspace,   XYZColorspace,   YCbCrColorspace,
        YCCColorspace,       YIQColorspace,   YPbPrColorspace, YUVColorspace,
        CMYKColorspace,      sRGBColorspace,  HSLColorspace,   HWBColorspace
    };
    static CONST char *opNames[] = {
        "undefined", "over",        "in",         "out",
        "atop",      "xor",         "plus",       "minus",
        "add",       "subtract",    "difference", "multiply",
        "bumpmap",   "copy",        "copyred",    "copygreen",
        "copyblue",  "copyopacity", "clear",      "dissolve"
        "displace",  "modulate",    "threshold",  "no",
        "darken",    "lighten",     "hue",        "saturate",
        "colorize",  "luminize",    "screen",     "overlay",
        "copycyan",  "copymagenta", "copyyellow", "copyblack",
        "replace",
	(char *) NULL
    };
    static CompositeOperator opTypes[] = {
        UndefinedCompositeOp, OverCompositeOp,        InCompositeOp,         OutCompositeOp,
        AtopCompositeOp,      XorCompositeOp,         PlusCompositeOp,       MinusCompositeOp,
        AddCompositeOp,       SubtractCompositeOp,    DifferenceCompositeOp, MultiplyCompositeOp,
        BumpmapCompositeOp,   CopyCompositeOp,        CopyRedCompositeOp,    CopyGreenCompositeOp,
        CopyBlueCompositeOp,  CopyOpacityCompositeOp, ClearCompositeOp,      DissolveCompositeOp,
        DisplaceCompositeOp,  ModulateCompositeOp,    ThresholdCompositeOp,  NoCompositeOp,
        DarkenCompositeOp,    LightenCompositeOp,     HueCompositeOp,        SaturateCompositeOp,
        ColorizeCompositeOp,  LuminizeCompositeOp,    ScreenCompositeOp,     OverlayCompositeOp,
        CopyCyanCompositeOp,  CopyMagentaCompositeOp, CopyYellowCompositeOp, CopyBlackCompositeOp,
        ReplaceCompositeOp,
    };
    static CONST char *compressNames[] = {
        "undefined", "none",   "bzip",
        "fax",       "group4", "jpeg",
        "jpeg-ls",   "lzw",    "rle",
        "zip",
        (char *) NULL
    };
    static CompressionType compressTypes[] = {
        UndefinedCompression,    NoCompression,     BZipCompression,
        FaxCompression,          Group4Compression, JPEGCompression,
        LosslessJPEGCompression, LZWCompression,    RLECompression,
        ZipCompression,
    };
    static CONST char *disposeNames[] = {
        "undefined", "none",    "background",    "previous",
        (char *) NULL
    };
    static DisposeType disposeTypes[] = {
        UndefinedDispose, NoneDispose, BackgroundDispose, PreviousDispose
    };
    static CONST char *interlaceNames[] = {
        "undefined", "none",    "line",    "plane", "partition",
        (char *) NULL
    };
    static InterlaceType interlaceTypes[] = {
        UndefinedInterlace, NoInterlace, LineInterlace, PlaneInterlace, PartitionInterlace,
    };
    static CONST char *renderNames[] = {
        "undefined", "saturation", "perceptual", "absolute", "relative",
        (char *) NULL
    };
    static RenderingIntent renderTypes[] = {
        UndefinedIntent, SaturationIntent, PerceptualIntent, AbsoluteIntent, RelativeIntent
    };
    static CONST char *typeNames[] = {
        "undefined",            "bilevel",        "grayscale",
        "grayscalematte",       "palette",        "palettematte",
        "truecolor",            "truecolormatte", "colorseparation",
        "colorseparationmatte", "optimize",
        (char *) NULL
    };
    static ImageType typeTypes[] = {
        UndefinedType,            BilevelType,        GrayscaleType,
        GrayscaleMatteType,       PaletteType,        PaletteMatteType,
        TrueColorType,            TrueColorMatteType, ColorSeparationType,
        ColorSeparationMatteType, OptimizeType
    };
    static CONST char *unitNames[] = {
        "undefined", "ppi", "ppcm",
        (char *) NULL
    };
    static ResolutionType unitTypes[] = {
        UndefinedResolution, PixelsPerInchResolution, PixelsPerCentimeterResolution
    };
    static CONST char *methodNames[] = {
        "undefined", "constant", "edge",
        "mirror",    "tile",
        (char *) NULL
    };
    static VirtualPixelMethod methodTypes[] = {
        UndefinedVirtualPixelMethod, ConstantVirtualPixelMethod, EdgeVirtualPixelMethod,
        MirrorVirtualPixelMethod,    TileVirtualPixelMethod
    };
    static CONST char *previewNames[] = {
        "undefined", "rotate",      "shear",      "roll",
        "hue",       "saturation",  "brightness", "gamma",
        "spiff",     "dull",        "grayscale",  "quantize",
        "despeckle", "reducenoise", "addnoise",   "sharpen",
        "blur",      "threshold",   "edgedetect", "spread",
        "solarize",  "shade",       "raise",      "segment",
        "swirl",     "implode",     "wave",       "oilpaint",
        "charcoal",  "jpeg",
        (char *) NULL
    };
    static PreviewType previewTypes[] = {
        UndefinedPreview,       RotatePreview,      ShearPreview,      RollPreview,
        HuePreview,             SaturationPreview,  BrightnessPreview, GammaPreview,
        SpiffPreview,           DullPreview,        GrayscalePreview,  QuantizePreview,
        DespecklePreview,       ReduceNoisePreview, AddNoisePreview,   SharpenPreview,
        BlurPreview,            ThresholdPreview,   EdgeDetectPreview, SpreadPreview,
        SolarizePreview,        ShadePreview,       RaisePreview,      SegmentPreview,
        SwirlPreview,           ImplodePreview,     WavePreview,       OilPaintPreview,
        CharcoalDrawingPreview, JPEGPreview
    };

    int index, stat, result=TCL_OK;
    TclMagickObj *magickPtr = (TclMagickObj *) clientData;
    MagickWand   *wandPtr   = (MagickWand *) magickPtr->wandPtr;

#ifdef MAGICK_DEBUG
    /*
     * Verify subCmds table size
     * No idea how to do this at compile-time
     */
    if( sizeof(subCmds)/sizeof(subCmds[0]) != TM_END_OF_TABLE + 1 ) {
        Tcl_Panic("magickObjCmd: Invalid subCmds[] table");
    }
#endif

    if( objc < 2 ) {
        Tcl_WrongNumArgs( interp, 1, objv, "subcmd ?args?" );
        return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subCmds, "subcmd", 0, &index) != TCL_OK) {
        return TCL_ERROR;
    }

    switch ((enum subIndex)index) {

    case TM_ADAPTIVE:                   /* adaptive ?width? ?height? ?ofs? */
    case TM_ADAPTIVE_THRESHOLD_IMAGE:   /* AdaptiveThresholdImage ?width? ?height? ?ofs? */
    {
	unsigned long width=1, height=1;
	long ofs=0;

	if( (objc > 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?width? ?height? ?ofs?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetLongFromObj(interp, objv[2], &width)) != TCL_OK) ) {
	    return stat;
	}
	height = width; /* default */
	if( (objc > 3) && ((stat = Tcl_GetLongFromObj(interp, objv[3], &height)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetLongFromObj(interp, objv[4], &ofs)) != TCL_OK) ) {
	    return stat;
	}

	result = MagickAdaptiveThresholdImage(wandPtr, width, height, ofs);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_ADD:            /* add name */
    case TM_ADD_IMAGE:      /* AddImage name */
    {
	MagickWand      *addWand;
	char            *name;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (addWand = findMagickWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	result = MagickAddImage( wandPtr, addWand );
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}

	break;
    }

    case TM_ADDNOISE:          /* addnoise ?noiseType? */
    case TM_ADD_NOISE_IMAGE:   /* AddNoiseImage ?noiseType? */
    {
	static CONST char *noiseNames[] = {
	    "uniform", "gaussian", "multiplicativegaussian", "impulse", "laplacian", "poisson",
	    (char *) NULL
	};
	static NoiseType noiseTypes[] = {
	    UniformNoise, GaussianNoise, MultiplicativeGaussianNoise, ImpulseNoise, LaplacianNoise, PoissonNoise
	};
	int noiseIdx=0;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?noiseType=uniform?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && (Tcl_GetIndexFromObj(interp, objv[2], noiseNames, "noiseType", 0, &noiseIdx) != TCL_OK) ) {
	    return TCL_ERROR;
	}
	result = MagickAddNoiseImage(wandPtr, noiseTypes[noiseIdx]);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_AFFINE_TRANSFORM:       /* affinetransform draw */
    case TM_AFFINE_TRANSFORM_IMAGE: /* AffineTransformImage draw */
    {
	char	*name;
	DrawingWand	*drawPtr;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "draw");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (drawPtr = findDrawingWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}

	result = MagickAffineTransformImage(wandPtr, drawPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_ANNOTATE:       /* annotate draw ?x y? ?angle? txt */
    case TM_ANNOTATE_IMAGE: /* AnnotateImage draw ?x y? ?angle? txt */
        {
	    char	*name;
	    DrawingWand	*drawPtr;
            double      x=0.0, y=0.0, angle=0.0;
            char        *txt="";

            if( (objc < 4) || (objc > 7) || (objc == 5) ) {
                Tcl_WrongNumArgs(interp, 2, objv, "draw ?x=0.0 y=0.0? ?angle=0.0? txt");
                return TCL_ERROR;
            }
            name = Tcl_GetString(objv[2]);
            if( (drawPtr = findDrawingWand(interp, name)) == NULL ) {
		return TCL_ERROR;
	    }
            if( objc >= 6 ) {	/* we have parameters x y */
                if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &x)) != TCL_OK ) {
                    return stat;
		}
                if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &y)) != TCL_OK ) {
                    return stat;
		}
            }
            if( objc == 7 ) {	/* we have parameter angle */
                if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &angle)) != TCL_OK ) {
                    return stat;
		}
            }
	    txt = Tcl_GetString(objv[objc-1]);

            result = MagickAnnotateImage(wandPtr, drawPtr, x, y, angle, txt);
            if (!result) {
                return myMagickError(interp, wandPtr);
            }
            break;
        }

    case TM_APPEND:         /* append ?stack=0? ?newName? */
    case TM_APPEND_IMAGES:  /* AppendImages ?stack=0? ?newName? */
    {
	unsigned int stack=0;
	MagickWand *newWand;
	char *name=NULL;

	if( objc > 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?stack=0? ?newName?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetBooleanFromObj(interp, objv[2], &stack)) != TCL_OK) ) {
	    return stat;
	}
	if( objc > 3 ) {
	    name = Tcl_GetString(objv[3]);
	}
	newWand = MagickAppendImages(wandPtr, stack);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_AVERAGE:        /* average ?newName? */
    case TM_AVERAGE_IMAGES: /* AverageImages ?newName? */
    {
	MagickWand *newWand;
	char *name=NULL;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?newName?");
	    return TCL_ERROR;
	}
	if( objc > 2 ) {
	    name = Tcl_GetString(objv[2]);
	}
	newWand = MagickAverageImages(wandPtr);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }


    case TM_BLACK_THRESHOLD:        /* blackthreshold thresholdPixel */
    case TM_BLACK_THRESHOLD_IMAGE:  /* BlackThresholdImage thresholdPixel */
    {
	char	    *name;
	PixelWand   *threshPtr;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "thresholdPixel");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (threshPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}

	result = MagickBlackThresholdImage(wandPtr, threshPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_BLUR:        /* blur ?radius? ?sigma? */
    case TM_BLUR_IMAGE:  /* BlurImage ?radius? ?sigma? */
    {
	double  radius=0.0, sigma=1.0;

	if( objc > 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0? ?sigma=1.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &sigma)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickBlurImage(wandPtr, radius, sigma);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_BORDER:        /* border borderPixel ?width? ?height? */
    case TM_BORDER_IMAGE:  /* BorderImage borderPixel ?width? ?height? */
    {
	unsigned long width=1, height=1;
	char        *name;
	PixelWand   *borderPtr;

	if( (objc < 3) || (objc > 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "borderPixel ?width=1? ?height=width?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (borderPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( (objc > 3) && ((stat = Tcl_GetLongFromObj(interp, objv[3], &width)) != TCL_OK) ) {
	    return stat;
	}
	height = width; /* default */
	if( (objc > 4) && ((stat = Tcl_GetLongFromObj(interp, objv[4], &height)) != TCL_OK) ) {
	    return stat;
	}

	result = MagickBorderImage(wandPtr, borderPtr, width, height);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_CHARCOAL:        /* charcoal ?radius? ?sigma? */
    case TM_CHARCOAL_IMAGE:  /* CharcoalImage ?radius? ?sigma? */
    {
	double  radius=0.0, sigma=1.0;

	if( objc > 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0? ?sigma=1.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &sigma)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickCharcoalImage(wandPtr, radius, sigma);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_CHOP:        /* chop width height ?x y? */
    case TM_CHOP_IMAGE:  /* ChopImage width height ?x y? */
    {
	unsigned long width, height;
	long x=0, y=0;

	if( (objc < 4) || (objc > 6) || (objc == 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "width height ?x=0 y=0?");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &width)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[3], &height)) != TCL_OK ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetLongFromObj(interp, objv[4], &x)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 5) && ((stat = Tcl_GetLongFromObj(interp, objv[5], &y)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickChopImage(wandPtr, width, height, x, y);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_CLIP:        /* clip */
    case TM_CLIP_IMAGE:  /* ClipImage */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickClipImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }


    case TM_CLIP_PATH:          /* clip pathname ?inside=0? */
    case TM_CLIP_PATH_IMAGE:    /* ClipImage pathname ?inside=0? */
    {
	unsigned int inside=0;
	char *pathname=NULL;

	if( (objc < 3) || (objc > 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pathname ?inside=0?");
	    return TCL_ERROR;
	}
        pathname = Tcl_GetString(objv[2]);
	if( (objc > 3) && ((stat = Tcl_GetBooleanFromObj(interp, objv[3], &inside)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickClipPathImage(wandPtr, pathname, inside );
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_CLONE:       /* clone ?newName? */
    case TM_CLONE_WAND:  /* CloneWand ?newName? */
    {
	MagickWand *newWand;
	char *name=NULL;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?newName?");
	    return TCL_ERROR;
	}
	if( objc > 2 ) {
	    name = Tcl_GetString(objv[2]);
	}
	newWand = CloneMagickWand(wandPtr);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_COALESCE:        /* coalesce ?newName? */
    case TM_COALESCE_IMAGES: /* CoalesceImages ?newName? */
    {
	MagickWand *newWand;
	char *name=NULL;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?newName?");
	    return TCL_ERROR;
	}
	if( objc > 2 ) {
	    name = Tcl_GetString(objv[2]);
	}
	newWand = MagickCoalesceImages(wandPtr);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_COLOR_FLOODFILL:        /* colorfloodfill fillPixel ?fuzz? ?borderPix? ?x y? */
    case TM_COLOR_FLOODFILL_IMAGE:  /* ColorFloodfillImage ?fuzz? ?borderPix? ?x y? */
				    /* - empty borderPix is allowed */
    {
	int	x=0, y=0;
	double  fuzz=0.0;
	char	*name;
	PixelWand *fillPtr, *borderPtr = NULL;

	if( (objc < 3) || (objc > 7) || (objc == 6) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "fillPixel ?fuzz=0.0? ?borderPix=fillPix? ?x=0 y=0?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (fillPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &fuzz)) != TCL_OK) ) {
	    return stat;
	}
	if( objc > 4 ) {
	    name = Tcl_GetString(objv[4]);
	    if( noWandObj(name) ) {
		borderPtr = NULL;
	    } else if( (borderPtr = findPixelWand(interp, name)) == NULL ) {
		return TCL_ERROR;
	    }
	}
	if( (objc > 5) && ((stat = Tcl_GetIntFromObj(interp, objv[5], &x)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 6) && ((stat = Tcl_GetIntFromObj(interp, objv[6], &y)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickColorFloodfillImage(wandPtr, fillPtr, fuzz, borderPtr, x, y);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_COLORIZE:       /* colorize fillPixel opacityPixel */
    case TM_COLORIZE_IMAGE: /* ColorizeImage fillPixel opacityPixel */
    {
	char	*name;
	PixelWand	*fillPtr, *opacityPtr;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "fillPixel opacityPixel");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (fillPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[3]);
	if( (opacityPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}

	result = MagickColorizeImage(wandPtr, fillPtr, opacityPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_COMMENT:        /* comment str */
    case TM_COMMENT_IMAGE:  /* CommentImage str */
    {
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "str");
	    return TCL_ERROR;
	}
	result = MagickCommentImage(wandPtr, Tcl_GetString(objv[2]));
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}

	break;
    }

    case TM_COMPARE_CHANNELS:        /* comparechannels refName chan metric */
    case TM_COMPARE_IMAGE_CHANNELS:  /* CompareImageChannels refName chan metric */
    {
	MagickWand      *refWand, *newWand;
        int             metricIdx, chanIdx;
	char            *name;
	double          value;

	if( objc != 5 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "refName");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (refWand = findMagickWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[3], chanNames,
				"channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[4], metricNames,
				"metricType", 0, &metricIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	newWand = MagickCompareImageChannels( wandPtr, refWand, chanTypes[chanIdx],
					      metricTypes[metricIdx], &value );
	if (newWand != NULL) {
            DestroyMagickWand(newWand);
	} else {
	    myMagickError(interp, wandPtr);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(value));

	break;
    }

    case TM_COMPARE:         /* compare refName metric */
    case TM_COMPARE_IMAGES:  /* CompareImages refName metric */
    {
	MagickWand      *refWand, *newWand;
        int             metricIdx;
	char            *name;
	double          value;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "refName metric");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (refWand = findMagickWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[3], metricNames,
				"metricType", 0, &metricIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	newWand = MagickCompareImages( wandPtr, refWand, metricTypes[metricIdx], &value );
	if (newWand != NULL) {
            DestroyMagickWand(newWand);
	} else {
	    myMagickError(interp, wandPtr);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(value));

	break;
    }

    case TM_COMPOSITE:          /* composite compWand opType ?x y? */
    case TM_COMPOSITE_IMAGE:    /* CompositeImage compWand opType ?x y? */
    {
	int opIdx;

	char	    *name;
	MagickWand  *compPtr;
	int x=0;
	int y=0;

	if( (objc < 4) || (objc > 6) || (objc == 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "opType compWand ?x=0 y=0?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (compPtr = findMagickWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[3], opNames, "opType", 0, &opIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	if( (objc > 4) && ((stat = Tcl_GetIntFromObj(interp, objv[4], &x)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 5) && ((stat = Tcl_GetIntFromObj(interp, objv[5], &y)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickCompositeImage(wandPtr, compPtr, opTypes[opIdx], x, y);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}

	break;
    }

    case TM_CONTRAST:        /* contrast ?sharpen? */
    case TM_CONTRAST_IMAGE:  /* ContrastImage ?sharpen? */
    {
	unsigned int sharpen=1;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?sharpen=yes?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetBooleanFromObj(interp, objv[2], &sharpen)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickContrastImage(wandPtr, sharpen);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_CONVOLVE:       /* convolve order kernelList */
    case TM_CONVOLVE_IMAGE: /* ConvolveImage order kernelList */
    {
	int     i, listLen;
	unsigned long order;
	double  *kernel;
	Tcl_Obj **listPtr;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "order kernelList");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &order)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_ListObjGetElements(interp, objv[3], &listLen, &listPtr)) != TCL_OK) {
	    return stat;
	}
	if( (unsigned long)listLen != order * order ) {
	    Tcl_AppendResult(
		interp,
		"ConvolveImage: Invalid kernelList length, should be = (order x order)", NULL);
	    return TCL_ERROR;
	}
	kernel = (double *)ckalloc(listLen * sizeof(double));
	if( kernel == NULL ) {
	    Tcl_AppendResult(interp, "TclMagick: out of memory", NULL);
	    return TCL_ERROR;
	}
	for( i=0; i < listLen; i++ ) {
	    if( (stat = Tcl_GetDoubleFromObj(interp, listPtr[i], &kernel[i])) != TCL_OK) {
		ckfree((char *)kernel);
		return stat;
	    }
	}

	result = MagickConvolveImage(wandPtr, order, kernel);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_CROP:        /* crop width height ?x y? */
    case TM_CROP_IMAGE:  /* CropImage width height ?x y? */
    {
	unsigned long width, height;
	long x=0, y=0;

	if( (objc < 4) || (objc > 6) || (objc == 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "width height ?x=0 y=0?");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &width)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[3], &height)) != TCL_OK ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetLongFromObj(interp, objv[4], &x)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 5) && ((stat = Tcl_GetLongFromObj(interp, objv[5], &y)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickCropImage(wandPtr, width, height, x, y);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_CYCLE_COLORMAP:         /* cyclecolormap ?displace? */
    case TM_CYCLE_COLORMAP_IMAGE:   /* CycleColormapImage ?displace? */
    {
	int displace=1;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?displace=1?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetIntFromObj(interp, objv[2], &displace)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickCycleColormapImage(wandPtr, displace);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_DECONSTRUCT:        /* deconstruct ?newName? */
    case TM_DECONSTRUCT_IMAGES: /* DeconstructImage ?newName? */
    {
	MagickWand *newWand;
	char *name=NULL;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?newName?");
	    return TCL_ERROR;
	}
	if( objc > 2 ) {
	    name = Tcl_GetString(objv[2]);
	}
	newWand = MagickDeconstructImages(wandPtr);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_DESCRIBE:       /* describe */
    case TM_DESCRIBE_IMAGE: /* DescribeImage */
    {
	char *txt;

	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	txt = MagickDescribeImage(wandPtr);
	if(txt != NULL) {
	    Tcl_SetResult(interp, txt, TCL_VOLATILE);
	    MagickRelinquishMemory(txt); /* Free TclMagick resource */
	}
	break;
    }

    case TM_DESPECKLE:          /* despeckle */
    case TM_DESPECKLE_IMAGE:    /* DespeckleImage */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickDespeckleImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_DRAW:       /* draw draw */
    case TM_DRAW_IMAGE: /* DrawImage draw */
    {
	char	*name;
	DrawingWand	*drawPtr;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "draw");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (drawPtr = findDrawingWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	result = MagickDrawImage(wandPtr, drawPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_EDGE:       /* edge ?radius? */
    case TM_EDGE_IMAGE: /* EdgeImage ?radius? */
    {
	double  radius=0.0;

	if( objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickEdgeImage(wandPtr, radius);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_EMBOSS:        /* emboss ?radius? ?sigma? */
    case TM_EMBOSS_IMAGE:  /* EmbossImage ?radius? ?sigma? */
    {
	double  radius=0.0, sigma=1.0;

	if( objc > 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0? ?sigma=1.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &sigma)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickEmbossImage(wandPtr, radius, sigma);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_ENHANCE:          /* enhance */
    case TM_ENHANCE_IMAGE:    /* EnhanceImage */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickEnhanceImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_EQUALIZE:          /* equalize */
    case TM_EQUALIZE_IMAGE:    /* EqualizeImage */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickEqualizeImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_FLATTEN:          /* flatten ?newName? */
    case TM_FLATTEN_IMAGES:   /* FlattenImages ?newName? */
    {
	MagickWand *newWand;
	char *name=NULL;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?newName?");
	    return TCL_ERROR;
	}
	if( objc > 2 ) {
	    name = Tcl_GetString(objv[2]);
	}
	newWand = MagickFlattenImages(wandPtr);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_FLIP:          /* flip */
    case TM_FLIP_IMAGE:    /* FlipImage */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickFlipImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }


    case TM_FLOP:          /* flop */
    case TM_FLOP_IMAGE:    /* FlopImage */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickFlopImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_FRAME:          /* frame framePixel ?width? ?height? ?inner? ?outer? */
    case TM_FRAME_IMAGE:    /* FrameImage framePixel ?width? ?height? ?inner? ?outer? */
    {
	unsigned long width=1, height=1;
	long inner=0, outer=0;
	char        *name;
	PixelWand	*framePtr;

	if( (objc < 3) || (objc > 7) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "framePixel ?width=1? ?height=width? ?inner=0? ?outer=inner?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (framePtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( (objc > 3) && ((stat = Tcl_GetLongFromObj(interp, objv[3], &width)) != TCL_OK) ) {
	    return stat;
	}
	height = width; /* default */
	if( (objc > 4) && ((stat = Tcl_GetLongFromObj(interp, objv[4], &height)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 5) && ((stat = Tcl_GetLongFromObj(interp, objv[5], &inner)) != TCL_OK) ) {
	    return stat;
	}
	outer = inner; /* default */
	if( (objc > 6) && ((stat = Tcl_GetLongFromObj(interp, objv[6], &outer)) != TCL_OK) ) {
	    return stat;
	}

	result = MagickFrameImage(wandPtr, framePtr, width, height, inner, outer);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_FX:         /* fx expr ?newName? */
    case TM_FX_IMAGE:   /* fxImage expr ?newName? */
    {
        char	   *expr;
	MagickWand *newWand;
	char       *name=NULL;

	if( (objc != 3) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "expr ?newName?");
	    return TCL_ERROR;
	}
	expr = Tcl_GetString(objv[2]);

	if( objc > 3 ) {
	    name = Tcl_GetString(objv[3]);
	}
	newWand = MagickFxImage(wandPtr, expr);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_FX_CHANNEL:         /* fxchannel channelType expr ?newName? */
    case TM_FX_IMAGE_CHANNEL:   /* fxImageChannel channelType expr ?newName? */
    {
	int        chanIdx;
        char       *expr;
	MagickWand *newWand;
	char       *name=NULL;

	if( (objc != 4) && (objc != 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channelType expr ?newName?");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], chanNames, "channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	expr = Tcl_GetString(objv[3]);

	if( objc > 4 ) {
	    name = Tcl_GetString(objv[4]);
	}
	newWand = MagickFxImageChannel(wandPtr, chanTypes[chanIdx], expr);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_GAMMAIMAGE:  /* gammaimage level */
    case TM_GAMMA_IMAGE: /* GammaImage level */
    {
	double gamma;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "level");
	    return TCL_ERROR;
	}
	if (Tcl_GetDoubleFromObj(interp, objv[2], &gamma) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = MagickGammaImage(wandPtr, gamma);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_GAMMACHANNEL:        /* gamma channelType level */
    case TM_GAMMA_IMAGE_CHANNEL: /* GammaImage channelType level */
    {
	int    chanIdx;
	double gamma;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channelType level");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], chanNames, "channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetDoubleFromObj(interp, objv[3], &gamma) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = MagickGammaImageChannel(wandPtr, chanTypes[chanIdx], gamma);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_FILENAME:        /* filename ?filename? */
    case TM_GET_FILENAME:    /* GetFilename */
    case TM_SET_FILENAME:    /* SetFilename filename */
    {
	char *filename;

	if( ((enum subIndex)index == TM_FILENAME) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?filename?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_FILENAME) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_FILENAME) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "filename");
	    return TCL_ERROR;
	}
	if (objc > 2) { /* Set filename */
	    Tcl_DString extrep;

	    filename = Tcl_UtfToExternalDString (NULL, Tcl_GetString(objv[2]), -1, &extrep);
	    MagickSetFilename(wandPtr, filename);

	    Tcl_DStringFree (&extrep);
	} else {    /* Get filename */
	    filename = (char *)MagickGetFilename(wandPtr);
	    if(filename != NULL) {
		SetResultAsExternalString(interp, filename);
		MagickRelinquishMemory(filename); /* Free TclMagick resource */
	    }
	}
	break;
    }

    case TM_BACKGROUND_COLOR:      /* backgroundcolor ?pixel? */
    case TM_GET_BACKGROUND_COLOR:  /* GetBackgroundColor ?pixel? */
    case TM_SET_BACKGROUND_COLOR:  /* SetBackgroundColor pixel */
    {
	char *name = NULL;
        PixelWand *pixPtr = NULL;

	if( ((enum subIndex)index == TM_SET_BACKGROUND_COLOR) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pixel");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index != TM_SET_BACKGROUND_COLOR) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?pixel?");
	    return TCL_ERROR;
	}
	if (objc > 2) { /* Set color / Get color with new name */
	    name = Tcl_GetString(objv[2]);
	    pixPtr = findPixelWand(interp, name);
        }
        /*
         * SET color requires existing pixel object
         */
        if( ((enum subIndex)index == TM_SET_BACKGROUND_COLOR) && (pixPtr == NULL) ) {
	        return TCL_ERROR;
        }
        /*
         * GET color if GET_COLOR or pixel object doesn't exists
         * otherwise SET color
         */
        if( ((enum subIndex)index == TM_GET_BACKGROUND_COLOR) || (pixPtr == NULL) ) {
            if( pixPtr == NULL ) {
                pixPtr = NewPixelWand();
                name = newPixelObj(interp, pixPtr, name );
            }
            result = MagickGetImageBackgroundColor( wandPtr, pixPtr );
            if (!result) {
                return myMagickError(interp, wandPtr);
	    }
            Tcl_SetResult(interp, name, TCL_VOLATILE);
        } else {
            result = MagickSetImageBackgroundColor( wandPtr, pixPtr );
            if (!result) {
                return myMagickError(interp, wandPtr);
            }
        }
	break;
    }

    case TM_BLUE_PRIMARY:      /* blueprimary ?x y? */
    case TM_GET_BLUE_PRIMARY:  /* GetBluePrimary */
    case TM_SET_BLUE_PRIMARY:  /* SetBluePrimary x y */
    {
        double x, y;

	if( ((enum subIndex)index == TM_BLUE_PRIMARY) && (objc != 2) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?x y?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_BLUE_PRIMARY) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_BLUE_PRIMARY) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    /*
	     * Set primary = x y
	     */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
		return stat;
	    }
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK ) {
		return stat;
	    }
	    result = MagickSetImageBluePrimary(wandPtr, x, y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get primary={x y}
	     */
	    Tcl_Obj *listPtr;

	    result = MagickGetImageBluePrimary(wandPtr, &x, &y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	    listPtr = Tcl_NewListObj(0, NULL);
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(x));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(y));
	    Tcl_SetObjResult(interp, listPtr);
	}
	break;
    }

    case TM_BORDER_COLOR:      /* bordercolor ?pixel? */
    case TM_GET_BORDER_COLOR:  /* GetBorderColor ?pixel? */
    case TM_SET_BORDER_COLOR:  /* SetBorderColor pixel */
    {
	char *name = NULL;
        PixelWand *pixPtr = NULL;

	if( ((enum subIndex)index == TM_SET_BORDER_COLOR) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pixel");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index != TM_SET_BORDER_COLOR) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?pixel?");
	    return TCL_ERROR;
	}
	if (objc > 2) { /* Set color / Get color with new name */
	    name = Tcl_GetString(objv[2]);
	    pixPtr = findPixelWand(interp, name);
        }
        /*
         * SET color requires existing pixel object
         */
        if( ((enum subIndex)index == TM_SET_BORDER_COLOR) && (pixPtr == NULL) ) {
	        return TCL_ERROR;
        }
        /*
         * GET color if GET_COLOR or pixel object doesn't exists
         * otherwise SET color
         */
        if( ((enum subIndex)index == TM_GET_BORDER_COLOR) || (pixPtr == NULL) ) {
            if( pixPtr == NULL ) {
                pixPtr = NewPixelWand();
                name = newPixelObj(interp, pixPtr, name );
            }
            result = MagickGetImageBorderColor( wandPtr, pixPtr );
            if (!result) {
                return myMagickError(interp, wandPtr);
	    }
            Tcl_SetResult(interp, name, TCL_VOLATILE);
        } else {
            result = MagickSetImageBorderColor( wandPtr, pixPtr );
            if (!result) {
                return myMagickError(interp, wandPtr);
            }
        }
	break;
    }

    case TM_CHANNEL_DEPTH:      /* channeldepth channel ?depth? */
    case TM_GET_CHANNEL_DEPTH:  /* GetChannelDepth channel */
    case TM_SET_CHANNEL_DEPTH:  /* SetChannelDepth channel depth */
    {
        unsigned long depth;
        int chanIdx;

	if( ((enum subIndex)index == TM_CHANNEL_DEPTH) && (objc != 3) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channel ?depth?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_CHANNEL_DEPTH) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channel");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_CHANNEL_DEPTH) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channel depth");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], chanNames, "channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    /*
	     * Set channel depth
	     */
	    if( (stat = Tcl_GetLongFromObj(interp, objv[3], &depth)) != TCL_OK ) {
		return stat;
	    }
	    result = MagickSetImageChannelDepth(wandPtr, chanTypes[chanIdx], depth);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get channel depth
	     */
	    depth = MagickGetImageChannelDepth(wandPtr, chanTypes[chanIdx]);
	    Tcl_SetObjResult(interp, Tcl_NewLongObj((long)depth));
	}
	break;
    }

    case TM_CHANNEL_EXTREMA:      /* channelextrema channelType */
    case TM_GET_CHANNEL_EXTREMA:  /* GetChannelExtrema channelType */
    {
        long min, max;
        int chanIdx;
        Tcl_Obj *listPtr;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channelType" );
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], chanNames, "channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = MagickGetImageChannelExtrema(wandPtr, chanTypes[chanIdx], &min, &max);
        if (!result) {
	    return myMagickError(interp, wandPtr);
	}
        listPtr = Tcl_NewListObj(0, NULL);

        Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj(min));
        Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj(max));
        Tcl_SetObjResult(interp, listPtr);

        break;
    }

    case TM_CHANNEL_MEAN:      /* channelmean channelType */
    case TM_GET_CHANNEL_MEAN:  /* GetChannelMean channelType */
    {
        double mean, deviation;
        int chanIdx;
        Tcl_Obj *listPtr;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channelType" );
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], chanNames, "channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = MagickGetImageChannelMean(wandPtr, chanTypes[chanIdx], &mean, &deviation);
        if (!result) {
	    return myMagickError(interp, wandPtr);
	}
        listPtr = Tcl_NewListObj(0, NULL);

        Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(mean));
        Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(deviation));
        Tcl_SetObjResult(interp, listPtr);

        break;
    }

    case TM_COLORMAP_COLOR:      /* colormapcolor index ?pixel? */
    case TM_GET_COLORMAP_COLOR:  /* GetColormapColor index ?pixel? */
    case TM_SET_COLORMAP_COLOR:  /* SetColormapColor index pixel */
    {
	char *name = NULL;
        unsigned long idx;
        PixelWand *pixPtr = NULL;

	if( ((enum subIndex)index == TM_SET_COLORMAP_COLOR) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index pixel");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index != TM_SET_COLORMAP_COLOR) && ((objc < 3) || (objc > 4)) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index ?pixel?");
	    return TCL_ERROR;
	}
	if (Tcl_GetLongFromObj(interp, objv[2], &idx) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (objc > 3) { /* Set color / Get color with new name */
	    name = Tcl_GetString(objv[3]);
	    pixPtr = findPixelWand(interp, name);
        }
        /*
         * SET color requires existing pixel object
         */
        if( ((enum subIndex)index == TM_SET_COLORMAP_COLOR) && (pixPtr == NULL) ) {
	        return TCL_ERROR;
        }
        /*
         * GET color if GET_COLOR or pixel object doesn't exists
         * otherwise SET color
         */
        if( ((enum subIndex)index == TM_GET_COLORMAP_COLOR) || (pixPtr == NULL) ) {
            if( pixPtr == NULL ) {
                pixPtr = NewPixelWand();
                name = newPixelObj(interp, pixPtr, name );
            }
            result = MagickGetImageColormapColor( wandPtr, idx, pixPtr );
            if (!result) {
                return myMagickError(interp, wandPtr);
	    }
            Tcl_SetResult(interp, name, TCL_VOLATILE);
        } else {
            result = MagickSetImageColormapColor( wandPtr, idx, pixPtr );
            if (!result) {
                return myMagickError(interp, wandPtr);
            }
        }
	break;
    }

    case TM_COLORS:      /* colors */
    case TM_GET_COLORS:  /* GetColors */
    {
        long colors;

	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	colors = MagickGetImageColors(wandPtr);
	Tcl_SetObjResult(interp, Tcl_NewLongObj(colors));
	break;
    }

    case TM_COLORSPACE:      /* colorspace ?colorspaceType? */
    case TM_GET_COLORSPACE:  /* GetColorspace */
    case TM_SET_COLORSPACE:  /* SetColorspace colorspaceType */
    {
        int csIdx;
        ColorspaceType cs;

	if( ((enum subIndex)index == TM_COLORSPACE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?colorspaceType?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_COLORSPACE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_COLORSPACE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "colorspaceType");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set colorspace
	     */
            if (Tcl_GetIndexFromObj(interp, objv[2], csNames, "csType", 0, &csIdx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageColorspace(wandPtr, csTypes[csIdx]);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get colorspace
	     */
	    cs = MagickGetImageColorspace(wandPtr);
	    for (csIdx = 0; csIdx < sizeof(csTypes)/sizeof(csTypes[0]); csIdx++) {
		if( csTypes[csIdx] == cs ) {
		    Tcl_SetResult(interp, (char *)csNames[csIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)cs));
	}
	break;
    }

    case TM_COMPOSE:      /* compose ?opType? */
    case TM_GET_COMPOSE:  /* GetCompose */
    case TM_SET_COMPOSE:  /* SetCompose opType */
    {
        int opIdx;
        CompositeOperator op;

	if( ((enum subIndex)index == TM_COMPOSE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?opType?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_COMPOSE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_COMPOSE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "opType");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set compose operator
	     */
            if (Tcl_GetIndexFromObj(interp, objv[2], opNames, "opType", 0, &opIdx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageColorspace(wandPtr, opTypes[opIdx]);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get compose operator
	     */
	    op = MagickGetImageColorspace(wandPtr);
	    for (opIdx = 0; opIdx < sizeof(opTypes)/sizeof(opTypes[0]); opIdx++) {
		if( opTypes[opIdx] == op ) {
		    Tcl_SetResult(interp, (char *)opNames[opIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)op));
	}
	break;
    }

    case TM_COMPRESSION:      /* compression ?compressionType? */
    case TM_GET_COMPRESSION:  /* GetCompression */
    case TM_SET_COMPRESSION:  /* SetCompression compressionType */
    {
        int csIdx;
        CompressionType cs;

	if( ((enum subIndex)index == TM_COMPRESSION) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?compressionType?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_COMPRESSION) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_COMPRESSION) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "compressionType");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set compression
	     */
            if (Tcl_GetIndexFromObj(interp, objv[2], compressNames, "compressType", 0, &csIdx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageCompression(wandPtr, compressTypes[csIdx]);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get compression
	     */
	    cs = MagickGetImageCompression(wandPtr);
	    for (csIdx = 0; csIdx < sizeof(compressTypes)/sizeof(compressTypes[0]); csIdx++) {
		if( compressTypes[csIdx] == cs ) {
		    Tcl_SetResult(interp, (char *)compressNames[csIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)cs));
	}
	break;
    }

    case TM_DELAY:      /* delay ?delay? */
    case TM_GET_DELAY:  /* GetDelay */
    case TM_SET_DELAY:  /* SetDelay delay */
    {
        unsigned long delay;

	if( ((enum subIndex)index == TM_DELAY) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?delay?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_DELAY) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_DELAY) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "delay");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set delay
	     */
	    if (Tcl_GetLongFromObj(interp, objv[2], &delay) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageDelay(wandPtr, delay);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get delay
	     */
	    delay = MagickGetImageDelay(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewLongObj((long)delay));
	}
	break;
    }

    case TM_DEPTH:      /* depth ?depth? */
    case TM_GET_DEPTH:  /* GetDepth */
    case TM_SET_DEPTH:  /* SetDepth depth */
    {
        unsigned long depth;

	if( ((enum subIndex)index == TM_DEPTH) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?depth?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_DEPTH) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_DEPTH) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "depth");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set depth
	     */
	    if (Tcl_GetLongFromObj(interp, objv[2], &depth) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageDepth(wandPtr, depth);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get depth
	     */
	    depth = MagickGetImageDepth(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewLongObj((long)depth));
	}
	break;
    }

    case TM_DISPOSE:      /* dispose ?disposeType? */
    case TM_GET_DISPOSE:  /* GetDispose */
    case TM_SET_DISPOSE:  /* SetDispose disposeType */
    {
        int disposeIdx;
        DisposeType dispose;

	if( ((enum subIndex)index == TM_DISPOSE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?disposeType?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_DISPOSE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_DISPOSE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "disposeType");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set dispose
	     */
            if (Tcl_GetIndexFromObj(interp, objv[2], disposeNames, "disposeType", 0, &disposeIdx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageDispose(wandPtr, disposeTypes[disposeIdx]);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get dispose
	     */
	    dispose = MagickGetImageDispose(wandPtr);
	    for (disposeIdx = 0; disposeIdx < sizeof(disposeTypes)/sizeof(disposeTypes[0]); disposeIdx++) {
		if( disposeTypes[disposeIdx] == dispose ) {
		    Tcl_SetResult(interp, (char *)disposeNames[disposeIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)dispose));
	}
	break;
    }

    case TM_EXTREMA:      /* extrema */
    case TM_GET_EXTREMA:  /* GetExtrema */
    {
        long min, max;
        Tcl_Obj *listPtr;

	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL );
	    return TCL_ERROR;
	}
	result = MagickGetImageExtrema(wandPtr, &min, &max);
        if (!result) {
	    return myMagickError(interp, wandPtr);
	}
        listPtr = Tcl_NewListObj(0, NULL);

        Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj(min));
        Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj(max));
        Tcl_SetObjResult(interp, listPtr);

        break;
    }

    case TM_FORMAT:     /* format */
    case TM_GET_FORMAT: /* GetImageFormat */
    {
	char *fmt;

	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	fmt = (char *)MagickGetImageFormat(wandPtr);
	if(fmt != NULL) {
	    Tcl_SetResult(interp, fmt, TCL_VOLATILE);
	    MagickRelinquishMemory(fmt); /* Free TclMagick resource */
	}
	break;
    }

    case TM_GETIMAGE:   /* getimage ?newName? */
    case TM_GET_IMAGE:  /* GetImage ?newName? */
    {
	MagickWand *newWand;
	char *name=NULL;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?newName?");
	    return TCL_ERROR;
	}
	if( objc > 2 ) {
	    name = Tcl_GetString(objv[2]);
	}
	newWand = MagickGetImage(wandPtr);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_IMAGE_FILENAME:        /* imagefilename ?filename? */
    case TM_GET_IMAGE_FILENAME:    /* GetImageFilename */
    case TM_SET_IMAGE_FILENAME:    /* SetImageFilename filename */
    {
	char *filename;

	if( ((enum subIndex)index == TM_IMAGE_FILENAME) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?filename?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_IMAGE_FILENAME) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_IMAGE_FILENAME) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "filename");
	    return TCL_ERROR;
	}
	if (objc > 2) { /* Set filename */
	    Tcl_DString extrep;
	    filename = Tcl_UtfToExternalDString(NULL, Tcl_GetString(objv[2]), -1, &extrep);
	    result = MagickSetImageFilename(wandPtr, filename);
	    Tcl_DStringFree(&extrep);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {    /* Get filename */
	    filename = (char *)MagickGetImageFilename(wandPtr);
	    if(filename != NULL) {
		SetResultAsExternalString(interp, filename);
		MagickRelinquishMemory(filename); /* Free TclMagick resource */
	    }
	}
	break;
    }

    case TM_GAMMA:      /* gamma ?gamma? */
    case TM_GET_GAMMA:  /* GetGamma */
    case TM_SET_GAMMA:  /* SetGamma gamma */
    {
        double gamma;

	if( ((enum subIndex)index == TM_GAMMA) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?gamma?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_GAMMA) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_GAMMA) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "gamma");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set gamma
	     */
	    if (Tcl_GetDoubleFromObj(interp, objv[2], &gamma) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageGamma(wandPtr, gamma);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get gamma
	     */
	    gamma = MagickGetImageGamma(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(gamma));
	}
	break;
    }

    case TM_GREEN_PRIMARY:      /* greenprimary ?x y? */
    case TM_GET_GREEN_PRIMARY:  /* GetGreenPrimary */
    case TM_SET_GREEN_PRIMARY:  /* SetGreenPrimary x y */
    {
        double x, y;

	if( ((enum subIndex)index == TM_GREEN_PRIMARY) && (objc != 2) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?x y?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_GREEN_PRIMARY) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_GREEN_PRIMARY) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    /*
	     * Set primary = x y
	     */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
		return stat;
	    }
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK ) {
		return stat;
	    }
	    result = MagickSetImageGreenPrimary(wandPtr, x, y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get primary={x y}
	     */
	    Tcl_Obj *listPtr;

	    result = MagickGetImageGreenPrimary(wandPtr, &x, &y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	    listPtr = Tcl_NewListObj(0, NULL);
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(x));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(y));
	    Tcl_SetObjResult(interp, listPtr);
	}
	break;
    }

    case TM_HEIGHT:     /* height */
    case TM_GET_HEIGHT: /* GetHeight */
    {
	int value;

        if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	value = MagickGetImageHeight(wandPtr);
        Tcl_SetObjResult(interp, Tcl_NewLongObj(value));

	break;
    }

    case TM_INDEX:      /* index ?index? */
    case TM_GET_INDEX:  /* GetIndex */
    case TM_SET_INDEX:  /* SetIndex index */
    {
	long idx;

	if( ((enum subIndex)index == TM_INDEX) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?index?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_INDEX) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_INDEX) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "index");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set index
	     */
	    if (Tcl_GetLongFromObj(interp, objv[2], &idx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageIndex(wandPtr, (long) idx);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get depth
	     */
	    idx = MagickGetImageIndex(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewLongObj((long)idx));
	}
	break;
    }

    case TM_INTERLACE:      /* interlace ?interlaceType? */
    case TM_GET_INTERLACE:  /* GetInterlace */
    case TM_SET_INTERLACE:  /* SetInterlace interlaceType */
    {
        int interlaceIdx;
        InterlaceType interlace;

	if( ((enum subIndex)index == TM_INTERLACE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?interlaceType?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_INTERLACE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_INTERLACE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "interlaceType");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set interlace
	     */
            if (Tcl_GetIndexFromObj(interp, objv[2], interlaceNames,
				    "interlaceType", 0, &interlaceIdx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageInterlaceScheme(wandPtr, interlaceTypes[interlaceIdx]);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get interlace
	     */
	    interlace = MagickGetImageInterlaceScheme(wandPtr);
	    for (interlaceIdx = 0;
		 interlaceIdx < sizeof(interlaceTypes)/sizeof(interlaceTypes[0]);
		 interlaceIdx++) {
		if( interlaceTypes[interlaceIdx] == interlace ) {
		    Tcl_SetResult(interp, (char *)interlaceNames[interlaceIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)interlace));
	}
	break;
    }

    case TM_ITERATIONS:      /* iterations ?num? */
    case TM_GET_ITERATIONS:  /* GetIterations */
    case TM_SET_ITERATIONS:  /* SetIterations num */
    {
        unsigned long num;

	if( (index == TM_ITERATIONS) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?num?");
	    return TCL_ERROR;
	}
	if( (index == TM_GET_ITERATIONS) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( (index == TM_SET_ITERATIONS) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "num");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set iterations
	     */
	    if (Tcl_GetLongFromObj(interp, objv[2], &num) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageIterations(wandPtr, num);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get depth
	     */
	    num = MagickGetImageIterations(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewLongObj((long)num));
	}
	break;
    }

    case TM_MATTE_COLOR:      /* mattecolor ?pixel? */
    case TM_GET_MATTE_COLOR:  /* GetMatteColor ?pixel? */
    case TM_SET_MATTE_COLOR:  /* SetMatteColor pixel */
    {
	char *name = NULL;
        PixelWand *pixPtr = NULL;

	if( ((enum subIndex)index == TM_SET_MATTE_COLOR) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pixel");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index != TM_SET_MATTE_COLOR) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?pixel?");
	    return TCL_ERROR;
	}
	if (objc > 2) { /* Set color / Get color with new name */
	    name = Tcl_GetString(objv[2]);
	    pixPtr = findPixelWand(interp, name);
        }
        /*
         * SET color requires existing pixel object
         */
        if( ((enum subIndex)index == TM_SET_MATTE_COLOR) && (pixPtr == NULL) ) {
	        return TCL_ERROR;
        }
        /*
         * GET color if GET_COLOR or pixel object doesn't exists
         * otherwise SET color
         */
        if( ((enum subIndex)index == TM_GET_MATTE_COLOR) || (pixPtr == NULL) ) {
            if( pixPtr == NULL ) {
                pixPtr = NewPixelWand();
                name = newPixelObj(interp, pixPtr, name );
            }
            result = MagickGetImageMatteColor( wandPtr, pixPtr );
            if (!result) {
                return myMagickError(interp, wandPtr);
	    }
            Tcl_SetResult(interp, name, TCL_VOLATILE);
        } else {
            result = MagickSetImageMatteColor( wandPtr, pixPtr );
            if (!result) {
                return myMagickError(interp, wandPtr);
            }
        }
	break;
    }

    case TM_PIXELS:       /* pixels x0 y0 cols rows map storageType ?data? */
    case TM_GET_PIXELS:   /* GetPixels x0 y0 cols rows map storageType */
    case TM_SET_PIXELS:   /* GetPixels x0 y0 cols rows map storageType data */
    {
	static CONST char *storNames[] = {
	    "char", "short", "integer", "long", "float", "double",
	    (char *) NULL
	};
	static StorageType storTypes[] = {
	    CharPixel, ShortPixel, IntegerPixel, LongPixel, FloatPixel, DoublePixel
	};
	static size_t storSize[] = {
	    sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(float), sizeof(double)
	};
	unsigned long cols, rows, size;
	long x0, y0;
	int  storIdx, len;
	char *map;
	unsigned char *pixels;

	if( ((enum subIndex)index == TM_PIXELS) && ((objc < 8) || (objc > 9)) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x0 y0 cols rows map storageType ?data?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_PIXELS) && (objc != 8) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x0 y0 cols rows map storageType");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_PIXELS) && (objc != 9) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x0 y0 cols rows map storageType data");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &x0)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[3], &y0)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[4], &cols)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[5], &rows)) != TCL_OK ) {
	    return stat;
	}
	map = Tcl_GetString(objv[6]);
	if (Tcl_GetIndexFromObj(interp, objv[7], storNames, "storageType", 0, &storIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	size = cols * rows * storSize[storIdx] * strlen(map);

	if( objc == 8 ) {
            /*
             * GetImagePixels: Allocate memory for storage
             */
	    pixels = ckalloc(size);
	    if( pixels == NULL ) {
		Tcl_AppendResult(interp, "TclMagick: out of memory", NULL);
		return TCL_ERROR;
	    }

	    result = MagickGetImagePixels(wandPtr, x0, y0, cols, rows, map,
					  storTypes[storIdx], pixels);
	    if (!result) {
		ckfree(pixels);
		return myMagickError(interp, wandPtr);
	    }

	    /*
	     * Return ByteArray object
	     */
	    Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pixels, (int)size));
	    ckfree(pixels);
	} else {
	    pixels = Tcl_GetByteArrayFromObj( objv[8], &len);
	    if( (unsigned long)len < size ) {
		Tcl_AppendResult(interp, "TclMagick: not enough data bytes", NULL);
		return TCL_ERROR;
	    }
	    result = MagickSetImagePixels(wandPtr, x0, y0, cols, rows, map,
					  storTypes[storIdx], pixels);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	}
	break;
    }

    case TM_PROFILE_IMAGE:  /* ProfileImage name ?profile? */
    {
	char *name;
	unsigned char *profile = NULL;
        int length = 0;

        if( (objc != 3) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name ?profile?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);

        if( objc > 3 ) {
	    profile = Tcl_GetByteArrayFromObj(objv[3], &length);
        }
        result = MagickProfileImage(wandPtr, name, profile, (unsigned long)length);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
        break;
    }

    case TM_REMOVE_PROFILE: /* RemoveProfile name */
    {
	char *name;
	unsigned char *profile;
        unsigned long length;

        if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);

        profile = MagickRemoveImageProfile(wandPtr, (const char*)name, &length);
        if(profile != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(profile, (long)length));
	    MagickRelinquishMemory(profile); /* Free TclMagick resource */
        }
        break;
    }

    case TM_PROFILE:        /* profile name ?profile? */
    case TM_GET_PROFILE:    /* GetProfile name */
    case TM_SET_PROFILE:    /* SetProfile name profile */
    {
	char *name;
	unsigned char *profile;

	if( ((enum subIndex)index == TM_PROFILE) && (objc != 3) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name ?profile?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_PROFILE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_PROFILE) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name profile");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);

        if( objc == 4 ) {
            int length;
            /*
             * Set/Add image profile
             */
	    profile = Tcl_GetByteArrayFromObj(objv[3], &length);
	    result = MagickSetImageProfile(wandPtr, (const char*)name, profile, (unsigned long)length);
	    if (!result) {
	        return myMagickError(interp, wandPtr);
	    }
        } else {
            unsigned long length;

            profile = (char *)MagickGetImageProfile(wandPtr, name, &length);
	    if(profile != NULL) {
	        Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(profile, (long)length));
	        MagickRelinquishMemory(profile); /* Free TclMagick resource */
            }
	}
	break;
    }

    case TM_RED_PRIMARY:      /* redprimary ?x y? */
    case TM_GET_RED_PRIMARY:  /* GetRedPrimary */
    case TM_SET_RED_PRIMARY:  /* SetRedPrimary x y */
    {
        double x, y;

	if( ((enum subIndex)index == TM_RED_PRIMARY) && (objc != 2) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?x y?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_RED_PRIMARY) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_RED_PRIMARY) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    /*
	     * Set primary = x y
	     */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
		return stat;
	    }
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK ) {
		return stat;
	    }
	    result = MagickSetImageRedPrimary(wandPtr, x, y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get primary={x y}
	     */
	    Tcl_Obj *listPtr;

	    result = MagickGetImageRedPrimary(wandPtr, &x, &y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	    listPtr = Tcl_NewListObj(0, NULL);
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(x));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(y));
	    Tcl_SetObjResult(interp, listPtr);
	}
	break;
    }

    case TM_RENDERING:      /* rendering ?renderType? */
    case TM_GET_RENDERING:  /* GetRenderingIntent */
    case TM_SET_RENDERING:  /* SetRenderingIntent renderType */
    {
        int renderIdx;
        RenderingIntent render;

	if( ((enum subIndex)index == TM_RENDERING) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?renderType?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_RENDERING) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_RENDERING) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "renderType");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set render
	     */
            if (Tcl_GetIndexFromObj(interp, objv[2], renderNames, "renderType", 0, &renderIdx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageRenderingIntent(wandPtr, renderTypes[renderIdx]);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get render
	     */
	    render = MagickGetImageRenderingIntent(wandPtr);
	    for (renderIdx = 0; renderIdx < sizeof(renderTypes)/sizeof(renderTypes[0]); renderIdx++) {
		if( renderTypes[renderIdx] == render ) {
		    Tcl_SetResult(interp, (char *)renderNames[renderIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)render));
	}
	break;
    }

    case TM_RESOLUTION:     /* resolution ?x? ?y? */
    case TM_GET_RESOLUTION: /* GetResolution */
    case TM_SET_RESOLUTION: /* SetResolution x ?y? */
    {
	double  x, y;

	if( ((enum subIndex)index == TM_RESOLUTION) && (objc > 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?x? ?y?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_RESOLUTION) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_RESOLUTION) && (objc != 3) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x ?y?");
	    return TCL_ERROR;
	}
	if (objc >= 3) {
	    /*
	     * Set resolution = x y, default: y=x
	     */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
		return stat;
	    }
            y = x;
	    if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK) ) {
		return stat;
	    }
	    result = MagickSetImageResolution(wandPtr, x, y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get resolution={x y}
	     */
	    Tcl_Obj *listPtr;

	    result = MagickGetImageResolution(wandPtr, &x, &y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	    listPtr = Tcl_NewListObj(0, NULL);
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(x));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(y));
	    Tcl_SetObjResult(interp, listPtr);
	}
	break;
    }

    case TM_SCENE:      /* scene ?num? */
    case TM_GET_SCENE:  /* GetScene */
    case TM_SET_SCENE:  /* SetScene num */
    {
        unsigned long num;

	if( (index == TM_SCENE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?num?");
	    return TCL_ERROR;
	}
	if( (index == TM_GET_SCENE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( (index == TM_SET_SCENE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "num");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set scene number
	     */
	    if (Tcl_GetLongFromObj(interp, objv[2], &num) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageScene(wandPtr, num);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get scene number
	     */
	    num = MagickGetImageScene(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewLongObj((long)num));
	}
	break;
    }

    case TM_SIGNATURE:     /* signature */
    case TM_GET_SIGNATURE: /* GetSignature */
    {
	char *signature;

	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	signature = (char *)MagickGetImageSignature(wandPtr);
	if(signature != NULL) {
	    Tcl_SetResult(interp, signature, TCL_VOLATILE);
	    MagickRelinquishMemory(signature); /* Free TclMagick resource */
	}
	break;
    }

    case TM_IMAGE_SIZE:      /* imagesize */
    case TM_GET_IMAGE_SIZE:  /* GetImageSize */
    {
	Tcl_WideInt size;

        if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
        /*
	 * Get image size={xSize ySize}
	 */
        size = MagickGetImageSize(wandPtr);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(size));

	break;
    }

    case TM_IMAGE_TYPE:      /* imagetype ?type? */
    case TM_GET_IMAGE_TYPE:  /* GetImageType */
    case TM_SET_IMAGE_TYPE:  /* SetImageType type */
    {
        int typeIdx;
        ImageType type;

	if( ((enum subIndex)index == TM_IMAGE_TYPE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?type?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_IMAGE_TYPE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_IMAGE_TYPE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "type");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set image type
	     */
            if (Tcl_GetIndexFromObj(interp, objv[2], typeNames,
				    "typeType", 0, &typeIdx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageType(wandPtr, typeTypes[typeIdx]);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get image type
	     */
	    type = MagickGetImageType(wandPtr);
	    for (typeIdx = 0; typeIdx < sizeof(typeTypes)/sizeof(typeTypes[0]); typeIdx++) {
		if( typeTypes[typeIdx] == type ) {
		    Tcl_SetResult(interp, (char *)typeNames[typeIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)type));
	}
	break;
    }

    case TM_IMAGE_UNITS:      /* imageunits ?unitType? */
    case TM_GET_IMAGE_UNITS:  /* GetImageUnits */
    case TM_SET_IMAGE_UNITS:  /* SetImageUnits unitType */
    {
        int unitIdx;
        ResolutionType unit;

	if( ((enum subIndex)index == TM_IMAGE_UNITS) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?unitType?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_IMAGE_UNITS) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_IMAGE_UNITS) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "unitType");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set image unit
	     */
            if (Tcl_GetIndexFromObj(interp, objv[2], unitNames, "unitType", 0, &unitIdx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageUnits(wandPtr, unitTypes[unitIdx]);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get image type
	     */
	    unit = MagickGetImageUnits(wandPtr);
	    for (unitIdx = 0; unitIdx < sizeof(unitTypes)/sizeof(unitTypes[0]); unitIdx++) {
		if( unitTypes[unitIdx] == unit ) {
		    Tcl_SetResult(interp, (char *)unitNames[unitIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)unit));
	}
	break;
    }

    case TM_VIRTUALPIXEL:      /* virtualpixelmethod ?methodType? */
    case TM_GET_VIRTUALPIXEL:  /* GetVirtualPixelMethod */
    case TM_SET_VIRTUALPIXEL:  /* SetVirtualPixelMethod methodType */
    {
        int methodIdx;
        ResolutionType method;

	if( ((enum subIndex)index == TM_IMAGE_UNITS) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?methodType?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_VIRTUALPIXEL) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_VIRTUALPIXEL) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "methodType");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set image method
	     */
            if (Tcl_GetIndexFromObj(interp, objv[2], methodNames, "methodType", 0, &methodIdx) != TCL_OK) {
	        return TCL_ERROR;
	    }
	    result = MagickSetImageUnits(wandPtr, methodTypes[methodIdx]);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get image type
	     */
	    method = MagickGetImageUnits(wandPtr);
	    for (methodIdx = 0; methodIdx < sizeof(methodTypes)/sizeof(methodTypes[0]); methodIdx++) {
		if( methodTypes[methodIdx] == method ) {
		    Tcl_SetResult(interp, (char *)methodNames[methodIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)method));
	}
	break;
    }

    case TM_WHITE_POINT:      /* whitepoint ?x y? */
    case TM_GET_WHITE_POINT:  /* GetWhitePoint */
    case TM_SET_WHITE_POINT:  /* SetWhitePoint x y */
    {
        double x, y;

	if( ((enum subIndex)index == TM_WHITE_POINT) && (objc != 2) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?x y?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_WHITE_POINT) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_WHITE_POINT) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    /*
	     * Set primary = x y
	     */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
		return stat;
	    }
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK ) {
		return stat;
	    }
	    result = MagickSetImageWhitePoint(wandPtr, x, y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get primary={x y}
	     */
	    Tcl_Obj *listPtr;

	    result = MagickGetImageWhitePoint(wandPtr, &x, &y);
	    if (!result) {
		return myMagickError(interp, wandPtr);
	    }
	    listPtr = Tcl_NewListObj(0, NULL);
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(x));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(y));
	    Tcl_SetObjResult(interp, listPtr);
	}
	break;
    }

    case TM_WIDTH:     /* width */
    case TM_GET_WIDTH: /* GetWidth */
    {
	int value;

        if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	value = MagickGetImageWidth(wandPtr);
        Tcl_SetObjResult(interp, Tcl_NewLongObj(value));

	break;
    }

    case TM_NUMBER:             /* number */
    case TM_GET_NUMBER_IMAGES:  /* GetNumberImages */
    {
        long num;

	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	num = MagickGetNumberImages(wandPtr);
	Tcl_SetObjResult(interp, Tcl_NewLongObj(num));
	break;
    }

    case TM_SAMPLING_FACTORS:      /* samplingfactors ?factorList? */
    case TM_GET_SAMPLING_FACTORS:  /* GetSamplingFactors */
    case TM_SET_SAMPLING_FACTORS:  /* GetSamplingFactors factorList */
    {
        double  *factors;

	if( ((enum subIndex)index == TM_SAMPLING_FACTORS) && (objc != 2) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?factorList?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_SAMPLING_FACTORS) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_SAMPLING_FACTORS) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "factorList");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    /*
	     * Set sampling factors
	     */
            Tcl_Obj **listPtr;
            int     i, listLen = 0;

	    if( (stat = Tcl_ListObjGetElements(interp, objv[2], &listLen, &listPtr)) != TCL_OK) {
	        return stat;
	    }
	    factors = (double *)ckalloc(listLen * sizeof(double));
            if( factors == NULL ) {
	        Tcl_AppendResult(interp, "TclMagick: out of memory", NULL);
	        return TCL_ERROR;
	    }
	    for( i=0; i < listLen; i++ ) {
	        if( (stat = Tcl_GetDoubleFromObj(interp, listPtr[i], &factors[i])) != TCL_OK) {
		    ckfree((char *)factors);
		    return stat;
	        }
	    }
	    result = MagickSetSamplingFactors(wandPtr, (unsigned long)listLen, factors);
	    if (!result) {
	        return myMagickError(interp, wandPtr);
	    }
	} else {
	    /*
	     * Get size={xSize ySize}
	     */
            Tcl_Obj *listPtr = NULL;
            unsigned long i, uLen;

	    factors = MagickGetSamplingFactors(wandPtr, &uLen);
	    if( (factors != NULL) && (uLen > 0) ) {
                listPtr = Tcl_NewListObj(0, NULL);
	        for( i=0; i < uLen; i++ ) {
                    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(factors[i]));
                }
    	        Tcl_SetObjResult(interp, listPtr);
            }
	    if (factors != NULL)
		MagickRelinquishMemory(factors); /* Free TclMagick resource */
	}
	break;
    }

    case TM_SIZE:      /* size ?x y? */
    case TM_GET_SIZE:  /* size */
    case TM_SET_SIZE:  /* size x y */
    {
	unsigned long x, y;

	if( ((enum subIndex)index == TM_SIZE) && (objc != 2) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?xSize ySize?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_SIZE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_SIZE) && (objc != 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "xSize ySize");
	    return TCL_ERROR;
	}
	if (objc == 4) {
	    /*
	     * Set size = x y
	     */

	    if( (stat = Tcl_GetLongFromObj(interp, objv[2], &x)) != TCL_OK ) {
		return stat;
	    }
	    if( (stat = Tcl_GetLongFromObj(interp, objv[3], &y)) != TCL_OK ) {
		return stat;
	    }
	    MagickSetSize(wandPtr, x, y);
	} else {
	    /*
	     * Get size={xSize ySize}
	     */
	    Tcl_Obj *listPtr = Tcl_NewListObj(0, NULL);

	    result = MagickGetSize(wandPtr, &x, &y);
	    if (!result) {
	        return myMagickError(interp, wandPtr);
	    }
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj((long)x));
	    Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj((long)y));
	    Tcl_SetObjResult(interp, listPtr);
	}
	break;
    }

    case TM_HASNEXT:
    case TM_HAS_NEXT_IMAGE:
    {
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 1, objv, "");
	    return TCL_ERROR;
	}
        result = MagickHasNextImage(wandPtr);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
	break;
    }

    case TM_HASPREVIOUS:
    case TM_HAS_PREVIOUS_IMAGE:
    {
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 1, objv, "");
	    return TCL_ERROR;
	}
        result = MagickHasPreviousImage(wandPtr);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
	break;
    }

    case TM_IMPLODE:       /* implode ?amount=0.0? */
    case TM_IMPLODE_IMAGE: /* ImplodeImage ?amount? */
    {
	double  amount=0.0;

	if( objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?amount=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &amount)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickImplodeImage(wandPtr, amount);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_LABEL:        /* label str */
    case TM_LABEL_IMAGE:  /* LabelImage str */
    {
	Tcl_DString extrep;
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "str");
	    return TCL_ERROR;
	}
	result = MagickLabelImage(wandPtr, 
	    Tcl_UtfToExternalDString(NULL, Tcl_GetString(objv[2]), -1, &extrep));

	Tcl_DStringFree(&extrep);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}

	break;
    }

    case TM_LEVEL:        /* level ?black=0.0? ?gamma=1.0? ?white=MaxRGB? */
    case TM_LEVEL_IMAGE:  /* LevelImage ?black? ?gamma=1.0? ?white=MaxRGB?  */
    {
	double  black=0.0, white=MaxRGB, gamma=1.0;

	if( objc > 5 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?black=0.0? ?gamma=1.0? ?white=MaxRGB? ");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &black)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &gamma)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetDoubleFromObj(interp, objv[4], &white)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickLevelImage(wandPtr, black, gamma, white);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_LEVEL_CHANNEL:        /* levelchannel channelType ?black=0.0? ?gamma=1.0? ?white=MaxRGB? */
    case TM_LEVEL_IMAGE_CHANNEL:  /* LevelImageChannel channelType ?black? ?gamma=1.0? ?white=MaxRGB?  */
    {
	int     chanIdx;
	double  black=0.0, white=MaxRGB, gamma=1.0;

	if( objc > 6 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channelType ?black=0.0? ?gamma=1.0? ?white=MaxRGB? ");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], chanNames, "channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &black)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetDoubleFromObj(interp, objv[4], &gamma)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 5) && ((stat = Tcl_GetDoubleFromObj(interp, objv[5], &white)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickLevelImageChannel(wandPtr, chanTypes[chanIdx], black, gamma, white);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_MAGNIFY:        /* magnify */
    case TM_MAGNIFY_IMAGE:  /* MagnifyImage */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickMagnifyImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}

	break;
    }

    case TM_MAP:        /* map mapName ?dither=false? */
    case TM_MAP_IMAGE:  /* MapImage mapName ?dither? */
    {
	MagickWand      *mapWand;
	char            *name;
	unsigned int    dither=0;

	if( objc > 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "mapName ?dither=no?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (mapWand = findMagickWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( (objc > 3) && ((stat = Tcl_GetBooleanFromObj(interp, objv[3], &dither)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickMapImage( wandPtr, mapWand, dither );
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}

	break;
    }

    case TM_MATTE_FLOODFILL:        /* mattefloodfill opacity ?fuzz=0.0? ?borderPix=none? ?x=0 y=0? */
    case TM_MATTE_FLOODFILL_IMAGE:  /* MatteFloodfillImage opacity ?fuzz? ?borderPix? ?x y? */
    {
	unsigned int	opacity;
	long x = 0, y = 0;
	double  fuzz = 0.0;
	char	*name;
	PixelWand	*borderPtr=NULL;

	if( (objc < 3) || (objc > 7) || (objc == 6) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "opacity ?fuzz=0.0? ?borderPix=none? ?x=0 y=0?");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetIntFromObj(interp, objv[2], &opacity)) != TCL_OK ) {
	    return stat;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &fuzz)) != TCL_OK) ) {
	    return stat;
	}
	if( objc > 4 ) {
	    name = Tcl_GetString(objv[4]);
	    if( (borderPtr = findPixelWand(interp, name)) == NULL ) {
		return TCL_ERROR;
	    }
	}
	if( (objc > 5) && ((stat = Tcl_GetLongFromObj(interp, objv[5], &x)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 6) && ((stat = Tcl_GetLongFromObj(interp, objv[6], &y)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickMatteFloodfillImage(wandPtr, (Quantum)(opacity), fuzz, borderPtr, x, y);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_MEDIANFILTER:       /* medianfilter ?radius? */
    case TM_MEDIANFILTER_IMAGE: /* MedianFilterImage ?radius? */
    {
	double  radius=0.0;

	if( objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickMedianFilterImage(wandPtr, radius);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_MINIFY:        /* minify */
    case TM_MINIFY_IMAGE:  /* MinifyImage */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickMinifyImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}

	break;
    }

    case TM_MODULATE:       /* modulate ?brightness=0.0? ?saturation=0.0? ?hue=0.0? */
    case TM_MODULATE_IMAGE: /* ModulateImage ?brightness? ?saturation? ?hue? */
    {
	double  brightness=0.0, saturation=0.0, hue=0.0;

	if( objc > 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?brightness=0.0? ?saturation=0.0? ?hue=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &brightness)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &saturation)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetDoubleFromObj(interp, objv[4], &hue)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickModulateImage(wandPtr, brightness, saturation, hue);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_MONTAGE:       /* montage draw tileGeom thumbGeom mode frameGeom ?newName? */
    case TM_MONTAGE_IMAGE: /* MontageImage draw tileGeom thumbGeom mode frameGeom ?newName? */
        {
	static CONST char *modeNames[] = {
	    "frame", "unframe", "concatenate",
	    (char *) NULL
	};
	static CompositeOperator modeTypes[] = {
	    FrameMode, UnframeMode, ConcatenateMode
	};
        char	    *name, *newName=NULL;
        DrawingWand *drawPtr;
	MagickWand  *newWand;
        int         modeIdx;
        char        *tileGeom, *thumbGeom, *frameGeom;

        if( (objc < 7) || (objc > 8) ) {
            Tcl_WrongNumArgs(interp, 2, objv, "draw tileGeom thumbGeom mode frameGeom ?newName?");
            return TCL_ERROR;
        }
        name = Tcl_GetString(objv[2]);
        if( (drawPtr = findDrawingWand(interp, name)) == NULL ) {
            return TCL_ERROR;
	}
        tileGeom  = Tcl_GetString(objv[3]);
        thumbGeom = Tcl_GetString(objv[4]);
	if (Tcl_GetIndexFromObj(interp, objv[5], modeNames, "mode", 0, &modeIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
        frameGeom = Tcl_GetString(objv[6]);
	if( objc > 7 ) {
	    newName = Tcl_GetString(objv[7]);
	}
	newWand = MagickMontageImage(wandPtr, drawPtr, tileGeom, thumbGeom,
				     modeTypes[modeIdx], frameGeom);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	newName = newWandObj(interp, newWand, newName);
	Tcl_SetResult(interp, newName, TCL_VOLATILE);

        break;
    }

    case TM_MORPH:         /* morph num ?newName? */
    case TM_MORPH_IMAGES:  /* MorphImages num ?newName? */
    {
	unsigned long num;
	MagickWand *newWand;
	char *name=NULL;

	if( (objc < 3) || (objc > 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "num ?newName?");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &num)) != TCL_OK ) {
	    return stat;
	}
	if( objc > 3 ) {
	    name = Tcl_GetString(objv[3]);
	}
	newWand = MagickMorphImages(wandPtr, num);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_MOSAIC:         /* mosaic ?newName? */
    case TM_MOSAIC_IMAGES:  /* MosaicImages ?newName? */
    {
	MagickWand *newWand;
	char *name=NULL;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?newName?");
	    return TCL_ERROR;
	}
	if( objc > 2 ) {
	    name = Tcl_GetString(objv[2]);
	}
	newWand = MagickMosaicImages(wandPtr);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_MOTIONBLUR:       /* motionblur ?radius=0.0? ?sigma=0.0? ?angle=0.0? */
    case TM_MOTIONBLUR_IMAGE: /* MotionBlurImage ?radius? ?sigma? ?angle? */
    {
	double  radius=0.0, sigma=0.0, angle=0.0;

	if( objc > 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0? ?sigma=0.0? ?angle=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &sigma)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetDoubleFromObj(interp, objv[4], &angle)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickMotionBlurImage(wandPtr, radius, sigma, angle);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_NEGATE:       /* negate ?gray=false? */
    case TM_NEGATE_IMAGE: /* NegateImage ?gray=false? */
    {
	unsigned int gray=0;

	if (objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?gray=no?");
	    return TCL_ERROR;
	}
        if( (objc > 2) && ((stat = Tcl_GetBooleanFromObj(interp, objv[2], &gray)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickNegateImage(wandPtr, gray);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_NEGATE_CHANNEL:       /* negatechannel channelType ?gray=false? */
    case TM_NEGATE_IMAGE_CHANNEL: /* NegateImageChannel channelType ?gray=false? */
    {
	unsigned int gray=0;
        int chanIdx;

	if( (objc < 3) || (objc > 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channelType ?gray=no?");
	    return TCL_ERROR;
        }
	if (Tcl_GetIndexFromObj(interp, objv[2], chanNames, "channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
        if( (objc > 3) && ((stat = Tcl_GetBooleanFromObj(interp, objv[3], &gray)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickNegateImageChannel(wandPtr, chanTypes[chanIdx], gray);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_NEXT:          /* next ?offset=1? */
    case TM_NEXT_IMAGE:    /* NextImage ?offset=1? */
    {
	int i, ofs=1;

	if (objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?offset=1?");
	    return TCL_ERROR;
	} else if (objc == 3) {
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &ofs)) != TCL_OK ) {
		return stat;
	    }
	}
	for( i=0; i<ofs; i++) {
	    result = MagickNextImage(wandPtr);
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
	break;
    }

    case TM_NORMALIZE:       /* normalize */
    case TM_NORMALIZE_IMAGE: /* NormalizeImage */
    {
	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickNormalizeImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_OILPAINT:       /* oilpaint ?radius? */
    case TM_OILPAINT_IMAGE: /* OilPaintImage ?radius? */
    {
	double  radius=0.0;

	if( objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickOilPaintImage(wandPtr, radius);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_OPAQUE:        /* opaque targetPix fillPix ?fuzz=0.0? */
    case TM_OPAQUE_IMAGE:  /* OpaqueImage targetPix fillPix ?fuzz=0.0? */
    {
	double    fuzz=0.0;
	char      *name;
	PixelWand *targetPtr, *fillPtr;

	if( (objc < 4) || (objc > 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "targetPix fillPix ?fuzz=0.0?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (targetPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[3]);
	if( (fillPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( (objc > 4) && ((stat = Tcl_GetDoubleFromObj(interp, objv[4], &fuzz)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickOpaqueImage(wandPtr, targetPtr, fillPtr, fuzz);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_PING:          /* ping filename */
    case TM_PING_IMAGE:    /* PingImage filename */
    {
	char *filename;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "filename");
	    return TCL_ERROR;
	}
	filename = Tcl_GetString(objv[2]);
	result = MagickPingImage(wandPtr, filename);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_PREVIEW:         /* preview previewType ?newName? */
    case TM_PREVIEW_IMAGES:  /* PreviewImages previewType ?newName? */
    {
	int previewIdx;
	MagickWand *newWand;
	char *name=NULL;

	if( (objc < 3) || (objc > 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "previewType ?newName?");
	    return TCL_ERROR;
	}
        if (Tcl_GetIndexFromObj(interp, objv[2], previewNames, "previewType", 0, &previewIdx) != TCL_OK) {
            return TCL_ERROR;
	}
	if( objc > 3 ) {
	    name = Tcl_GetString(objv[3]);
	}
	newWand = MagickPreviewImages(wandPtr, previewTypes[previewIdx]);
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	name = newWandObj(interp, newWand, name);
	Tcl_SetResult(interp, name, TCL_VOLATILE);

	break;
    }

    case TM_PREVIOUS:          /* previous ?offset=1? */
    case TM_PREVIOUS_IMAGE:    /* PreviousImage ?offset=1? */
    {
	int i, ofs=1;

	if (objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?offset?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetIntFromObj(interp, objv[2], &ofs)) != TCL_OK) ) {
	    return stat;
	}
	for( i=0; i<ofs; i++) {
	    result = MagickPreviousImage(wandPtr);
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
	break;
    }

    case TM_QUANTIZE:        /* quantize numColors ?colorspaceType? ?treedepth? ?dither? ?measureError? */
    case TM_QUANTIZE_IMAGE:  /* QuantizeImage numColors ?colorspaceType? ?treedepth? ?dither? ?measureError? */
    case TM_QUANTIZE_IMAGES: /* QuantizeImage numColors ?colorspaceType? ?treedepth? ?dither? ?measureError? */
    {
	unsigned long numColors, treeDepth=0;
	unsigned int dither=0, measureError=0;
	int csIdx=RGBColorspace;

	if( (objc < 3) || (objc > 7) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "numColors ?colorspaceType=RGB? ?treedepth=0? ?dither=no? ?measureError=no?");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &numColors)) != TCL_OK ) {
	    return stat;
	}
	if( (objc > 3) && (Tcl_GetIndexFromObj(interp, objv[3], csNames, "colorspaceType", 0, &csIdx) != TCL_OK) ) {
	    return TCL_ERROR;
	}
	if( (objc > 4) && ((stat = Tcl_GetLongFromObj(interp, objv[4], &treeDepth)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 5) && ((stat = Tcl_GetBooleanFromObj(interp, objv[5], &dither)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 6) && ((stat = Tcl_GetBooleanFromObj(interp, objv[6], &measureError)) != TCL_OK) ) {
	    return stat;
	}
	if( (enum subIndex)index == TM_QUANTIZE_IMAGES ) {
	    result = MagickQuantizeImages(wandPtr, numColors, csTypes[csIdx], treeDepth, dither, measureError);
	} else {
	    result = MagickQuantizeImage(wandPtr, numColors, csTypes[csIdx], treeDepth, dither, measureError);
	}
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_QUERYFONTMETRICS:     /* queryfontmetrics draw text */
    case TM_QUERY_FONT_METRICS:   /* QueryFontMetrics draw text */
    {
        double  *metrics;
        int     i;
        Tcl_Obj *listPtr;
        char    *name, *text;
	DrawingWand *drawPtr;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "draw text");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (drawPtr = findDrawingWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	text = Tcl_GetString(objv[3]);

	metrics = MagickQueryFontMetrics(wandPtr, drawPtr, text);
	if( (metrics != NULL) ) {
            listPtr = Tcl_NewListObj(0, NULL);
	    for( i=0; i < 7; i++ ) {
                Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(metrics[i]));
            }
    	    Tcl_SetObjResult(interp, listPtr);
        }
	if (metrics != NULL)
	    MagickRelinquishMemory(metrics); /* Free TclMagick resource */

        break;
    }

    case TM_RAISE:        /* raise width height ?x y? ?raise? */
    case TM_RAISE_IMAGE:  /* RaiseImage width height ?x y? ?raise? */
    {
	unsigned long width, height;
	long x=0, y=0;
	unsigned int raise=0;

	if( (objc < 4) || (objc > 7) || (objc == 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "width height ?x y? ?raise=no?");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &width)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[3], &height)) != TCL_OK ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetLongFromObj(interp, objv[4], &x)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 5) && ((stat = Tcl_GetLongFromObj(interp, objv[5], &y)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 6) && ((stat = Tcl_GetBooleanFromObj(interp, objv[6], &raise)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickRaiseImage(wandPtr, width, height, x, y, raise);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_READ:          /* read filename */
    case TM_READ_IMAGE:    /* ReadImage filename */
    {
	char *filename;
	Tcl_DString extrep;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "filename");
	    return TCL_ERROR;
	}
	filename = Tcl_UtfToExternalDString(NULL, Tcl_GetString(objv[2]), -1, &extrep);
	result = MagickReadImage(wandPtr, filename);
	Tcl_DStringFree(&extrep);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_READ_BLOB:          /* readblob data */
    case TM_READ_IMAGE_BLOB:    /* ReadImageBlob data */
    {
	unsigned char *data;
        int length;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data");
	    return TCL_ERROR;
	}
	data = Tcl_GetByteArrayFromObj(objv[2], &length);
	result = MagickReadImageBlob(wandPtr, data, (size_t)length);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_REDUCENOISE:       /* reducenoise ?radius? */
    case TM_REDUCENOISE_IMAGE: /* ReduceNoiseImage ?radius? */
    {
	double  radius=0.0;

	if( objc > 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickReduceNoiseImage(wandPtr, radius);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_REMOVE:        /* remove */
    case TM_REMOVE_IMAGE:  /* RemoveImage */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickRemoveImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_RESETITERATOR:   /* resetiterator */
    case TM_RESET_ITERATOR:  /* ResetIterator */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	MagickResetIterator(wandPtr);
	break;
    }

    case TM_RESAMPLE:        /* resample xRes ?yRes? ?filter? ?blur=1.0? */
    case TM_RESAMPLE_IMAGE:  /* ResampleImage xRes ?yRes? ?filter? ?blur=1.0? */
    {
	int     filterIdx=0;
	double  xRes, yRes, blur=1.0;

	if( (objc < 3) || (objc > 6) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "xRes ?yRes=xRes? ?filterType=undefined? ?blur=1.0?");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &xRes)) != TCL_OK ) {
	    return stat;
	}
	yRes = xRes; /* default */
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &yRes)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 4) && (Tcl_GetIndexFromObj(interp, objv[4], filterNames, "filterType",
					       0, &filterIdx) != TCL_OK) ) {
	    return TCL_ERROR;
	}
	if( (objc > 5) && ((stat = Tcl_GetDoubleFromObj(interp, objv[5], &blur)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickResampleImage(wandPtr, xRes, yRes, filterTypes[filterIdx], blur);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_RESIZE:        /* resize x y ?filter? ?blur=1.0? */
    case TM_RESIZE_IMAGE:  /* ResizeImage x y ?filter? ?blur=1.0? */
    {
	int     filterIdx=0;
	unsigned long x, y;
	double  blur=1.0;

	if( (objc < 4) || (objc > 6) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y ?filterType=undefined? ?blur=1.0?");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[3], &y)) != TCL_OK ) {
	    return stat;
	}
	if( (objc > 4) && (Tcl_GetIndexFromObj(interp, objv[4], filterNames, "filterType", 0, &filterIdx) != TCL_OK) ) {
	    return TCL_ERROR;
	}
	if( (objc > 5) && ((stat = Tcl_GetDoubleFromObj(interp, objv[5], &blur)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickResizeImage(wandPtr, x, y, filterTypes[filterIdx], blur);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_ROLL:       /* roll xOfs yOfs */
    case TM_ROLL_IMAGE: /* RollImage xOfs yOfs */
    {
	int  xOfs, yOfs;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "xOfs yOfs");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetIntFromObj(interp, objv[2], &xOfs)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetIntFromObj(interp, objv[3], &yOfs)) != TCL_OK ) {
	    return stat;
	}
	result = MagickRollImage(wandPtr, xOfs, yOfs);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_ROTATE:        /* rotate background degrees */
    case TM_ROTATE_IMAGE:  /* RotateImage background degrees */
    {
	double    degrees;
	PixelWand *bgPtr;
	char      *name;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "background degrees");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (bgPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &degrees)) != TCL_OK ) {
	    return stat;
	}
	result = MagickRotateImage(wandPtr, bgPtr, degrees);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SAMPLE:       /* sample x y */
    case TM_SAMPLE_IMAGE: /* SampleImage x y */
    {
	unsigned long  x, y;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[3], &y)) != TCL_OK ) {
	    return stat;
	}
	result = MagickSampleImage(wandPtr, x, y);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SCALE:       /* scale x y */
    case TM_SCALE_IMAGE: /* ScaleImage x y */
    {
	unsigned long  x, y;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[3], &y)) != TCL_OK ) {
	    return stat;
	}
	result = MagickScaleImage(wandPtr, x, y);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SEPARATE:         /* separate channelType */
    case TM_SEPARATE_CHANNEL: /* SeparateImageChannel channelType */
    {
	int chanIdx;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channelType");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], chanNames, "channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	result = MagickSeparateImageChannel(wandPtr, chanTypes[chanIdx]);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SETIMAGE:  /* setimage name */
    case TM_SET_IMAGE: /* SetImage name */
    {
	char *name = NULL;
	MagickWand *setWand;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "setwand");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (setWand = findMagickWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	result = MagickSetImage(wandPtr, setWand);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SETOPTION:  /* setoption format key value */
    case TM_SET_OPTION: /* SetOption format key value */
    {
	char *format, *key, *value;

	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "format key value");
	    return TCL_ERROR;
	}
	format  = Tcl_GetString(objv[2]);
	key = Tcl_GetString(objv[3]);
	value = Tcl_GetString(objv[4]);
	result = MagickSetImageOption(wandPtr, format, key, value);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_PASSPHRASE:     /* passphrase phrase */
    case TM_SET_PASSPHRASE: /* SetPassphrase phrase */
    {
	char *phrase;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "phrase");
	    return TCL_ERROR;
	}
	phrase  = Tcl_GetString(objv[2]);
	result = MagickSetPassphrase(wandPtr, phrase);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SHARPEN:       /* sharpen ?radius? ?sigma? */
    case TM_SHARPEN_IMAGE: /* SharpenImage ?radius? ?sigma? */
    {
	double  radius=0.0, sigma=1.0;

	if( objc > 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0? ?sigma=1.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &sigma)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickSharpenImage(wandPtr, radius, sigma);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SHAVE:       /* shave x y */
    case TM_SHAVE_IMAGE: /* ShaveImage x y */
    {
	unsigned long x, y;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[3], &y)) != TCL_OK ) {
	    return stat;
	}
	result = MagickShaveImage(wandPtr, x, y);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SHEAR:        /* shear background xShear ?yShear? */
    case TM_SHEAR_IMAGE:  /* ShearImage background xShear ?yShear? */
    {
	double    xShear, yShear;
	PixelWand *bgPtr;
	char      *name;

	if( (objc < 4) || (objc > 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "background xShear ?yShear=xShear?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (bgPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &xShear)) != TCL_OK ) {
	    return stat;
	}
	yShear = xShear; /* default */
	if( (objc > 4) && ((stat = Tcl_GetDoubleFromObj(interp, objv[4], &yShear)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickShearImage(wandPtr, bgPtr, xShear, yShear);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SOLARIZE:        /* solarize ?threshold? */
    case TM_SOLARIZE_IMAGE:  /* SolarizeImage ?threshold? */
    {
	double    threshold=0.0;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?threshold=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &threshold)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickSolarizeImage(wandPtr, threshold);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SPREAD:       /* spread ?radius? */
    case TM_SPREAD_IMAGE: /* SpreadImage ?radius? */
    {
	double  radius=0.0;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickSpreadImage(wandPtr, radius);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_STEGANO:       /* stegano watermark ?offset=0? ?newName? */
    case TM_STEGANO_IMAGE: /* SteganoImage watermark ?offset=0? ?newName? */
    {
	MagickWand      *watermarkPtr, *newWand;
	char            *name, *newName=NULL;
	int             offset=0;

	if( objc > 5 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "watermark ?offset=0?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (watermarkPtr = findMagickWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( (objc > 3) && ((stat = Tcl_GetIntFromObj(interp, objv[3], &offset)) != TCL_OK) ) {
	    return stat;
	}
	if( objc > 4 ) {
	    newName = Tcl_GetString(objv[4]);
	}
	newWand = MagickSteganoImage( wandPtr, watermarkPtr, offset );
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	newName = newWandObj(interp, newWand, newName);
	Tcl_SetResult(interp, newName, TCL_VOLATILE);

	break;
    }

    case TM_STEREO:       /* stereo anotherWand ?newName? */
    case TM_STEREO_IMAGE: /* StereoImage anotherwand ?newName? */
    {
	MagickWand      *anotherPtr, *newWand;
	char            *name, *newName=NULL;

	if( objc > 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "anotherWand ?newName?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (anotherPtr = findMagickWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( objc > 3 ) {
	    newName = Tcl_GetString(objv[3]);
	}
	newWand = MagickStereoImage( wandPtr, anotherPtr );
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	newName = newWandObj(interp, newWand, newName);
	Tcl_SetResult(interp, newName, TCL_VOLATILE);

	break;
    }

    case TM_STRIP:       /* strip */
    case TM_STRIP_IMAGE: /* StripImage */
    {
	if( objc > 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	result = MagickStripImage(wandPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_SWIRL:       /* swirl ?degrees? */
    case TM_SWIRL_IMAGE: /* SwirlImage ?degrees? */
    {
	double  degrees=0.0;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?degrees=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &degrees)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickSwirlImage(wandPtr, degrees);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_TEXTURE:       /* texture textWand ?newName? */
    case TM_TEXTURE_IMAGE: /* TextureImage textWand ?newName? */
    {
	MagickWand      *textPtr, *newWand;
	char            *name, *newName=NULL;

	if( objc > 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "textWand ?newName?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (textPtr = findMagickWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( objc > 3 ) {
	    newName = Tcl_GetString(objv[3]);
	}
	newWand = MagickTextureImage( wandPtr, textPtr );
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	newName = newWandObj(interp, newWand, newName);
	Tcl_SetResult(interp, newName, TCL_VOLATILE);

	break;
    }

    case TM_THRESHOLD:        /* threshold threshold */
    case TM_THRESHOLD_IMAGE:  /* ThresholdImage threshold */
    {
	double    threshold=0.0;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "threshold");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &threshold)) != TCL_OK ) {
	    return stat;
	}
	result = MagickThresholdImage(wandPtr, threshold);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_THRESHOLDCHANNEL:         /* thresholdchannel channelType threshold */
    case TM_THRESHOLD_IMAGE_CHANNEL:  /* ThresholdImageChannel channelType threshold */
    {
        int    chanIdx;
	double threshold=0.0;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "channelType threshold");
	    return TCL_ERROR;
	}
	if (Tcl_GetIndexFromObj(interp, objv[2], chanNames, "channelType", 0, &chanIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &threshold)) != TCL_OK ) {
	    return stat;
	}
	result = MagickThresholdImageChannel(wandPtr, chanTypes[chanIdx], threshold);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_TINT:        /* tint tintPixel opacityPixel */
    case TM_TINT_IMAGE:  /* TintImage tintPixel opacityPixel */
    {
	char	  *name;
	PixelWand *tintPtr, *opacityPtr;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "tintPixel opacityPixel");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (tintPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[3]);
	if( (opacityPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}

	result = MagickTintImage(wandPtr, tintPtr, opacityPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_TRANSFORM:       /* transform crop geometry ?newName? */
    case TM_TRANSFORM_IMAGE: /* TransformImage crop geometry ?newName? */
    {
	MagickWand      *newWand;
	char            *crop, *geometry, *newName=NULL;

	if( (objc < 4) || (objc > 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "crop geometry ?newName?");
	    return TCL_ERROR;
	}
	crop = Tcl_GetString(objv[2]);
	geometry = Tcl_GetString(objv[3]);
	if( objc > 4 ) {
	    newName = Tcl_GetString(objv[4]);
	}
	newWand = MagickTransformImage( wandPtr, crop, geometry );
	if (newWand == NULL) {
	    return myMagickError(interp, wandPtr);
	}
	newName = newWandObj(interp, newWand, newName);
	Tcl_SetResult(interp, newName, TCL_VOLATILE);

	break;
    }

    case TM_TRANSPARENT:        /* transparent targetPix ?opacity? ?fuzz=0.0? */
    case TM_TRANSPARENT_IMAGE:  /* TransparentImage targetPix ?opacity? ?fuzz=0.0? */
    {
	double    fuzz=0.0;
	unsigned  opacity=0;
	char      *name;
	PixelWand *targetPtr;

	if( (objc < 3) || (objc > 5) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "targetPix ?opacity=0? ?fuzz=0.0?");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (targetPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}
	if( (objc > 3) && ((stat = Tcl_GetIntFromObj(interp, objv[3], &opacity)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetDoubleFromObj(interp, objv[4], &fuzz)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickTransparentImage(wandPtr, targetPtr, (const Quantum)opacity, fuzz);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_TRIM:        /* trim ?fuzz=0.0? */
    case TM_TRIM_IMAGE:  /* TrimImage ?fuzz=0.0? */
    {
	double    fuzz=0.0;

	if( objc > 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?fuzz=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &fuzz)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickTrimImage(wandPtr, fuzz);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_UNSHARPMASK:        /* unsharpmask ?radius? ?sigma? ?amount? ?threshold? */
    case TM_UNSHARPMASK_IMAGE:  /* UnsharpMaskImage ?radius? ?sigma? ?amount? ?threshold? */
    {
	double radius=0.0, sigma=1.0, amount=0.0, threshold=0.0;

	if( objc > 6 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?radius=0.0? ?sigma=1.0? ?amount=0.0? ?threshold=0.0?");
	    return TCL_ERROR;
	}
	if( (objc > 2) && ((stat = Tcl_GetDoubleFromObj(interp, objv[2], &radius)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &sigma)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 4) && ((stat = Tcl_GetDoubleFromObj(interp, objv[4], &amount)) != TCL_OK) ) {
	    return stat;
	}
	if( (objc > 5) && ((stat = Tcl_GetDoubleFromObj(interp, objv[5], &threshold)) != TCL_OK) ) {
	    return stat;
	}
	result = MagickUnsharpMaskImage(wandPtr, radius, sigma, amount, threshold);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_WAVE:        /* wave amplitude wavelength */
    case TM_WAVE_IMAGE:  /* WaveImage amplitude wavelength */
    {
	double amplitude, wavelength;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "amplitude wavelength");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &amplitude)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &wavelength)) != TCL_OK ) {
	    return stat;
	}
	result = MagickWaveImage(wandPtr, amplitude, wavelength);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_WHITE_THRESHOLD:        /* whitethreshold thresholdPixel */
    case TM_WHITE_THRESHOLD_IMAGE:  /* WhiteThresholdImage thresholdPixel */
    {
	char	*name;
	PixelWand	*threshPtr;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "thresholdPixel");
	    return TCL_ERROR;
	}
	name = Tcl_GetString(objv[2]);
	if( (threshPtr = findPixelWand(interp, name)) == NULL ) {
	    return TCL_ERROR;
	}

	result = MagickWhiteThresholdImage(wandPtr, threshPtr);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_WRITE:         /* write filename */
    case TM_WRITE_IMAGE:   /* WriteImage filename */
    case TM_WRITE_IMAGES:  /* WriteImages filename ?adjoin? */
    {
	char *filename;
	unsigned int  adjoin=0;
	Tcl_DString extrep;

	if( ((enum subIndex)index == TM_WRITE_IMAGES) && ((objc < 3) || (objc > 4)) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "filename ?adjoin=no?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index != TM_WRITE_IMAGES) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "filename");
	    return TCL_ERROR;
	}
	filename = Tcl_UtfToExternalDString(NULL, Tcl_GetString(objv[2]), -1, &extrep);
	if( (objc > 3) && ((stat = Tcl_GetBooleanFromObj(interp, objv[3], &adjoin)) != TCL_OK) ) {
	    return stat;
	}
	if( (enum subIndex) index == TM_WRITE_IMAGES ) {
	    result = MagickWriteImages(wandPtr, filename, adjoin);
	} else {
	    result = MagickWriteImage(wandPtr, filename);
	}
	Tcl_DStringFree(&extrep);
	if (!result) {
	    return myMagickError(interp, wandPtr);
	}
	break;
    }

    case TM_WRITE_BLOB:         /* writeblob */
    case TM_WRITE_IMAGE_BLOB:   /* WriteImageBlob */
    {
	unsigned char *data;
        int  length;

	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
        data = (char *)MagickWriteImageBlob(wandPtr, &length);
        if(data != NULL) {
            Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(data, length));
            MagickRelinquishMemory(data); /* Free TclMagick resource */
	}
	break;
    }

    /*
     * All subcommands should be matched
     * A DEFAULT or TM_END_OF_TABLE would be a serious fault
     */
    case TM_END_OF_TABLE:
    default:
    {
	Tcl_AppendResult(interp, "TclMagick wandObjCmd: Unmatched subcommand table entry", NULL);
	return TCL_ERROR;
    }

    } /* switch(index) */

    return(TCL_OK);
}



/*----------------------------------------------------------------------
 * PixelWand object command
 *----------------------------------------------------------------------
 *
 * PixelWand subcmd ?args?
 *
 *----------------------------------------------------------------------
 */
static int pixelObjCmd(
    ClientData  clientData,         /* PixelWand pointer */
    Tcl_Interp  *interp,            /* Interpreter containing image */
    int         objc,               /* Number of arguments */
    Tcl_Obj     *CONST objv[] )     /* List of arguments */
{
    static CONST char *subCmds[] = {
        "set",             "get",             "color",
        "SetBlack",        "GetBlack",        "SetBlackQuantum",   "GetBlackQuantum",
        "SetBlue",         "GetBlue",         "SetBlueQuantum",    "GetBlueQuantum",
        "SetCyan",         "GetCyan",         "SetCyanQuantum",    "GetCyanQuantum",
        "SetGreen",        "GetGreen",        "SetGreenQuantum",   "GetGreenQuantum",
        "SetMagenta",      "GetMagenta",      "SetMagentaQuantum", "GetMagentaQuantum",
        "SetOpacity",      "GetOpacity",      "SetOpacityQuantum", "GetOpacityQuantum",
        "SetRed",          "GetRed",          "SetRedQuantum",     "GetRedQuantum",
        "SetYellow",       "GetYellow",       "SetYellowQuantum",  "GetYellowQuantum",
        "SetColor",        "GetColor",        "GetColorAsString",
        "SetQuantumColor", "GetQuantumColor", "quantumcolor",
        (char *) NULL
    };
    enum subIndex {
        TM_SET,         TM_GET,         TM_COLOR,
        TM_SET_BLACK,   TM_GET_BLACK,   TM_SET_BLACK_QUANTUM,   TM_GET_BLACK_QUANTUM,
        TM_SET_BLUE,    TM_GET_BLUE,    TM_SET_BLUE_QUANTUM,    TM_GET_BLUE_QUANTUM,
        TM_SET_CYAN,    TM_GET_CYAN,    TM_SET_CYAN_QUANTUM,    TM_GET_CYAN_QUANTUM,
        TM_SET_GREEN,   TM_GET_GREEN,   TM_SET_GREEN_QUANTUM,   TM_GET_GREEN_QUANTUM,
        TM_SET_MAGENTA, TM_GET_MAGENTA, TM_SET_MAGENTA_QUANTUM, TM_GET_MAGENTA_QUANTUM,
        TM_SET_OPACITY, TM_GET_OPACITY, TM_SET_OPACITY_QUANTUM, TM_GET_OPACITY_QUANTUM,
        TM_SET_RED,     TM_GET_RED,     TM_SET_RED_QUANTUM,     TM_GET_RED_QUANTUM,
        TM_SET_YELLOW,  TM_GET_YELLOW,  TM_SET_YELLOW_QUANTUM,  TM_GET_YELLOW_QUANTUM,
        TM_SET_COLOR,   TM_GET_COLOR,   TM_GET_COLOR_AS_STRING,
        TM_SET_QUANTUM, TM_GET_QUANTUM, TM_QUANTUM,
        TM_END_OF_TABLE
    };
    static CONST char  *colors[]  = {
        "black",   "blue",    "cyan", "green",
        "magenta", "opacity", "red",  "yellow",
        (char *) NULL };

    int          index, stat, result, quantFlag=0;
    int          quantVal;
    double       normVal;
    TclMagickObj *magickPtr = (TclMagickObj *) clientData;
    PixelWand    *wandPtr   = (PixelWand *) magickPtr->wandPtr;

#ifdef MAGICK_DEBUG
    /*
     * Verify subCmds table size
     * No idea how to do this at compile-time
     */
    if( sizeof(subCmds)/sizeof(subCmds[0]) != TM_END_OF_TABLE + 1 ) {
        Tcl_Panic("pixelObjCmd: Invalid subCmds[] table");
    }
#endif

    if( objc < 2 ) {
        Tcl_WrongNumArgs( interp, 1, objv, "subcmd ?args?" );
        return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subCmds, "subcmd", 0, &index) != TCL_OK) {
        return TCL_ERROR;
    }

    switch ((enum subIndex)index) {

    case TM_SET:    /* set ?-quant*um? color val color val ... */
    {
	int     color;

	if( objc < 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-quant*? color value color value ...");
	    return TCL_ERROR;
	}
	if( strncmp(Tcl_GetString(objv[2]), "-quant", 6) == 0 ) {
	    quantFlag = 1;
	    objv += 3, objc -= 3;
	} else {
	    quantFlag = 0;
	    objv += 2, objc -= 2;
	}
	while( objc > 0 ) {
	    if (Tcl_GetIndexFromObj(interp, objv[0], colors, "color", 0, &color) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if( objc == 1 ) {
		Tcl_AppendResult(interp, "Magick: Missing value for color ", objv[0], NULL);
		return TCL_ERROR;
	    }
	    if( quantFlag ) {
		if( (stat = Tcl_GetIntFromObj(interp, objv[1], &quantVal)) != TCL_OK ) {
		    return stat;
		}
		switch(color) {
		case 0:  PixelSetBlackQuantum(wandPtr,    (Quantum)quantVal); break;
		case 1:  PixelSetBlueQuantum(wandPtr,     (Quantum)quantVal); break;
		case 2:  PixelSetCyanQuantum(wandPtr,     (Quantum)quantVal); break;
		case 3:  PixelSetGreenQuantum(wandPtr,    (Quantum)quantVal); break;
		case 4:  PixelSetMagentaQuantum(wandPtr,  (Quantum)quantVal); break;
		case 5:  PixelSetOpacityQuantum(wandPtr,  (Quantum)quantVal); break;
		case 6:  PixelSetRedQuantum(wandPtr,      (Quantum)quantVal); break;
		case 7:  PixelSetYellowQuantum(wandPtr,   (Quantum)quantVal); break;
		}
	    } else {
		if( (stat = Tcl_GetDoubleFromObj(interp, objv[1], &normVal)) != TCL_OK ) {
		    return stat;
		}
		switch(color) {
		case 0:  PixelSetBlack(wandPtr,    normVal); break;
		case 1:  PixelSetBlue(wandPtr,     normVal); break;
		case 2:  PixelSetCyan(wandPtr,     normVal); break;
		case 3:  PixelSetGreen(wandPtr,    normVal); break;
		case 4:  PixelSetMagenta(wandPtr,  normVal); break;
		case 5:  PixelSetOpacity(wandPtr,  normVal); break;
		case 6:  PixelSetRed(wandPtr,      normVal); break;
		case 7:  PixelSetYellow(wandPtr,   normVal); break;
		}
	    }
	    objv += 2, objc -= 2;
	}
	break;
    }

    case TM_GET:    /* get -quantum color color ... */
    {
	Tcl_Obj *listPtr;
	int     color;

	if( objc < 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?-quant*? color color ...");
	    return TCL_ERROR;
	}
	if( strncmp(Tcl_GetString(objv[2]), "-quant", 6) == 0 ) {
	    quantFlag = 1;
	    objv += 3, objc -= 3;
	} else {
	    quantFlag = 0;
	    objv += 2, objc -= 2;
	}
	listPtr = Tcl_NewListObj(0, NULL);
	while( objc > 0 ) {
	    if (Tcl_GetIndexFromObj(interp, objv[0], colors, "color", 0, &color) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if( quantFlag ) {
		switch(color) {
		case 0:  quantVal = PixelGetBlackQuantum(wandPtr);    break;
		case 1:  quantVal = PixelGetBlueQuantum(wandPtr);     break;
		case 2:  quantVal = PixelGetCyanQuantum(wandPtr);     break;
		case 3:  quantVal = PixelGetGreenQuantum(wandPtr);    break;
		case 4:  quantVal = PixelGetMagentaQuantum(wandPtr);  break;
		case 5:  quantVal = PixelGetOpacityQuantum(wandPtr);  break;
		case 6:  quantVal = PixelGetRedQuantum(wandPtr);      break;
		case 7:  quantVal = PixelGetYellowQuantum(wandPtr);   break;
		}
		Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewIntObj(quantVal));
	    } else {
		switch(color) {
		case 0:  normVal = PixelGetBlack(wandPtr);    break;
		case 1:  normVal = PixelGetBlue(wandPtr);     break;
		case 2:  normVal = PixelGetCyan(wandPtr);     break;
		case 3:  normVal = PixelGetGreen(wandPtr);    break;
		case 4:  normVal = PixelGetMagenta(wandPtr);  break;
		case 5:  normVal = PixelGetOpacity(wandPtr);  break;
		case 6:  normVal = PixelGetRed(wandPtr);      break;
		case 7:  normVal = PixelGetYellow(wandPtr);   break;
		}
		Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(normVal));
	    }
	    objv += 1, objc -= 1;
	}
	Tcl_SetObjResult(interp, listPtr);

	break;
    }

    case TM_COLOR:                  /* color ?string? */
    case TM_SET_COLOR:              /* SetColor string */
    case TM_GET_COLOR:              /* GetColor */
    case TM_GET_COLOR_AS_STRING:    /* GetColorAsString */
    {
	char *color;

	if( ((enum subIndex)index == TM_COLOR) && (objc != 2) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?string?");
	    return TCL_ERROR;
	} else if ( ((enum subIndex)index == TM_SET_COLOR) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string");
	    return TCL_ERROR;
	} else if ( ((enum subIndex)index == TM_GET_COLOR) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if ( ((enum subIndex)index == TM_GET_COLOR_AS_STRING) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( objc == 3 ) {   /* Set color */
	    color = Tcl_GetString(objv[2]);
	    result = PixelSetColor(wandPtr, color);
	    if( !result ) {
		Tcl_AppendResult(interp, "Magick: Invalid color ", color, NULL);
		return TCL_ERROR;
	    }
	} else {
	    color = PixelGetColorAsString(wandPtr);
	    Tcl_SetResult(interp, color, TCL_VOLATILE);
	    MagickRelinquishMemory(color); /* Free TclMagick resource */
	}

	break;
    }

    case TM_SET_BLACK_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_SET_BLACK:
    {
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &quantVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetBlackQuantum(wandPtr, (Quantum)quantVal);
	} else {
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &normVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetBlack(wandPtr, normVal);
	}
	break;
    }

    case TM_SET_BLUE_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_SET_BLUE:
    {
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &quantVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetBlueQuantum(wandPtr, (Quantum)quantVal);
	} else {
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &normVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetBlue(wandPtr, normVal);
	}
	break;
    }

    case TM_SET_CYAN_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_SET_CYAN:
    {
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &quantVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetCyanQuantum(wandPtr, (Quantum)quantVal);
	} else {
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &normVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetCyan(wandPtr, normVal);
	}
	break;
    }

    case TM_SET_GREEN_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_SET_GREEN:
    {
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &quantVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetGreenQuantum(wandPtr, (Quantum)quantVal);
	} else {
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &normVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetGreen(wandPtr, normVal);
	}
	break;
    }

    case TM_SET_MAGENTA_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_SET_MAGENTA:
    {
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &quantVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetMagentaQuantum(wandPtr, (Quantum)quantVal);
	} else {
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &normVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetMagenta(wandPtr, normVal);
	}
	break;
    }

    case TM_SET_OPACITY_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_SET_OPACITY:
    {
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &quantVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetOpacityQuantum(wandPtr, (Quantum)quantVal);
	} else {
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &normVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetOpacity(wandPtr, normVal);
	}
	break;
    }

    case TM_SET_RED_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_SET_RED:
    {
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &quantVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetRedQuantum(wandPtr, (Quantum)quantVal);
	} else {
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &normVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetRed(wandPtr, normVal);
	}
	break;
    }

    case TM_SET_YELLOW_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_SET_YELLOW:
    {
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &quantVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetYellowQuantum(wandPtr, (Quantum)quantVal);
	} else {
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &normVal)) != TCL_OK ) {
		return stat;
	    }
	    PixelSetYellow(wandPtr, normVal);
	}
	break;
    }

    case TM_GET_BLACK_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_GET_BLACK:
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    quantVal = PixelGetBlackQuantum(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(quantVal));
	} else {
	    normVal = PixelGetBlack(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(normVal));
	}
	break;
    }

    case TM_GET_BLUE_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_GET_BLUE:
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    quantVal = PixelGetBlueQuantum(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(quantVal));
	} else {
	    normVal = PixelGetBlue(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(normVal));
	}
	break;
    }

    case TM_GET_CYAN_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_GET_CYAN:
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    quantVal = PixelGetCyanQuantum(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(quantVal));
	} else {
	    normVal = PixelGetCyan(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(normVal));
	}
	break;
    }

    case TM_GET_GREEN_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_GET_GREEN:
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    quantVal = PixelGetGreenQuantum(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(quantVal));
	} else {
	    normVal = PixelGetGreen(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(normVal));
	}
	break;
    }

    case TM_GET_MAGENTA_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_GET_MAGENTA:
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    quantVal = PixelGetMagentaQuantum(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(quantVal));
	} else {
	    normVal = PixelGetMagenta(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(normVal));
	}
	break;
    }

    case TM_GET_OPACITY_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_GET_OPACITY:
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    quantVal = PixelGetOpacityQuantum(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(quantVal));
	} else {
	    normVal = PixelGetOpacity(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(normVal));
	}
	break;
    }

    case TM_GET_RED_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_GET_RED:
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    quantVal = PixelGetRedQuantum(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(quantVal));
	} else {
	    normVal = PixelGetRed(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(normVal));
	}
	break;
    }

    case TM_GET_YELLOW_QUANTUM:
    {
	quantFlag = 1; /* and continue ... */
    }
    case TM_GET_YELLOW:
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( quantFlag ) {
	    quantVal = PixelGetYellowQuantum(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(quantVal));
	} else {
	    normVal = PixelGetYellow(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(normVal));
	}
	break;
    }

    case TM_QUANTUM:                /* quantum ?{r g b o}? */
    case TM_GET_QUANTUM:            /* GetQuantum */
    case TM_SET_QUANTUM:            /* SetQuantum {r g b o} */
    {
        PixelPacket color;

	if( ((enum subIndex)index == TM_QUANTUM) && (objc != 2) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?{r g b o}?");
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_GET_QUANTUM) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	if( ((enum subIndex)index == TM_SET_QUANTUM) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "{r g b o}");
	    return TCL_ERROR;
	}
	if( objc == 3 ) {
	    /*
	     * Set quantum values
	     */
            Tcl_Obj        **listPtr;
            unsigned long  quant[4];
            int            i, listLen;

	    if( (stat = Tcl_ListObjGetElements(interp, objv[2], &listLen, &listPtr)) != TCL_OK ) {
	        return stat;
	    }
            if( listLen != 4 ) {
	        Tcl_AppendResult(interp, "PixelWand SetQuantum: List of 4 colors {r g b o} required", NULL);
	        return TCL_ERROR;
            }
	    for( i=0; i < 4; i++ ) {
	        if( (stat = Tcl_GetLongFromObj(interp, listPtr[i], &quant[i])) != TCL_OK) {
		    return stat;
	        }
	    }
            color.red     = (Quantum) quant[0];
            color.green   = (Quantum) quant[1];
            color.blue    = (Quantum) quant[2];
            color.opacity = (Quantum) quant[3];

	    PixelSetQuantumColor(wandPtr, &color);
	} else {
	    /*
	     * Get quantum values
	     */
            Tcl_Obj *listPtr = Tcl_NewListObj(0, NULL);;

	    PixelGetQuantumColor(wandPtr, &color);

            Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj(color.red));
            Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj(color.green));
            Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj(color.blue));
            Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewLongObj(color.opacity));

            Tcl_SetObjResult(interp, listPtr);
	}
	break;
    }
    /*
     * All subcommands should be matched
     * A DEFAULT or TM_END_OF_TABLE would be a serious fault
     */
    case TM_END_OF_TABLE:
    default:
    {
	Tcl_AppendResult(interp, "TclMagick pixelObjCmd: Unmatched subcommand table entry", NULL);
	return TCL_ERROR;
    }

    } /* switch(index) */

    return(TCL_OK);
}


/*----------------------------------------------------------------------
 * DrawingWand object command
 *----------------------------------------------------------------------
 *
 * DrawWand subcmd ?args?
 *
 *----------------------------------------------------------------------
 */
static int drawObjCmd(
    ClientData  clientData,         /* PixelWand pointer */
    Tcl_Interp  *interp,            /* Interpreter containing image */
    int         objc,               /* Number of arguments */
    Tcl_Obj     *CONST objv[] )     /* List of arguments */
{
    static CONST char *subCmds[] = {
        "affine",           "Affine",
        "annotation",       "Annotation",
        "arc",              "Arc",
        "bezier",           "Bezier",
        "circle",           "Circle",
        "clippath",         "GetClipPath",      "SetClipPath",
        "cliprule",         "GetClipRule",      "SetClipRule",
        "clipunits",        "GetClipUnits",     "SetClipUnits",
        "color",            "Color",
        "comment",          "Comment",
        "ellipse",          "Ellipse",
        "fillcolor",        "GetFillColor",     "SetFillColor",
        "fillopacity",      "GetFillOpacity",   "SetFillOpacity",
        "fillpatternurl",   			"SetFillPatternURL",
        "fillrule",         "GetFillRule",      "SetFillRule",
        "font",             "GetFont",          "SetFont",
        "fontfamily",       "GetFontFamily",    "SetFontFamily",
        "fontsize",         "GetFontSize",      "SetFontSize",
        "fontstretch",      "GetFontStretch",   "SetFontStretch",
        "fontstyle",        "GetFontStyle",     "SetFontStyle",
        "fontweight",       "GetFontWeight",    "SetFontWeight",
        "gravity",          "GetGravity",       "SetGravity",
        "line",             "Line",
        "matte",            "Matte",
        "point",            "Point",
        "polygon",          "Polygon",
        "polyline",         "Polyline",
        "path",
        "push",             "pop",
        "PushClipPath",     "PopClipPath",
        "PushDefs",         "PopDefs",
        "PushGraphicContext","PopGraphicContext",
        "PushPattern",      "PopPattern",
        "rectangle",        "Rectangle",
        "render",           "Render",
        "rotate",           "Rotate",
        "round",            "RoundRectangle",
        "scale",            "Scale",
        "skewx",            "SkewX",
        "skewy",            "SkewY",
        "strokecolor",      "GetStrokeColor",       "SetStrokeColor",
        "strokeantialias",  "GetStrokeAntialias",   "SetStrokeAntialias",
        "strokedasharray",  "GetStrokeDashArray",   "SetStrokeDashArray",
        "strokedashoffset", "GetStrokeDashOffset",  "SetStrokeDashOffset",
        "strokelinecap",    "GetStrokeLineCap",     "SetStrokeLineCap",
        "strokelinejoin",   "GetStrokeLineJoin",    "SetStrokeLineJoin",
        "strokemiterlimit", "GetStrokeMiterLimit",  "SetStrokeMiterLimit",
        "strokeopacity",    "GetStrokeOpacity",     "SetStrokeOpacity",
        "strokepatternurl",   			    "SetStrokePatternURL",
        "strokewidth",      "GetStrokeWidth",       "SetStrokeWidth",
        "textantialias",    "GetTextAntialias",     "SetTextAntialias",
        "textdecoration",   "GetTextDecoration",    "SetTextDecoration",
        "textencoding",     "GetTextEncoding",      "SetTextEncoding",
        "textundercolor",   "GetTextUnderColor",    "SetTextUnderColor",
        "translate",        "Translate",
        "viewbox",          "SetViewbox",
        (char *) NULL
    };
    enum subIndex {
        TM_AFFINE,          TM_AAFFINE,
        TM_ANNOTATION,      TM_AANNOTATION,
        TM_ARC,             TM_AARC,
        TM_BEZIER,          TM_BBEZIER,
        TM_CIRCLE,          TM_CCIRCLE,
        TM_CLIPPATH,        TM_GET_CLIPPATH,        TM_SET_CLIPPATH,
        TM_CLIPRULE,        TM_GET_CLIPRULE,        TM_SET_CLIPRULE,
        TM_CLIPUNITS,       TM_GET_CLIPUNITS,       TM_SET_CLIPUNITS,
        TM_COLOR,           TM_CCOLOR,
        TM_COMMENT,         TM_CCOMMENT,
        TM_ELLIPSE,         TM_EELLIPSE,
        TM_FILLCOLOR,       TM_GET_FILLCOLOR,       TM_SET_FILLCOLOR,
        TM_FILLOPACITY,     TM_GET_FILLOPACITY,     TM_SET_FILLOPACITY,
        TM_FILLPATTERNURL,                          TM_SET_FILLPATTERNURL,
        TM_FILLRULE,        TM_GET_FILLRULE,        TM_SET_FILLRULE,
        TM_FONT,            TM_GET_FONT,            TM_SET_FONT,
        TM_FONTFAMILY,      TM_GET_FONTFAMILY,      TM_SET_FONTFAMILY,
        TM_FONTSIZE,        TM_GET_FONTSIZE,        TM_SET_FONTSIZE,
        TM_FONTSTRETCH,     TM_GET_FONTSTRETCH,     TM_SET_FONTSTRETCH,
        TM_FONTSTYLE,       TM_GET_FONTSTYLE,       TM_SET_FONTSTYLE,
        TM_FONTWEIGHT,      TM_GET_FONTWEIGHT,      TM_SET_FONTWEIGHT,
        TM_GRAVITY,         TM_GET_GRAVITY,         TM_SET_GRAVITY,
        TM_LINE,            TM_LLINE,
        TM_MATTE,           TM_MMATTE,
        TM_POINT,           TM_PPOINT,
        TM_POLYGON,         TM_PPOLYGON,
        TM_POLYLINE,        TM_PPOLYLINE,
        TM_PATH,
        TM_PUSH,            TM_POP,
        TM_PUSH_CLIPPATH,   TM_POP_CLIPPATH,
        TM_PUSH_DEFS,       TM_POP_DEFS,
        TM_PUSH_GRAPHIC_CTX,TM_POP_GRAPHIC_CTX,
        TM_PUSH_PATTERN,    TM_POP_PATTERN,
        TM_RECTANGLE,       TM_RRECTANGLE,
        TM_RENDER,          TM_RRENDER,
        TM_ROTATE,          TM_RROTATE,
        TM_ROUND,           TM_ROUND_RECTANGLE,
        TM_SCALE,           TM_SSCALE,
        TM_SKEWX,           TM_SKEW_X,
        TM_SKEWY,           TM_SKEW_Y,
        TM_STROKE_COLOR,    TM_GET_STROKE_COLOR,        TM_SET_STROKE_COLOR,
        TM_STROKE_ANTIALIAS,TM_GET_STROKE_ANTIALIAS,    TM_SET_STROKE_ANTIALIAS,
        TM_STROKE_DASHARRAY,TM_GET_STROKE_DASHARRAY,    TM_SET_STROKE_DASHARRAY,
        TM_STROKE_DASHOFFS, TM_GET_STROKE_DASHOFFS,     TM_SET_STROKE_DASHOFFS,
        TM_STROKE_LINECAP,  TM_GET_STROKE_LINECAP,      TM_SET_STROKE_LINECAP,
        TM_STROKE_LINEJOIN, TM_GET_STROKE_LINEJOIN,     TM_SET_STROKE_LINEJOIN,
        TM_STROKE_MITERLIM, TM_GET_STROKE_MITERLIM,     TM_SET_STROKE_MITERLIM,
        TM_STROKE_OPACITY,  TM_GET_STROKE_OPACITY,      TM_SET_STROKE_OPACITY,
        TM_STROKE_PATTERNURL,                           TM_SET_STROKE_PATTERNURL,
        TM_STROKE_WIDTH,    TM_GET_STROKE_WIDTH,        TM_SET_STROKE_WIDTH,
        TM_TEXT_ANTIALIAS,  TM_GET_TEXT_ANTIALIAS,      TM_SET_TEXT_ANTIALIAS,
        TM_TEXT_DECORATION, TM_GET_TEXT_DECORATION,     TM_SET_TEXT_DECORATION,
        TM_TEXT_ENCODING,   TM_GET_TEXT_ENCODING,       TM_SET_TEXT_ENCODING,
        TM_TEXT_UNDERCOLOR, TM_GET_TEXT_UNDERCOLOR,     TM_SET_TEXT_UNDERCOLOR,
        TM_TRANSLATE,       TM_TTRANSLATE,
        TM_VIEWBOX,         TM_SET_VIEWBOX,
        TM_END_OF_TABLE
    };
    static CONST char *pushCmdNames[] = {
        "clippath", "defs", "graphiccontext", "pattern",
        (char *) NULL
    };
    enum pushCmdIndex {
        TM_PUSH_CMD_CLIP, TM_PUSH_CMD_DEFS, TM_PUSH_CMD_GRAPH, TM_PUSH_CMD_PAT,
    };
    static CONST char *fillRuleNames[] = {
        "undefined","evenodd","nonzero",
        (char *) NULL
    };
    static FillRule fillRules[] = {
	UndefinedRule, EvenOddRule, NonZeroRule
    };
    static CONST char *paintMethodNames[] = {
        "point", "replace", "floodfill", "filltoborder", "reset",
	(char *) NULL
    };
    static PaintMethod paintMethods[] = {
	PointMethod, ReplaceMethod, FloodfillMethod, FillToBorderMethod, ResetMethod
    };
    int         index, stat;
    TclMagickObj *magickPtr = (TclMagickObj *) clientData;
    DrawingWand  *wandPtr   = (DrawingWand *) magickPtr->wandPtr;

#ifdef MAGICK_DEBUG
    /*
     * Verify subCmds table size
     * No idea how to do this at compile-time
     */
    if( sizeof(subCmds)/sizeof(subCmds[0]) != TM_END_OF_TABLE + 1 ) {
        Tcl_Panic("magickObjCmd: Invalid subCmds[] table");
    }
#endif

    if( objc < 2 ) {
        Tcl_WrongNumArgs( interp, 1, objv, "subcmd ?args?" );
        return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subCmds, "subcmd", 0, &index) != TCL_OK) {
        return TCL_ERROR;
    }

    switch ((enum subIndex)index) {

    case TM_AFFINE:     /* affine sx rx ry sy tx ty */
    case TM_AAFFINE:    /* Affine sx rx ry sy tx ty */
    {
	AffineMatrix A;

	if( objc != 8 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "sx rx ry sy tx ty");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &A.sx)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &A.rx)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &A.ry)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &A.sy)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[6], &A.tx)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[7], &A.ty)) != TCL_OK ) {
	    return stat;
	}
	DrawAffine(wandPtr, &A);
	break;
    }

    case TM_ANNOTATION:     /* annotation x y text */
    case TM_AANNOTATION:    /* Annotation x y text */
    {
	double x, y;
	char *text;

	if( objc != 5 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y text");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK ) {
	    return stat;
	}
	text = Tcl_GetString(objv[4]);
	DrawAnnotation(wandPtr, x, y, text);
	break;
    }

    case TM_ARC:    /* arc sx sy ex ey sd ed */
    case TM_AARC:   /* Arc sx sy ex ey sd ed */
    {
	double sx, sy, ex, ey, sd, ed;

	if( objc != 8 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "sx sy ex ey sd ed");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &sx)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &sy)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &ex)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &ey)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[6], &sd)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[7], &ed)) != TCL_OK ) {
	    return stat;
	}
	DrawArc(wandPtr, sx, sy, ex, ey, sd, ed);
	break;
    }

    case TM_BEZIER:     /* bezier   x y x y ... */
    case TM_BBEZIER:    /* Bezier   x y x y ... */
    case TM_POLYGON:    /* polygon  x y x y ... */
    case TM_PPOLYGON:   /* Polygon  x y x y ... */
    case TM_POLYLINE:   /* polyline x y x y ... */
    case TM_PPOLYLINE:  /* Polyline x y x y ... */
    {
	PointInfo *coordinates;
	unsigned long i, num;

	if( (objc-2) % 2 != 0 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y x y ...");
	    return TCL_ERROR;
	}
	num = (objc-2)/2;   /* number of coordinates */
	coordinates = (PointInfo *)ckalloc(num*sizeof(coordinates[0]));
	if( coordinates == NULL ) {
	    Tcl_AppendResult(interp, "TclMagick: out of memory", NULL);
	    return TCL_ERROR;
	}
        memset( coordinates, 0, num*sizeof(coordinates[0]) );

	objc -= 2, objv += 2;
	for( i=0; i<num; i++) {
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[0], &coordinates[i].x)) != TCL_OK ) {
		return stat;
	    }
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[1], &coordinates[i].y)) != TCL_OK ) {
		return stat;
	    }
	    objc -= 2, objv +=2;
	}
	switch ((enum subIndex)index) {
	case TM_BEZIER:   case TM_BBEZIER:
	    DrawBezier(wandPtr, num, coordinates);
            break;
	case TM_POLYGON:  case TM_PPOLYGON:
	    DrawPolygon(wandPtr, num, coordinates);
            break;
	case TM_POLYLINE: case TM_PPOLYLINE:
	    DrawPolyline(wandPtr, num, coordinates);
            break;
	default:
	    break;
	}

	ckfree((char *)coordinates);
	break;
    }

    case TM_CIRCLE:     /* circle ox oy px py */
    case TM_CCIRCLE:    /* Circle ox oy px py */
    {
	double ox, oy, px, py;

	if( objc != 6 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "ox oy px py");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &ox)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &oy)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &px)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &py)) != TCL_OK ) {
	    return stat;
	}
	DrawCircle(wandPtr, ox, oy, px, py);
	break;
    }

    case TM_COLOR:  /* color x y paintMethod */
    case TM_CCOLOR: /* Color x y paintMethod */
    {
	double x, y;
	int paintIdx;

	if( objc != 5 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y paintMethod");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK ) {
	    return stat;
	}
	if (Tcl_GetIndexFromObj(interp, objv[4], paintMethodNames, "paintMethod", 0, &paintIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	DrawColor(wandPtr, x, y, paintMethods[paintIdx]);
	break;
    }

    case TM_COMMENT:    /* comment text */
    case TM_CCOMMENT:   /* Comment text */
    {
	char *text;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "text");
	    return TCL_ERROR;
	}
	text = Tcl_GetString(objv[2]);
	DrawComment(wandPtr, text);
	break;
    }

    case TM_ELLIPSE:    /* ellipse ox oyo rx ry start end */
    case TM_EELLIPSE:   /* Ellipse ox oyo rx ry start end */
    {
	double ox, oy, rx, ry, start, end;

	if( objc != 8 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "ox oy rx ry start end");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &ox)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &oy)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &rx)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &ry)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[6], &start)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[7], &end)) != TCL_OK ) {
	    return stat;
	}
	DrawEllipse(wandPtr, ox, oy, rx, ry, start, end);
	break;
    }

    case TM_CLIPPATH:        /* clippath ?name? */
    case TM_GET_CLIPPATH:    /* GetClipPath */
    case TM_SET_CLIPPATH:    /* SetClipPath name */
    {
	char *name;

	if( ((enum subIndex)index == TM_CLIPPATH) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?name?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_CLIPPATH) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_CLIPPATH) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set name */
	    name = Tcl_GetString(objv[2]);
	    DrawSetClipPath(wandPtr, name);
	} else {    /* Get name */
	    name = (char *)DrawGetClipPath(wandPtr);
	    if(name != NULL) {
		Tcl_SetResult(interp, name, TCL_VOLATILE);
		MagickRelinquishMemory(name);
	    }
	}
	break;
    }

    case TM_CLIPRULE:        /* cliprule ?rule? */
    case TM_GET_CLIPRULE:    /* GetClipRule */
    case TM_SET_CLIPRULE:    /* SetClipRule rule */
    {
	int      ruleIdx;
	FillRule rule;

	if( ((enum subIndex)index == TM_CLIPRULE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?rule?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_CLIPRULE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_CLIPRULE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "rule");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set rule */
	    if (Tcl_GetIndexFromObj(interp, objv[2], fillRuleNames, "fillRule", 0, &ruleIdx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    DrawSetClipRule(wandPtr, fillRules[ruleIdx]);
	} else {    /* Get rule */
	    rule = DrawGetClipRule(wandPtr);
	    for (ruleIdx = 0; ruleIdx < sizeof(fillRules)/sizeof(fillRules[0]); ruleIdx++) {
		if( fillRules[ruleIdx] == rule ) {
		    Tcl_SetResult(interp, (char *)fillRuleNames[ruleIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)rule));
	}
	break;
    }

    case TM_CLIPUNITS:      /* clipunits ?unit? */
    case TM_GET_CLIPUNITS:  /* GetClipUnits */
    case TM_SET_CLIPUNITS:  /* SetClipunits unit */
    {
	static CONST char *unitNames[] = {
	    "userspace", "userspaceonuse", "objectboundingbox",
	    (char *) NULL
	};
	static ClipPathUnits unitTypes[] = {
	    UserSpace, UserSpaceOnUse, ObjectBoundingBox
	};
	int           unitIdx;
	ClipPathUnits unit;

	if( ((enum subIndex)index == TM_CLIPUNITS) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?unit?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_CLIPUNITS) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_CLIPUNITS) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "unit");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set rule */
	    if (Tcl_GetIndexFromObj(interp, objv[2], unitNames, "unit", 0, &unitIdx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    DrawSetClipUnits(wandPtr, unitTypes[unitIdx]);
	} else {    /* Get rule */
	    unit = DrawGetClipUnits(wandPtr);
	    for (unitIdx = 0; unitIdx < sizeof(unitTypes)/sizeof(unitTypes[0]); unitIdx++) {
		if( unitTypes[unitIdx] == unit ) {
		    Tcl_SetResult(interp, (char *)unitNames[unitIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)unit));
	}
	break;
    }

    case TM_FILLCOLOR:              /* fillcolor ?pixel? */
    case TM_STROKE_COLOR:           /* strokecolor ?pixel? */
    case TM_TEXT_UNDERCOLOR:        /* textundercolor ?pixel? */
    {
        PixelWand   *pixelPtr = NULL;
        char        *name = NULL;

        if( objc > 3 ) {
            Tcl_WrongNumArgs(interp, 2, objv, "?pixelName?");
            return TCL_ERROR;
        }
	if (objc > 2) { /* Set color / Get color with new name */
	    name = Tcl_GetString(objv[2]);
	    pixelPtr = findPixelWand(interp, name);
        }
        /*
         * GET color if pixel object doesn't exists
         * otherwise SET color
         */
        if( pixelPtr == NULL ) {
            pixelPtr = NewPixelWand();
            name = newPixelObj(interp, pixelPtr, name );

            switch ((enum subIndex)index) {
		case TM_FILLCOLOR:
			DrawGetFillColor(wandPtr, pixelPtr);
			break;
		case TM_STROKE_COLOR:
			DrawGetStrokeColor(wandPtr, pixelPtr);
			break;
		case TM_TEXT_UNDERCOLOR:
			DrawGetTextUnderColor(wandPtr, pixelPtr);
			break;
		default:
			break;
            }
            Tcl_SetResult(interp, name, TCL_VOLATILE);

        } else {
            switch ((enum subIndex)index) {
		case TM_FILLCOLOR:
			DrawSetFillColor(wandPtr, pixelPtr);
			break;
		case TM_STROKE_COLOR:
			DrawSetStrokeColor(wandPtr, pixelPtr);
			break;
		case TM_TEXT_UNDERCOLOR:
			DrawSetTextUnderColor(wandPtr, pixelPtr);
			break;
		default:
			break;
            }
        }
	break;
    }

    case TM_GET_FILLCOLOR:          /* GetFillColor pixel */
    case TM_GET_STROKE_COLOR:       /* GetStrokeColor pixel */
    case TM_GET_TEXT_UNDERCOLOR:    /* GetTextUnderColor pixel */
       {
            PixelWand   *pixelPtr;
            char        *name;

            if( objc != 3 ) {
                Tcl_WrongNumArgs(interp, 2, objv, "pixelName");
                return TCL_ERROR;
            }
            name = Tcl_GetString(objv[2]);
            if( (pixelPtr = findPixelWand(interp, name)) == NULL ) {
		return TCL_ERROR;
	    }
            switch ((enum subIndex)index) {
	    case TM_GET_FILLCOLOR:
		DrawGetFillColor(wandPtr, pixelPtr);
		break;
	    case TM_GET_STROKE_COLOR:
		DrawGetStrokeColor(wandPtr, pixelPtr);
		break;
	    case TM_GET_TEXT_UNDERCOLOR:
		DrawGetTextUnderColor(wandPtr, pixelPtr);
		break;
	    default:
		break;
            }
            break;
        }

    case TM_SET_FILLCOLOR:          /* SetFillColor pixel */
    case TM_SET_STROKE_COLOR:       /* SetStrokeColor pixel */
    case TM_SET_TEXT_UNDERCOLOR:    /* SetTextUnderColor pixel */
       {
            PixelWand   *pixelPtr;
            char        *name;

            if( objc != 3 ) {
                Tcl_WrongNumArgs(interp, 2, objv, "pixelName");
                return TCL_ERROR;
            }
            name = Tcl_GetString(objv[2]);
            if( (pixelPtr = findPixelWand(interp, name)) == NULL ) {
		return TCL_ERROR;
	    }
            switch ((enum subIndex)index) {
	    case TM_SET_FILLCOLOR:
		DrawSetFillColor(wandPtr, pixelPtr);
		break;
	    case TM_SET_STROKE_COLOR:
		DrawSetStrokeColor(wandPtr, pixelPtr);
		break;
	    case TM_SET_TEXT_UNDERCOLOR:
		DrawSetTextUnderColor(wandPtr, pixelPtr);
		break;
	    default:
		break;
            }
            break;
        }

    case TM_FILLOPACITY:     /* fillopacity ?value? */
    case TM_GET_FILLOPACITY: /* GetFillOpacity  */
    case TM_SET_FILLOPACITY: /* SetFillOpacity value */
    {
	double value;

	if( ((enum subIndex)index == TM_FILLOPACITY) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?value?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_FILLOPACITY) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_FILLOPACITY) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set fill opacity */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &value)) != TCL_OK ) {
		return stat;
	    }
	    DrawSetFillOpacity(wandPtr, value);
	} else {    /* Get fill opacity */
	    value = DrawGetFillOpacity(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(value));
	}
	break;
    }

    case TM_FILLPATTERNURL:      /* fillpatternurl url */
    case TM_SET_FILLPATTERNURL:  /* SetFillPatternURL url */
    {
	char *url;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "url");
	    return TCL_ERROR;
	}
	url = Tcl_GetString(objv[2]);
	DrawSetFillPatternURL(wandPtr, url);
	break;
    }

    case TM_FILLRULE:        /* fillrule ?rule? */
    case TM_GET_FILLRULE:    /* GetFillRule */
    case TM_SET_FILLRULE:    /* SetFillRule rule */
    {
	int      ruleIdx;
	FillRule rule;

	if( ((enum subIndex)index == TM_FILLRULE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?rule?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_FILLRULE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_FILLRULE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "rule");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set rule */
	    if (Tcl_GetIndexFromObj(interp, objv[2], fillRuleNames, "fillRule", 0, &ruleIdx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    DrawSetFillRule(wandPtr, fillRules[ruleIdx]);
	} else {    /* Get rule */
	    rule = DrawGetFillRule(wandPtr);
	    for (ruleIdx = 0; ruleIdx < sizeof(fillRules)/sizeof(fillRules[0]); ruleIdx++) {
		if( fillRules[ruleIdx] == rule ) {
		    Tcl_SetResult(interp, (char *)fillRuleNames[ruleIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)rule));
	}
	break;
    }

    case TM_FONT:        /* font ?fontname? */
    case TM_GET_FONT:    /* GetFont */
    case TM_SET_FONT:    /* SetFont fontname */
    {
	char *fontname;

	if( ((enum subIndex)index == TM_FONT) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?fontname?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_FONT) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_FONT) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "fontname");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set font */
	    fontname = Tcl_GetString(objv[2]);
	    DrawSetFont(wandPtr, fontname);
	} else {    /* Get font */
	    fontname = DrawGetFont(wandPtr);
	    if(fontname != NULL) {
		Tcl_SetResult(interp, fontname, TCL_VOLATILE);
		MagickRelinquishMemory(fontname); /* Free TclMagick resource */
	    }
	}
	break;
    }

    case TM_FONTFAMILY:        /* fontfamily ?name? */
    case TM_GET_FONTFAMILY:    /* GetFontFamily */
    case TM_SET_FONTFAMILY:    /* SetFontFamily name */
    {
	char *name;

	if( ((enum subIndex)index == TM_FONTFAMILY) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?name?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_FONTFAMILY) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_FONTFAMILY) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "name");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set font family */
	    name = Tcl_GetString(objv[2]);
	    DrawSetFontFamily(wandPtr, name);
	} else {    /* Get font family */
	    name = DrawGetFontFamily(wandPtr);
	    if(name != NULL) {
		Tcl_SetResult(interp, name, TCL_VOLATILE);
		MagickRelinquishMemory(name); /* Free TclMagick resource */
	    }
	}
	break;
    }

    case TM_FONTSIZE:        /* fontsize ?value? */
    case TM_GET_FONTSIZE:    /* GetFontSize */
    case TM_SET_FONTSIZE:    /* SetFontSize value */
    {
	double value;

	if( ((enum subIndex)index == TM_FONTSIZE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?value?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_FONTSIZE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_FONTSIZE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set font size */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &value)) != TCL_OK ) {
		return stat;
	    }
	    DrawSetFontSize(wandPtr, value);
	} else {    /* Get font size */
	    value = DrawGetFontSize(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(value));
	}
	break;
    }

    case TM_FONTSTRETCH:     /* fontstretch ?stretchType? */
    case TM_GET_FONTSTRETCH: /* GetFontStretch */
    case TM_SET_FONTSTRETCH: /* SetFontStretch stretchType */
    {
	static CONST char *stretchNames[] = {
	    "normal",        "ultracondensed", "extracondensed", "condensed",
	    "semicondensed", "semiexpanded",   "expanded",       "extraexpanded",
	    "ultraexpanded", "any",
	    (char *) NULL
	};
	static StretchType stretchTypes[] = {
	    NormalStretch,        UltraCondensedStretch, ExtraCondensedStretch, CondensedStretch,
	    SemiCondensedStretch, SemiExpandedStretch,   ExpandedStretch,       ExtraExpandedStretch,
	    UltraExpandedStretch, AnyStretch

	};
	int stretchIdx;
	StretchType stretch;

	if( ((enum subIndex)index == TM_FONTSTRETCH) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?stretchType?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_FONTSTRETCH) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_FONTSTRETCH) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "stretchType");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set font stretch */
	    if (Tcl_GetIndexFromObj(interp, objv[2], stretchNames, "stretchType", 0, &stretchIdx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    DrawSetFontStretch(wandPtr, stretchTypes[stretchIdx]);
	} else {    /* Get font stretch */
	    stretch = DrawGetFontStretch(wandPtr);
	    for (stretchIdx = 0; stretchIdx < sizeof(stretchTypes)/sizeof(stretchTypes[0]); stretchIdx++) {
		if( stretchTypes[stretchIdx] == stretch ) {
		    Tcl_SetResult(interp, (char *)stretchNames[stretchIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)stretch));
	}
	break;
    }

    case TM_FONTSTYLE:     /* fontstyle ?style? */
    case TM_GET_FONTSTYLE: /* GetFontStyle */
    case TM_SET_FONTSTYLE: /* SetFontStyle style */
    {
	static CONST char *styleNames[] = {
	    "normal", "italic", "oblique", "any",
	    (char *) NULL
	};
	static StyleType styleTypes[] = {
	    NormalStyle, ItalicStyle, ObliqueStyle, AnyStyle
	};
	int styleIdx;
	StyleType style;

	if( ((enum subIndex)index == TM_FONTSTYLE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?styleType?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_FONTSTYLE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_FONTSTYLE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "styleType");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set font style */
	    if (Tcl_GetIndexFromObj(interp, objv[2], styleNames, "styleType", 0, &styleIdx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    DrawSetFontStyle(wandPtr, styleTypes[styleIdx]);
	} else {    /* Get font style */
	    style = DrawGetFontStyle(wandPtr);
	    for (styleIdx = 0; styleIdx < sizeof(styleTypes)/sizeof(styleTypes[0]); styleIdx++) {
		if( styleTypes[styleIdx] == style ) {
		    Tcl_SetResult(interp, (char *)styleNames[styleIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)style));
	}
	break;
    }

    case TM_FONTWEIGHT:     /* fontweight ?value? */
    case TM_GET_FONTWEIGHT: /* GetFontWeight */
    case TM_SET_FONTWEIGHT: /* SetFontWeight value */
    {
	unsigned value;

	if( ((enum subIndex)index == TM_FONTSTYLE) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?value?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_FONTSTYLE) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_FONTSTYLE) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "value");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set font weight */
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &value)) != TCL_OK ) {
		return stat;
	    }
	    DrawSetFontWeight(wandPtr, value);
	} else {    /* Get font weight */
	    value = DrawGetFontWeight(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)value));
	}
	break;
    }

    case TM_GRAVITY:     /* gravity ?gravityType? */
    case TM_GET_GRAVITY: /* gravity */
    case TM_SET_GRAVITY: /* gravity gravityType */
    {
	static CONST char *gravNames[] = {
	    "forget", "northwest", "north",    "northeast", "west",
	    "center", "east",      "southwest","south",     "southeast",
	    "static",
	    (char *) NULL
	};
	static GravityType gravTypes[] = {
	    ForgetGravity, NorthWestGravity, NorthGravity,     NorthEastGravity, WestGravity,
	    CenterGravity, EastGravity,      SouthWestGravity, SouthGravity,     SouthEastGravity,
	    StaticGravity
	};
	int gravIdx;
	GravityType grav;

	if( ((enum subIndex)index == TM_GRAVITY) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?gravityType?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_GRAVITY) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_GRAVITY) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "gravityType");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set gravity */
	    if (Tcl_GetIndexFromObj(interp, objv[2], gravNames, "gravityType", 0, &gravIdx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    DrawSetGravity(wandPtr, gravTypes[gravIdx]);
	} else {    /* Get gravity */
	    grav = DrawGetGravity(wandPtr);
	    for (gravIdx = 0; gravIdx < sizeof(gravTypes)/sizeof(gravTypes[0]); gravIdx++) {
		if( gravTypes[gravIdx] == grav ) {
		    Tcl_SetResult(interp, (char *)gravNames[gravIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)grav));
	}
	break;
    }

    case TM_LINE:       /* line sx sy ex ey */
    case TM_LLINE:      /* Line sx sy ex ey */
    {
	double sx, sy, ex, ey;

	if( objc != 6 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "sx sy ex ey");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &sx)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &sy)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &ex)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &ey)) != TCL_OK ) {
	    return stat;
	}
	DrawLine(wandPtr, sx, sy, ex, ey);
	break;
    }

    case TM_MATTE:  /* matte x y paintMethod */
    case TM_MMATTE: /* Matte x y paintMethod */
    {
	double x, y;
	int paintIdx=0;

	if( objc != 5 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y paintMethod");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK ) {
	    return stat;
	}
	if (Tcl_GetIndexFromObj(interp, objv[4], paintMethodNames, "paintMethod", 0, &paintIdx) != TCL_OK) {
	    return TCL_ERROR;
	}
	DrawMatte(wandPtr, x, y, paintMethods[paintIdx]);
	break;
    }

    case TM_POINT:  /* point x y */
    case TM_PPOINT: /* Point x y */
    {
	double x, y;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK ) {
	    return stat;
	}
	DrawPoint(wandPtr, x, y);
	break;
    }

    case TM_RECTANGLE:  /* rectangle x1 y1 x2 y2 */
    case TM_RRECTANGLE: /* Rectangle x1 y1 x2 y2 */
    {
	double x1, y1, x2, y2;

	if( objc != 6 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x1 y1 x2 y2");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x1)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y1)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &x2)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &y2)) != TCL_OK ) {
	    return stat;
	}
	DrawRectangle(wandPtr, x1, y1, x2, y2);
	break;
    }

    case TM_RENDER:  /* render */
    case TM_RRENDER: /* Render */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	DrawRender(wandPtr);
	break;
    }

    case TM_ROTATE:     /* rotate degrees */
    case TM_RROTATE:    /* Rotate degrees */
    {
	double degrees;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "degrees");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &degrees)) != TCL_OK ) {
	    return stat;
	}
	DrawRotate(wandPtr, degrees);
	break;
    }

    case TM_ROUND:          /* round x1 y1 x2 y2 rx ry */
    case TM_ROUND_RECTANGLE:/* RoundRectangle x1 y1 x2 y2 rx ry */
    {
	double x1, y1, x2, y2, rx, ry;

	if( objc != 8 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x1 y1 x2 y2 rx ry");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x1)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y1)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &x2)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &y2)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[6], &rx)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[7], &ry)) != TCL_OK ) {
	    return stat;
	}
	DrawRoundRectangle(wandPtr, x1, y1, x2, y2, rx, ry);
	break;
    }

    case TM_SCALE:  /* scale x y */
    case TM_SSCALE: /* Scale x y */
    {
	double x, y;

	if( (objc < 3) || (objc > 4) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x ?y?");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	y = x; /* default */
	if( (objc > 3) && ((stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK) ) {
	    return stat;
	}
	DrawScale(wandPtr, x, y);
	break;
    }

    case TM_SKEWX:     /* skewx degrees */
    case TM_SKEW_X:    /* SkewX degrees */
    {
	double degrees;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "degrees");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &degrees)) != TCL_OK ) {
	    return stat;
	}
	DrawSkewX(wandPtr, degrees);
	break;
    }

    case TM_SKEWY:     /* skewy degrees */
    case TM_SKEW_Y:    /* SkewY degrees */
    {
	double degrees;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "degrees");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &degrees)) != TCL_OK ) {
	    return stat;
	}
	DrawSkewY(wandPtr, degrees);
	break;
    }

    case TM_STROKE_ANTIALIAS:     /* strokeantialias ?flag? */
    case TM_GET_STROKE_ANTIALIAS: /* GetStrokeAntialias */
    case TM_SET_STROKE_ANTIALIAS: /* SetStrokeAntialias flag */
    {
	unsigned flag;

	if( ((enum subIndex)index == TM_STROKE_ANTIALIAS) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?flag?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_STROKE_ANTIALIAS) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_STROKE_ANTIALIAS) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "flag");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set antialias flag */
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &flag)) != TCL_OK ) {
		return stat;
	    }
	    DrawSetStrokeAntialias(wandPtr, flag);
	} else {    /* Get antialias flag */
	    flag = DrawGetStrokeAntialias(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)flag));
	}
	break;
    }

    case TM_STROKE_DASHARRAY:     /* strokedasharray {} | val val ... */
    case TM_GET_STROKE_DASHARRAY: /* GetStrokeDashArray */
    case TM_SET_STROKE_DASHARRAY: /* SetStrokeDashArray {} | val val ... */
    {
	unsigned long i, num;
	double *arr;

	if( ((enum subIndex)index == TM_GET_STROKE_DASHARRAY) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_STROKE_DASHARRAY) && (objc < 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "{} | val val ...");
	    return TCL_ERROR;
	}
	if (objc == 2) { /* Get dash array */
	    Tcl_Obj *listPtr = Tcl_NewListObj(0, NULL);

	    arr = DrawGetStrokeDashArray(wandPtr, &num);
	    while ( num > 0 ) {
		Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewDoubleObj(*arr));
		++arr;
	    }
	    Tcl_SetObjResult(interp, listPtr);
	} else {    /* Set dash array */
	    char *str = Tcl_GetString(objv[2]);

	    if( strlen(str) == 0 ) { /* SetStrokeDashArray {} : Remove existing dash array */
		DrawSetStrokeDashArray(wandPtr, 0, NULL);
	    } else {
		num = objc-2;
		arr = (double *)ckalloc(num * sizeof(*arr));
		if( arr == NULL ) {
		    Tcl_AppendResult(interp, "TclMagick: out of memory", NULL);
		    return TCL_ERROR;
		}
		for( i=0; i<num; i++ ) {
		    if( (stat = Tcl_GetDoubleFromObj(interp, objv[i+2], &arr[i])) != TCL_OK ) {
			return stat;
		    }
		}
		DrawSetStrokeDashArray(wandPtr, num, arr);
		ckfree((char *)arr);
	    }
	}
	break;
    }

    case TM_STROKE_DASHOFFS:     /* strokedashoffset ?val? */
    case TM_GET_STROKE_DASHOFFS: /* strokedashoffset */
    case TM_SET_STROKE_DASHOFFS: /* strokedashoffset val */
    {
	double val;

	if( ((enum subIndex)index == TM_STROKE_DASHOFFS) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?val?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_STROKE_DASHOFFS) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_STROKE_DASHOFFS) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "val");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set stroke dash offset */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &val)) != TCL_OK ) {
		return stat;
	    }
	    DrawSetStrokeDashOffset(wandPtr, val);
	} else {    /* Get stroke dash offset */
	    val = DrawGetStrokeDashOffset(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(val));
	}
	break;
    }

    case TM_STROKE_LINECAP:     /* strokelinecap ?linecapType? */
    case TM_GET_STROKE_LINECAP: /* GetStrokeLineCap */
    case TM_SET_STROKE_LINECAP: /* SetStrokeLineCap linecapType */
    {
	static CONST char *capNames[] = {
	    "undefined", "butt", "round", "square",
	    (char *) NULL
	};
	static LineCap capTypes[] = {
	    UndefinedCap, ButtCap, RoundCap, SquareCap
	};
	int capIdx;
	LineCap cap;

	if( ((enum subIndex)index == TM_STROKE_LINECAP) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?linecapType?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_STROKE_LINECAP) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_STROKE_LINECAP) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "linecapType");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set font style */
	    if (Tcl_GetIndexFromObj(interp, objv[2], capNames, "linecapType", 0, &capIdx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    DrawSetStrokeLineCap(wandPtr, capTypes[capIdx]);
	} else {    /* Get font style */
	    cap = DrawGetStrokeLineCap(wandPtr);
	    for (capIdx = 0; capIdx < sizeof(capTypes)/sizeof(capTypes[0]); capIdx++) {
		if( capTypes[capIdx] == cap ) {
		    Tcl_SetResult(interp, (char *)capNames[capIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)cap));
	}
	break;
    }

    case TM_STROKE_LINEJOIN:     /* strokelinejoin ?linejoinType? */
    case TM_GET_STROKE_LINEJOIN: /* GetStrokeLineJoin */
    case TM_SET_STROKE_LINEJOIN: /* SetStrokeLineJoin linejoinType */
    {
	static CONST char *joinNames[] = {
	    "undefined", "miter", "round", "bevel",
	    (char *) NULL
	};
	static LineJoin joinTypes[] = {
	    UndefinedJoin, MiterJoin, RoundJoin, BevelJoin

	};
	int joinIdx;
	LineJoin join;

	if( ((enum subIndex)index == TM_STROKE_LINEJOIN) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?linejoinType?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_STROKE_LINEJOIN) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_STROKE_LINEJOIN) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "linejoinType");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set font style */
	    if (Tcl_GetIndexFromObj(interp, objv[2], joinNames, "linejoinType", 0, &joinIdx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    DrawSetStrokeLineCap(wandPtr, joinTypes[joinIdx]);
	} else {    /* Get font style */
	    join = DrawGetStrokeLineCap(wandPtr);
	    for (joinIdx = 0; joinIdx < sizeof(joinTypes)/sizeof(joinTypes[0]); joinIdx++) {
		if( joinTypes[joinIdx] == join ) {
		    Tcl_SetResult(interp, (char *)joinNames[joinIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)join));
	}
	break;
    }

    case TM_STROKE_MITERLIM:     /* strokemiterlimit ?val? */
    case TM_GET_STROKE_MITERLIM: /* strokemiterlimit */
    case TM_SET_STROKE_MITERLIM: /* strokemiterlimit val */
    {
	unsigned val;

	if( ((enum subIndex)index == TM_STROKE_MITERLIM) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?val?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_STROKE_MITERLIM) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_STROKE_MITERLIM) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "val");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set stroke miterlimit */
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &val)) != TCL_OK ) {
		return stat;
	    }
	    DrawSetStrokeMiterLimit(wandPtr, val);
	} else {    /* Get stroke miterlimit */
	    val = DrawGetStrokeMiterLimit(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)val));
	}
	break;
    }

    case TM_STROKE_OPACITY:     /* strokeopacity ?val? */
    case TM_GET_STROKE_OPACITY: /* strokeopacity */
    case TM_SET_STROKE_OPACITY: /* strokeopacity val */
    {
	double val;

	if( ((enum subIndex)index == TM_STROKE_OPACITY) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?val?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_STROKE_OPACITY) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_STROKE_OPACITY) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "val");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set stroke opacity */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &val)) != TCL_OK ) {
		return stat;
	    }
	    DrawSetStrokeOpacity(wandPtr, val);
	} else {    /* Get stroke opacity */
	    val = DrawGetStrokeOpacity(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(val));
	}
	break;
    }

    case TM_STROKE_PATTERNURL:      /* strokepatternurl url */
    case TM_SET_STROKE_PATTERNURL:  /* SetStrokePatternURL url */
    {
	char *url;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "url");
	    return TCL_ERROR;
	}
	url = Tcl_GetString(objv[2]);
	DrawSetStrokePatternURL(wandPtr, url);
	break;
    }

    case TM_STROKE_WIDTH:     /* strokewidth ?val? */
    case TM_GET_STROKE_WIDTH: /* strokewidth */
    case TM_SET_STROKE_WIDTH: /* strokewidth val */
    {
	double val;

	if( ((enum subIndex)index == TM_STROKE_WIDTH) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?val?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_STROKE_WIDTH) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_STROKE_WIDTH) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "val");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set stroke width */
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &val)) != TCL_OK ) {
		return stat;
	    }
	    DrawSetStrokeWidth(wandPtr, val);
	} else {    /* Get stroke width */
	    val = DrawGetStrokeWidth(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(val));
	}
	break;
    }

    case TM_TEXT_ANTIALIAS:     /* textantialias ?flag? */
    case TM_GET_TEXT_ANTIALIAS: /* GetTextAntialias */
    case TM_SET_TEXT_ANTIALIAS: /* SetTextAntialias flag */
    {
	unsigned flag;

	if( ((enum subIndex)index == TM_TEXT_ANTIALIAS) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?flag?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_TEXT_ANTIALIAS) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_TEXT_ANTIALIAS) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "flag");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set antialias flag */
	    if( (stat = Tcl_GetIntFromObj(interp, objv[2], &flag)) != TCL_OK ) {
		return stat;
	    }
	    DrawSetTextAntialias(wandPtr, flag);
	} else {    /* Get antialias flag */
	    flag = DrawGetTextAntialias(wandPtr);
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)flag));
	}
	break;
    }

    case TM_TEXT_DECORATION:     /* textdecoration ?decorationType? */
    case TM_GET_TEXT_DECORATION: /* GetTextDecoration */
    case TM_SET_TEXT_DECORATION: /* SetTextDecoration decorationType */
    {
	static CONST char *decoNames[] = {
	    "none", "underline", "overline", "linethrough",
	    (char *) NULL
	};
	static DecorationType decoTypes[] = {
	    NoDecoration, UnderlineDecoration, OverlineDecoration, LineThroughDecoration
	};
	int decoIdx;
	DecorationType deco;

	if( ((enum subIndex)index == TM_TEXT_DECORATION) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?decorationType?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_TEXT_DECORATION) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_TEXT_DECORATION) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "decorationType");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set antialias flag */
	    if (Tcl_GetIndexFromObj(interp, objv[2], decoNames, "decorationType", 0, &decoIdx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    DrawSetTextDecoration(wandPtr, decoTypes[decoIdx]);
	} else {    /* Get antialias flag */
	    deco = DrawGetTextDecoration(wandPtr);
	    for (decoIdx = 0; decoIdx < sizeof(decoTypes)/sizeof(decoTypes[0]); decoIdx++) {
		if( decoTypes[decoIdx] == deco ) {
		    Tcl_SetResult(interp, (char *)decoNames[decoIdx], TCL_VOLATILE);
		    return TCL_OK;
		}
	    }
	    Tcl_SetObjResult(interp, Tcl_NewIntObj((int)deco));
	}
	break;
    }

    case TM_TEXT_ENCODING:      /* textencoding ?string? */
    case TM_GET_TEXT_ENCODING:  /* GetTextEncoding */
    case TM_SET_TEXT_ENCODING:  /* SetTextEncoding string */
    {
	char *str;

	if( ((enum subIndex)index == TM_TEXT_ENCODING) && (objc > 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "?string?");
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_GET_TEXT_ENCODING) && (objc != 2) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	} else if( ((enum subIndex)index == TM_SET_TEXT_ENCODING) && (objc != 3) ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "string");
	    return TCL_ERROR;
	}
	if (objc == 3) { /* Set antialias flag */
	    str = Tcl_GetString(objv[2]);
	    DrawSetTextEncoding(wandPtr, str);
	} else {    /* Get antialias flag */
	    str = DrawGetTextEncoding(wandPtr);
	    Tcl_SetResult(interp, str, TCL_VOLATILE);
	    MagickRelinquishMemory(str);
	}
	break;
    }

    case TM_TRANSLATE:  /* translate x y */
    case TM_TTRANSLATE: /* Translate x y */
    {
	double x, y;

	if( objc != 4 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x y");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[2], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &y)) != TCL_OK ) {
	    return stat;
	}
	DrawTranslate(wandPtr, x, y);
	break;
    }

    case TM_VIEWBOX:        /* viewbox x1 y1 x2 y2 */
    case TM_SET_VIEWBOX:    /* SetViewbox x1 y1 x2 y2 */
    {
	unsigned long x1, y1, x2, y2;

	if( objc != 6 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "x1 y1 x2 y2");
	    return TCL_ERROR;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[2], &x1)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[3], &y1)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[4], &x2)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetLongFromObj(interp, objv[5], &y2)) != TCL_OK ) {
	    return stat;
	}
	DrawSetViewbox(wandPtr, x1, y1, x2, y2);
	break;
    }

    /****************************************************************
     * PUSH & POP COMMANDS
     ****************************************************************/
    case TM_PUSH_CLIPPATH: /* PushClipPath id */
    {
	char *id;

	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "id");
	    return TCL_ERROR;
	}
	id = Tcl_GetString(objv[2]);
	DrawPushClipPath(wandPtr, id);
	break;
    }

    case TM_PUSH_DEFS: /* PushDefs */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	DrawPushDefs(wandPtr);
	break;
    }

    case TM_PUSH_GRAPHIC_CTX: /* PushGraphicContext */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	DrawPushGraphicContext(wandPtr);
	break;
    }

    case TM_PUSH_PATTERN: /* PushPattern id x y width height */
    {
	char   *id;
	double x, y, width, height;

	if( objc != 7 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, "id x y width height");
	    return TCL_ERROR;
	}
	id = Tcl_GetString(objv[3]);
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[3], &x)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &y)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &width)) != TCL_OK ) {
	    return stat;
	}
	if( (stat = Tcl_GetDoubleFromObj(interp, objv[6], &height)) != TCL_OK ) {
	    return stat;
	}
	DrawPushPattern(wandPtr, id, x, y, width, height);
	break;
    }

    case TM_POP_CLIPPATH:       /* PopClipPath */
    case TM_POP_DEFS:           /* PopDefs */
    case TM_POP_GRAPHIC_CTX:    /* PopGraphicContext */
    case TM_POP_PATTERN:        /* PopPattern */
    {
	if( objc != 2 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	switch((enum subIndex)index) {
	case TM_POP_CLIPPATH:       DrawPopClipPath(wandPtr); break;
	case TM_POP_DEFS:           DrawPopDefs(wandPtr); break;
	case TM_POP_GRAPHIC_CTX:    DrawPopGraphicContext(wandPtr); break;
	case TM_POP_PATTERN:        DrawPopPattern(wandPtr); break;
	default: break;
	}
	break;
    }

    case TM_PUSH:   /* push what ?args? */
    {
	int what;

	if (Tcl_GetIndexFromObj(interp, objv[2], pushCmdNames, "what", 0, &what) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch((enum pushCmdIndex)what) {
	case TM_PUSH_CMD_CLIP: /* clippath */
	{
	    char *id;

	    if( objc != 4 ) {
		Tcl_WrongNumArgs(interp, 2, objv, "id");
		return TCL_ERROR;
	    }
	    id = Tcl_GetString(objv[3]);
	    DrawPushClipPath(wandPtr, id);
	    break;
	}
	case TM_PUSH_CMD_DEFS: /* defs */
	{
	    if( objc != 3 ) {
		Tcl_WrongNumArgs(interp, 2, objv, NULL);
		return TCL_ERROR;
	    }
	    DrawPushDefs(wandPtr);
	}
	case TM_PUSH_CMD_GRAPH: /* graphiccontext */
	{
	    if( objc != 3 ) {
		Tcl_WrongNumArgs(interp, 2, objv, NULL);
		return TCL_ERROR;
	    }
	    DrawPushGraphicContext(wandPtr);
	    break;
	}
	case TM_PUSH_CMD_PAT: /* pattern */
	{
	    char   *id;
	    double x, y, width, height;

	    if( objc != 8 ) {
		Tcl_WrongNumArgs(interp, 2, objv, "id x y width height");
		return TCL_ERROR;
	    }
	    id = Tcl_GetString(objv[3]);
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[4], &x)) != TCL_OK ) {
		return stat;
	    }
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[5], &y)) != TCL_OK ) {
		return stat;
	    }
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[6], &width)) != TCL_OK ) {
		return stat;
	    }
	    if( (stat = Tcl_GetDoubleFromObj(interp, objv[7], &height)) != TCL_OK ) {
		return stat;
	    }
	    DrawPushPattern(wandPtr, id, x, y, width, height);
	    break;
	}
	} /* switch(what) */
	break;
    }

    case TM_POP:   /* pop what */
    {
	int what;

	if (Tcl_GetIndexFromObj(interp, objv[2], pushCmdNames, "what", 0, &what) != TCL_OK) {
	    return TCL_ERROR;
	}
	if( objc != 3 ) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	switch((enum pushCmdIndex)what) {
	case TM_PUSH_CMD_CLIP:  DrawPopClipPath(wandPtr);       break;
	case TM_PUSH_CMD_DEFS:  DrawPopDefs(wandPtr);           break;
	case TM_PUSH_CMD_GRAPH: DrawPopGraphicContext(wandPtr); break;
	case TM_PUSH_CMD_PAT:   DrawPopPattern(wandPtr);        break;
	} /* switch(what) */
	break;
    }

    /****************************************************************
     * PATH COMMANDS
     ****************************************************************/
    case TM_PATH:   /* path -opt|cmd ?args? -opt|cmd ?args? */
    {
	static CONST char *pathCmdNames[] = {
	    "#",        "-relative",  "-smooth",
	    "close",    "cubic",      "elliptic",
	    "finish",   "horizontal", "line",
	    "move",     "quadratic",  "start",
	    "vertical",
	    (char *) NULL
	};
	enum pathCmdIndex {
	    TM_PATH_COMMENT,      TM_PATH_OPT_RELATIVE,   TM_PATH_OPT_SMOOTH,
	    TM_PATH_CMD_CLOSE,    TM_PATH_CMD_CUBIC,      TM_PATH_CMD_ELLIPTIC,
	    TM_PATH_CMD_FINISH,   TM_PATH_CMD_HORIZONTAL, TM_PATH_CMD_LINE,
	    TM_PATH_CMD_MOVE,     TM_PATH_CMD_QUADRATIC,  TM_PATH_CMD_START,
	    TM_PATH_CMD_VERTICAL,
	};
	int cmd, stat;
	int relFlag=0, smoothFlag=0;
	int argc;
	Tcl_Obj **argv;

	/*
	 * Two ways of calling '$draw path' command:
	 * 1. With many arguments:
	 *    $draw path start -relative on \
	 *         move 10 10   \
	 *         line 10 20   \
	 *         line 10 -20  \
	 *         close finish
	 * 2. With a single argument list
	 *    $draw path {
	 *         start -relative on
	 *         move 10 10
	 *         line 10 20
	 *         line 10 -20
	 *         close finish
	 *    }
	 */
	if( objc == 3 ) {
	    /*
	     * Single argument list
	     */
	    if( (stat = Tcl_ListObjGetElements(interp, objv[2], &argc, &argv) != TCL_OK) ) {
		return stat;
	    }
	} else {
	    argc = objc-2;
	    argv = (Tcl_Obj **)(objv+2);
	}
	while( argc > 0 ) {
	    if (Tcl_GetIndexFromObj(interp, argv[0], pathCmdNames, "option/command", 0, &cmd) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch((enum pathCmdIndex)cmd) {

	    case TM_PATH_COMMENT:  /* # comment */
		argc -= 2, argv += 2;
		break;

	    case TM_PATH_OPT_RELATIVE:  /* -relative boolean */
		if( argc < 2 ) {
		    Tcl_WrongNumArgs(interp, 1, argv, "boolean");
		    return TCL_ERROR;
		}
		if( (stat = Tcl_GetBooleanFromObj(interp, argv[1], &relFlag)) != TCL_OK) {
		    return stat;
		}
		argc -= 2, argv += 2;
		break;

	    case TM_PATH_OPT_SMOOTH:    /* -smooth boolean */
		if( argc < 2 ) {
		    Tcl_WrongNumArgs(interp, 1, argv, "boolean");
		    return TCL_ERROR;
		}
		if( (stat = Tcl_GetBooleanFromObj(interp, argv[1], &smoothFlag)) != TCL_OK) {
		    return stat;
		}
		argc -= 2, argv += 2;
		break;

	    case TM_PATH_CMD_CLOSE:     /* close */
		DrawPathClose(wandPtr);
		argc -= 1, argv += 1;
		break;

	    case TM_PATH_CMD_CUBIC:     /* cubic ?x1 y1? x2 y2 x y */
	    {
		double x1, y1, x2, y2, x, y;

		if( smoothFlag ) {
		    /*
		     * -smooth 1 cubic x2 y2 x y
		     */
		    if( argc < 5 ) {
			Tcl_WrongNumArgs(interp, 1, argv, "x2 y2 x y");
			return TCL_ERROR;
		    }
		    if(    ((stat = Tcl_GetDoubleFromObj(interp, argv[1], &x2)) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[2], &y2)) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[3], &x )) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[4], &y )) != TCL_OK) )
		    {
			Tcl_AppendResult(interp, "Smooth cubic bezier curve arguments: x2 y2 x y", NULL);
			return stat;
		    }
		    relFlag
			? DrawPathCurveToSmoothRelative(wandPtr, x2, y2, x, y)
			: DrawPathCurveToSmoothAbsolute(wandPtr, x2, y2, x, y);

		    argc -= 5, argv += 5;
		} else {
		    /*
		     * -smooth 0 cubic x1 y1 x2 y2 x y
		     */
		    if( argc < 7 ) {
			Tcl_WrongNumArgs(interp, 1, argv, "x1 y1 x2 y2 x y");
			return TCL_ERROR;
		    }
		    if(    ((stat = Tcl_GetDoubleFromObj(interp, argv[1], &x1)) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[2], &y1)) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[3], &x2)) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[4], &y2)) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[5], &x )) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[6], &y )) != TCL_OK) )
		    {
			Tcl_AppendResult(interp, "Cubic bezier curve arguments: x1 y1 x2 y2 x y", NULL);
			return stat;
		    }
		    relFlag
			? DrawPathCurveToRelative(wandPtr, x1, y1, x2, y2, x, y)
			: DrawPathCurveToAbsolute(wandPtr, x1, y1, x2, y2, x, y);

		    argc -= 7, argv += 7;
		}
		break;
	    }

	    case TM_PATH_CMD_ELLIPTIC:  /* elliptic rx ry rotation large sweep x y */
	    {
		double      rx, ry, rot, x, y;
		unsigned    large, sweep;

		if( argc < 8 ) {
		    Tcl_WrongNumArgs(interp, 1, argv, "rx ry rotation large sweep x y");
		    return TCL_ERROR;
		}
		if(    ((stat = Tcl_GetDoubleFromObj(interp,  argv[1], &rx )) != TCL_OK)
		       || ((stat = Tcl_GetDoubleFromObj(interp,  argv[2], &ry )) != TCL_OK)
		       || ((stat = Tcl_GetDoubleFromObj(interp,  argv[3], &rot)) != TCL_OK)
		       || ((stat = Tcl_GetBooleanFromObj(interp, argv[4], &large )) != TCL_OK)
		       || ((stat = Tcl_GetBooleanFromObj(interp, argv[5], &sweep )) != TCL_OK)
		       || ((stat = Tcl_GetDoubleFromObj(interp,  argv[6], &x  )) != TCL_OK)
		       || ((stat = Tcl_GetDoubleFromObj(interp,  argv[7], &y  )) != TCL_OK) )
		{
		    Tcl_AppendResult(interp, "Elliptic arc arguments: rx ry rotation large sweep x y", NULL);
		    return stat;
		}
		relFlag
		    ? DrawPathEllipticArcRelative(wandPtr, rx, ry, rot, large, sweep, x, y)
		    : DrawPathEllipticArcAbsolute(wandPtr, rx, ry, rot, large, sweep, x, y);

		argc -= 8, argv += 8;
		break;
	    }

	    case TM_PATH_CMD_FINISH:     /* finish */
		DrawPathFinish(wandPtr);
		argc -= 1, argv += 1;
		break;

	    case TM_PATH_CMD_HORIZONTAL:  /* horizontal x */
	    {
		double x;

		if( argc < 2 ) {
		    Tcl_WrongNumArgs(interp, 1, argv, "x");
		    return TCL_ERROR;
		}
		if( (stat = Tcl_GetDoubleFromObj(interp, argv[1], &x)) != TCL_OK) {
		    Tcl_AppendResult(interp, "Horizonal line argument: x", NULL);
		    return stat;
		}
		relFlag
		    ? DrawPathLineToHorizontalRelative(wandPtr, x)
		    : DrawPathLineToHorizontalAbsolute(wandPtr, x);

		argc -= 2, argv += 2;
		break;
	    }

	    case TM_PATH_CMD_LINE:  /* line x y */
	    {
		double x, y;

		if( argc < 3 ) {
		    Tcl_WrongNumArgs(interp, 1, argv, "x y");
		    return TCL_ERROR;
		}
		if(    ((stat = Tcl_GetDoubleFromObj(interp, argv[1], &x )) != TCL_OK)
		       || ((stat = Tcl_GetDoubleFromObj(interp, argv[2], &y )) != TCL_OK) )
		{
		    Tcl_AppendResult(interp, "Line arguments: x y", NULL);
		    return stat;
		}
		relFlag
		    ? DrawPathLineToRelative(wandPtr, x, y)
		    : DrawPathLineToAbsolute(wandPtr, x, y);

		argc -= 3, argv += 3;
		break;
	    }

	    case TM_PATH_CMD_MOVE:  /* move {x y} */
	    {
		double x, y;

		if( argc < 3 ) {
		    Tcl_WrongNumArgs(interp, 1, argv, "x y");
		    return TCL_ERROR;
		}
		if(    ((stat = Tcl_GetDoubleFromObj(interp, argv[1], &x )) != TCL_OK)
		       || ((stat = Tcl_GetDoubleFromObj(interp, argv[2], &y )) != TCL_OK) )
		{
		    Tcl_AppendResult(interp, "Line arguments: x y", NULL);
		    return stat;
		}
		relFlag
		    ? DrawPathMoveToRelative(wandPtr, x, y)
		    : DrawPathMoveToAbsolute(wandPtr, x, y);

		argc -= 3, argv += 3;
		break;
	    }

	    case TM_PATH_CMD_QUADRATIC:     /* quadratic ?x1 y1? x y */
	    {
		double x1, y1, x, y;

		if( smoothFlag ) {
		    /*
		     * -smooth 1 quadratic x y
		     */
		    if( argc < 3 ) {
			Tcl_WrongNumArgs(interp, 1, argv, "x y");
			return TCL_ERROR;
		    }
		    if(    ((stat = Tcl_GetDoubleFromObj(interp, argv[1], &x )) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[2], &y )) != TCL_OK) )
		    {
			Tcl_AppendResult(interp, "Smooth quadratic bezier curve arguments: x y", NULL);
			return stat;
		    }
		    relFlag
			? DrawPathCurveToQuadraticBezierSmoothRelative(wandPtr, x, y)
			: DrawPathCurveToQuadraticBezierSmoothAbsolute(wandPtr, x, y);

		    argc -= 3, argv += 3;
		} else {
		    /*
		     * -smooth 0 quadratic x1 y1 x y
		     */
		    if( argc < 5 ) {
			Tcl_WrongNumArgs(interp, 1, argv, "x2 y2 x y");
			return TCL_ERROR;
		    }
		    if(    ((stat = Tcl_GetDoubleFromObj(interp, argv[1], &x1)) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[2], &y1)) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[3], &x )) != TCL_OK)
			   || ((stat = Tcl_GetDoubleFromObj(interp, argv[4], &y )) != TCL_OK) )
		    {
			Tcl_AppendResult(interp, "Quadratic bezier curve arguments: x1 y1 x y", NULL);
			return stat;
		    }
		    relFlag
			? DrawPathCurveToQuadraticBezierRelative(wandPtr, x1, y1, x, y)
			: DrawPathCurveToQuadraticBezierAbsolute(wandPtr, x1, y1, x, y);

		    argc -= 5, argv += 5;
		}
		break;
	    }

	    case TM_PATH_CMD_START:     /* start */
		DrawPathStart(wandPtr);
		argc -= 1, argv += 1;
		break;

	    case TM_PATH_CMD_VERTICAL:  /* vertical {y} */
	    {
		double y;

		if( argc < 2 ) {
		    Tcl_WrongNumArgs(interp, 1, argv, "y");
		    return TCL_ERROR;
		}
		if( (stat = Tcl_GetDoubleFromObj(interp, argv[1], &y)) != TCL_OK) {
		    Tcl_AppendResult(interp, "Horizonal line argument: y", NULL);
		    return stat;
		}
		relFlag
		    ? DrawPathLineToVerticalRelative(wandPtr, y)
		    : DrawPathLineToVerticalAbsolute(wandPtr, y);

		argc -= 2, argv += 2;
		break;
	    }

	    } /* switch( path-cmd) */
	}
	break; /* path */
    }

    /*
     * All subcommands should be matched
     * A DEFAULT or TM_END_OF_TABLE would be a serious fault
     */
    case TM_END_OF_TABLE:
    default:
    {
	Tcl_AppendResult(interp, "TclMagick drawObjCmd: Unmatched subcommand table entry", NULL);
	return TCL_ERROR;
    }
    } /* switch(index) */

    return(TCL_OK);
}

/*----------------------------------------------------------------------
 *
 * Tclmagick_Init --
 *
 *      Initialize TclMagick module, called from [load TclMagick.dll]
 * Results:
 *          TCL_OK
 *          TCL_ERROR
 *
 * Side effects:
 *      Installs exit handler
 *----------------------------------------------------------------------
 */
static void tmExitHandler(
    ClientData  data )      // Tcl Interpreter which is exiting
{
    if ( TM.initialized ) {
        DestroyMagick();
        TM.initialized = 0;
    }
}

EXPORT(int, Tclmagick_Init)(Tcl_Interp *interp)
{
#ifdef USE_TCL_STUBS
    if (Tcl_InitStubs(interp, "8", 0) == NULL) {
	return TCL_ERROR;
    }
#endif
    /*
     * Initialize global variables
     */
    if ( ! TM.initialized ) {
        memset(&TM, 0, sizeof(TM));

        /*
         * Create Exit handler, hash table
         */
        Tcl_CreateExitHandler(tmExitHandler,(int *) interp);
        Tcl_InitHashTable(&TM.hashTable, TCL_STRING_KEYS);
        InitializeMagick(Tcl_GetString(Tcl_FSGetCwd(interp)));

        TM.initialized = 1;
    }
    /*
     * Create commands per interpreter
     */
    Tcl_CreateObjCommand(interp, "magick",  magickCmd,  NULL, NULL);

    if ( Tcl_PkgProvide(interp,"TclMagick", VERSION) != TCL_OK ) {
        return TCL_ERROR;
    }

    return TCL_OK;
}

EXPORT(int, Tclmagick_SafeInit)(Tcl_Interp *interp)
{
    return Tclmagick_Init(interp);
}

