Logo Search packages:      
Sourcecode: tclmagick version File versions  Download package

TclMagick.c

/**********************************************************************
 * 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.32 2005/01/22 18:30:09 schroedt 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);
}


Generated by  Doxygen 1.6.0   Back to index