📄 tkimgphoto.c
字号:
* * Side effects: * The data structure for a new photo image is allocated and * initialized. * *---------------------------------------------------------------------- */static intImgPhotoCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) Tcl_Interp *interp; /* Interpreter for application containing * image. */ char *name; /* Name to use for image. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings for options (doesn't * include image name or type). */ Tk_ImageType *typePtr; /* Pointer to our type record (not used). */ Tk_ImageMaster master; /* Token for image, to be used by us in * later callbacks. */ ClientData *clientDataPtr; /* Store manager's token for image here; * it will be returned in later callbacks. */{ PhotoMaster *masterPtr; /* * Allocate and initialize the photo image master record. */ masterPtr = (PhotoMaster *) ckalloc(sizeof(PhotoMaster)); memset((void *) masterPtr, 0, sizeof(PhotoMaster)); masterPtr->tkMaster = master; masterPtr->interp = interp; masterPtr->imageCmd = Tcl_CreateCommand(interp, name, ImgPhotoCmd, (ClientData) masterPtr, ImgPhotoCmdDeletedProc); masterPtr->palette = NULL; masterPtr->pix24 = NULL; masterPtr->instancePtr = NULL; masterPtr->validRegion = TkCreateRegion(); /* * Process configuration options given in the image create command. */ if (ImgPhotoConfigureMaster(interp, masterPtr, argc, argv, 0) != TCL_OK) { ImgPhotoDelete((ClientData) masterPtr); return TCL_ERROR; } *clientDataPtr = (ClientData) masterPtr; return TCL_OK;}/* *---------------------------------------------------------------------- * * ImgPhotoCmd -- * * This procedure is invoked to process the Tcl command that * corresponds to a photo image. See the user documentation * for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */static intImgPhotoCmd(clientData, interp, argc, argv) ClientData clientData; /* Information about photo master. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ PhotoMaster *masterPtr = (PhotoMaster *) clientData; int c, result, index; int x, y, width, height; int dataWidth, dataHeight; struct SubcommandOptions options; int listArgc; char **listArgv; char **srcArgv; unsigned char *pixelPtr; Tk_PhotoImageBlock block; Tk_Window tkwin; char string[16]; XColor color; Tk_PhotoImageFormat *imageFormat; int imageWidth, imageHeight; int matched; Tcl_Channel chan; Tk_PhotoHandle srcHandle; size_t length; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option ?arg arg ...?\"", (char *) NULL); return TCL_ERROR; } c = argv[1][0]; length = strlen(argv[1]); if ((c == 'b') && (strncmp(argv[1], "blank", length) == 0)) { /* * photo blank command - just call Tk_PhotoBlank. */ if (argc == 2) { Tk_PhotoBlank(masterPtr); } else { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " blank\"", (char *) NULL); return TCL_ERROR; } } else if ((c == 'c') && (length >= 2) && (strncmp(argv[1], "cget", length) == 0)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " cget option\"", (char *) NULL); return TCL_ERROR; } Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs, (char *) masterPtr, argv[2], 0); } else if ((c == 'c') && (length >= 3) && (strncmp(argv[1], "configure", length) == 0)) { /* * photo configure command - handle this in the standard way. */ if (argc == 2) { return Tk_ConfigureInfo(interp, Tk_MainWindow(interp), configSpecs, (char *) masterPtr, (char *) NULL, 0); } if (argc == 3) { return Tk_ConfigureInfo(interp, Tk_MainWindow(interp), configSpecs, (char *) masterPtr, argv[2], 0); } return ImgPhotoConfigureMaster(interp, masterPtr, argc-2, argv+2, TK_CONFIG_ARGV_ONLY); } else if ((c == 'c') && (length >= 3) && (strncmp(argv[1], "copy", length) == 0)) { /* * photo copy command - first parse options. */ index = 2; memset((VOID *) &options, 0, sizeof(options)); options.zoomX = options.zoomY = 1; options.subsampleX = options.subsampleY = 1; options.name = NULL; if (ParseSubcommandOptions(&options, interp, OPT_FROM | OPT_TO | OPT_ZOOM | OPT_SUBSAMPLE | OPT_SHRINK, &index, argc, argv) != TCL_OK) { return TCL_ERROR; } if (options.name == NULL || index < argc) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " copy source-image ?-from x1 y1 x2 y2?", " ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?", "\"", (char *) NULL); return TCL_ERROR; } /* * Look for the source image and get a pointer to its image data. * Check the values given for the -from option. */ if ((srcHandle = Tk_FindPhoto(interp, options.name)) == NULL) { Tcl_AppendResult(interp, "image \"", argv[2], "\" doesn't", " exist or is not a photo image", (char *) NULL); return TCL_ERROR; } Tk_PhotoGetImage(srcHandle, &block); if ((options.fromX2 > block.width) || (options.fromY2 > block.height) || (options.fromX2 > block.width) || (options.fromY2 > block.height)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", "outside source image", (char *) NULL); return TCL_ERROR; } /* * Fill in default values for unspecified parameters. */ if (((options.options & OPT_FROM) == 0) || (options.fromX2 < 0)) { options.fromX2 = block.width; options.fromY2 = block.height; } if (((options.options & OPT_TO) == 0) || (options.toX2 < 0)) { width = options.fromX2 - options.fromX; if (options.subsampleX > 0) { width = (width + options.subsampleX - 1) / options.subsampleX; } else if (options.subsampleX == 0) { width = 0; } else { width = (width - options.subsampleX - 1) / -options.subsampleX; } options.toX2 = options.toX + width * options.zoomX; height = options.fromY2 - options.fromY; if (options.subsampleY > 0) { height = (height + options.subsampleY - 1) / options.subsampleY; } else if (options.subsampleY == 0) { height = 0; } else { height = (height - options.subsampleY - 1) / -options.subsampleY; } options.toY2 = options.toY + height * options.zoomY; } /* * Set the destination image size if the -shrink option was specified. */ if (options.options & OPT_SHRINK) { ImgPhotoSetSize(masterPtr, options.toX2, options.toY2); } /* * Copy the image data over using Tk_PhotoPutZoomedBlock. */ block.pixelPtr += options.fromX * block.pixelSize + options.fromY * block.pitch; block.width = options.fromX2 - options.fromX; block.height = options.fromY2 - options.fromY; Tk_PhotoPutZoomedBlock((Tk_PhotoHandle) masterPtr, &block, options.toX, options.toY, options.toX2 - options.toX, options.toY2 - options.toY, options.zoomX, options.zoomY, options.subsampleX, options.subsampleY); } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) { /* * photo get command - first parse and check parameters. */ if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " get x y\"", (char *) NULL); return TCL_ERROR; } if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) { return TCL_ERROR; } if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { Tcl_AppendResult(interp, argv[0], " get: ", "coordinates out of range", (char *) NULL); return TCL_ERROR; } /* * Extract the value of the desired pixel and format it as a string. */ pixelPtr = masterPtr->pix24 + (y * masterPtr->width + x) * 3; sprintf(string, "%d %d %d", pixelPtr[0], pixelPtr[1], pixelPtr[2]); Tcl_AppendResult(interp, string, (char *) NULL); } else if ((c == 'p') && (strncmp(argv[1], "put", length) == 0)) { /* * photo put command - first parse the options and colors specified. */ index = 2; memset((VOID *) &options, 0, sizeof(options)); options.name = NULL; if (ParseSubcommandOptions(&options, interp, OPT_TO, &index, argc, argv) != TCL_OK) { return TCL_ERROR; } if ((options.name == NULL) || (index < argc)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " put {{colors...}...} ?-to x1 y1 x2 y2?\"", (char *) NULL); return TCL_ERROR; } if (Tcl_SplitList(interp, options.name, &dataHeight, &srcArgv) != TCL_OK) { return TCL_ERROR; } tkwin = Tk_MainWindow(interp); block.pixelPtr = NULL; dataWidth = 0; pixelPtr = NULL; for (y = 0; y < dataHeight; ++y) { if (Tcl_SplitList(interp, srcArgv[y], &listArgc, &listArgv) != TCL_OK) { break; } if (y == 0) { dataWidth = listArgc; pixelPtr = (unsigned char *) ckalloc((unsigned) dataWidth * dataHeight * 3); block.pixelPtr = pixelPtr; } else { if (listArgc != dataWidth) { Tcl_AppendResult(interp, "all elements of color list must", " have the same number of elements", (char *) NULL); ckfree((char *) listArgv); break; } } for (x = 0; x < dataWidth; ++x) { if (!XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), listArgv[x], &color)) { Tcl_AppendResult(interp, "can't parse color \"", listArgv[x], "\"", (char *) NULL); break; } *pixelPtr++ = color.red >> 8; *pixelPtr++ = color.green >> 8; *pixelPtr++ = color.blue >> 8; } ckfree((char *) listArgv); if (x < dataWidth) break; } ckfree((char *) srcArgv); if (y < dataHeight || dataHeight == 0 || dataWidth == 0) { if (block.pixelPtr != NULL) { ckfree((char *) block.pixelPtr); } if (y < dataHeight) { return TCL_ERROR; } return TCL_OK; } /* * Fill in default values for the -to option, then * copy the block in using Tk_PhotoPutBlock. */ if (((options.options & OPT_TO) == 0) || (options.toX2 < 0)) { options.toX2 = options.toX + dataWidth; options.toY2 = options.toY + dataHeight; } block.width = dataWidth; block.height = dataHeight; block.pitch = dataWidth * 3; block.pixelSize = 3; block.offset[0] = 0; block.offset[1] = 1; block.offset[2] = 2; Tk_PhotoPutBlock((ClientData)masterPtr, &block, options.toX, options.toY, options.toX2 - options.toX, options.toY2 - options.toY); ckfree((char *) block.pixelPtr); } else if ((c == 'r') && (length >= 3) && (strncmp(argv[1], "read", length) == 0)) { /* * photo read command - first parse the options specified. */ index = 2; memset((VOID *) &options, 0, sizeof(options)); options.name = NULL; options.format = NULL; if (ParseSubcommandOptions(&options, interp, OPT_FORMAT | OPT_FROM | OPT_TO | OPT_SHRINK, &index, argc, argv) != TCL_OK) { return TCL_ERROR; } if ((options.name == NULL) || (index < argc)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " read fileName ?-format format-name?", " ?-from x1 y1 x2 y2? ?-to x y? ?-shrink?\"", (char *) NULL); return TCL_ERROR; } /* * Prevent file system access in safe interpreters. */ if (Tcl_IsSafe(interp)) { Tcl_AppendResult(interp, "can't get image from a file in a", " safe interpreter", (char *) NULL); return TCL_ERROR; } /* * Open the image file and look for a handler for it. */ chan = Tcl_OpenFileChannel(interp, options.name, "r", 0); if (chan == NULL) { return TCL_ERROR; } if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) { return TCL_ERROR; } if (MatchFileFormat(interp, chan, options.name, options.format, &imageFormat, &imageWidth, &imageHeight) != TCL_OK) { Tcl_Close(NULL, chan); return TCL_ERROR; } /* * Check the values given for the -from option. */ if ((options.fromX > imageWidth) || (options.fromY > imageHeight) || (options.fromX2 > imageWidth) || (options.fromY2 > imageHeight)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", "outside source image", (char *) NULL); Tcl_Close(NULL, chan); return TCL_ERROR; } if (((options.options & OPT_FROM) == 0) || (options.fromX2 < 0)) { width = imageWidth - options.fromX; height = imageHeight - options.fromY; } else { width = options.fromX2 - options.fromX; height = options.fromY2 - options.fromY; } /* * If the -shrink option was specified, set the size of the image. */ if (options.options & OPT_SHRINK) { ImgPhotoSetSize(masterPtr, options.toX + width,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -