📄 tkimgphoto.c
字号:
/* * tkImgPhoto.c -- * * Implements images of type "photo" for Tk. Photo images are * stored in full color (24 bits per pixel) and displayed using * dithering if necessary. * * Copyright (c) 1994 The Australian National University. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Author: Paul Mackerras (paulus@cs.anu.edu.au), * Department of Computer Science, * Australian National University. * * SCCS: @(#) tkImgPhoto.c 1.60 97/08/08 11:32:46 */#include "tkInt.h"#include "tkPort.h"#include "tclMath.h"#include <ctype.h>/* * Declaration for internal Xlib function used here: */extern _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image));/* * A signed 8-bit integral type. If chars are unsigned and the compiler * isn't an ANSI one, then we have to use short instead (which wastes * space) to get signed behavior. */#if defined(__STDC__) || defined(_AIX) typedef signed char schar;#else# ifndef __CHAR_UNSIGNED__ typedef char schar;# else typedef short schar;# endif#endif/* * An unsigned 32-bit integral type, used for pixel values. * We use int rather than long here to accommodate those systems * where longs are 64 bits. */typedef unsigned int pixel;/* * The maximum number of pixels to transmit to the server in a * single XPutImage call. */#define MAX_PIXELS 65536/* * The set of colors required to display a photo image in a window depends on: * - the visual used by the window * - the palette, which specifies how many levels of each primary * color to use, and * - the gamma value for the image. * * Pixel values allocated for specific colors are valid only for the * colormap in which they were allocated. Sets of pixel values * allocated for displaying photos are re-used in other windows if * possible, that is, if the display, colormap, palette and gamma * values match. A hash table is used to locate these sets of pixel * values, using the following data structure as key: */typedef struct { Display *display; /* Qualifies the colormap resource ID */ Colormap colormap; /* Colormap that the windows are using. */ double gamma; /* Gamma exponent value for images. */ Tk_Uid palette; /* Specifies how many shades of each primary * we want to allocate. */} ColorTableId;/* * For a particular (display, colormap, palette, gamma) combination, * a data structure of the following type is used to store the allocated * pixel values and other information: */typedef struct ColorTable { ColorTableId id; /* Information used in selecting this * color table. */ int flags; /* See below. */ int refCount; /* Number of instances using this map. */ int liveRefCount; /* Number of instances which are actually * in use, using this map. */ int numColors; /* Number of colors allocated for this map. */ XVisualInfo visualInfo; /* Information about the visual for windows * using this color table. */ pixel redValues[256]; /* Maps 8-bit values of red intensity * to a pixel value or index in pixelMap. */ pixel greenValues[256]; /* Ditto for green intensity */ pixel blueValues[256]; /* Ditto for blue intensity */ unsigned long *pixelMap; /* Actual pixel values allocated. */ unsigned char colorQuant[3][256]; /* Maps 8-bit intensities to quantized * intensities. The first index is 0 for * red, 1 for green, 2 for blue. */} ColorTable;/* * Bit definitions for the flags field of a ColorTable. * BLACK_AND_WHITE: 1 means only black and white colors are * available. * COLOR_WINDOW: 1 means a full 3-D color cube has been * allocated. * DISPOSE_PENDING: 1 means a call to DisposeColorTable has * been scheduled as an idle handler, but it * hasn't been invoked yet. * MAP_COLORS: 1 means pixel values should be mapped * through pixelMap. */#define BLACK_AND_WHITE 1#define COLOR_WINDOW 2#define DISPOSE_PENDING 4#define MAP_COLORS 8/* * Definition of the data associated with each photo image master. */typedef struct PhotoMaster { Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means * the image is being deleted. */ Tcl_Interp *interp; /* Interpreter associated with the * application using this image. */ Tcl_Command imageCmd; /* Token for image command (used to delete * it when the image goes away). NULL means * the image command has already been * deleted. */ int flags; /* Sundry flags, defined below. */ int width, height; /* Dimensions of image. */ int userWidth, userHeight; /* User-declared image dimensions. */ Tk_Uid palette; /* User-specified default palette for * instances of this image. */ double gamma; /* Display gamma value to correct for. */ char *fileString; /* Name of file to read into image. */ char *dataString; /* String value to use as contents of image. */ char *format; /* User-specified format of data in image * file or string value. */ unsigned char *pix24; /* Local storage for 24-bit image. */ int ditherX, ditherY; /* Location of first incorrectly * dithered pixel in image. */ TkRegion validRegion; /* Tk region indicating which parts of * the image have valid image data. */ struct PhotoInstance *instancePtr; /* First in the list of instances * associated with this master. */} PhotoMaster;/* * Bit definitions for the flags field of a PhotoMaster. * COLOR_IMAGE: 1 means that the image has different color * components. * IMAGE_CHANGED: 1 means that the instances of this image * need to be redithered. */#define COLOR_IMAGE 1#define IMAGE_CHANGED 2/* * The following data structure represents all of the instances of * a photo image in windows on a given screen that are using the * same colormap. */typedef struct PhotoInstance { PhotoMaster *masterPtr; /* Pointer to master for image. */ Display *display; /* Display for windows using this instance. */ Colormap colormap; /* The image may only be used in windows with * this particular colormap. */ struct PhotoInstance *nextPtr; /* Pointer to the next instance in the list * of instances associated with this master. */ int refCount; /* Number of instances using this structure. */ Tk_Uid palette; /* Palette for these particular instances. */ double gamma; /* Gamma value for these instances. */ Tk_Uid defaultPalette; /* Default palette to use if a palette * is not specified for the master. */ ColorTable *colorTablePtr; /* Pointer to information about colors * allocated for image display in windows * like this one. */ Pixmap pixels; /* X pixmap containing dithered image. */ int width, height; /* Dimensions of the pixmap. */ schar *error; /* Error image, used in dithering. */ XImage *imagePtr; /* Image structure for converted pixels. */ XVisualInfo visualInfo; /* Information about the visual that these * windows are using. */ GC gc; /* Graphics context for writing images * to the pixmap. */} PhotoInstance;/* * The following data structure is used to return information * from ParseSubcommandOptions: */struct SubcommandOptions { int options; /* Individual bits indicate which * options were specified - see below. */ char *name; /* Name specified without an option. */ int fromX, fromY; /* Values specified for -from option. */ int fromX2, fromY2; /* Second coordinate pair for -from option. */ int toX, toY; /* Values specified for -to option. */ int toX2, toY2; /* Second coordinate pair for -to option. */ int zoomX, zoomY; /* Values specified for -zoom option. */ int subsampleX, subsampleY; /* Values specified for -subsample option. */ char *format; /* Value specified for -format option. */};/* * Bit definitions for use with ParseSubcommandOptions: * Each bit is set in the allowedOptions parameter on a call to * ParseSubcommandOptions if that option is allowed for the current * photo image subcommand. On return, the bit is set in the options * field of the SubcommandOptions structure if that option was specified. * * OPT_FORMAT: Set if -format option allowed/specified. * OPT_FROM: Set if -from option allowed/specified. * OPT_SHRINK: Set if -shrink option allowed/specified. * OPT_SUBSAMPLE: Set if -subsample option allowed/spec'd. * OPT_TO: Set if -to option allowed/specified. * OPT_ZOOM: Set if -zoom option allowed/specified. */#define OPT_FORMAT 1#define OPT_FROM 2#define OPT_SHRINK 4#define OPT_SUBSAMPLE 8#define OPT_TO 0x10#define OPT_ZOOM 0x20/* * List of option names. The order here must match the order of * declarations of the OPT_* constants above. */static char *optionNames[] = { "-format", "-from", "-shrink", "-subsample", "-to", "-zoom", (char *) NULL};/* * The type record for photo images: */static int ImgPhotoCreate _ANSI_ARGS_((Tcl_Interp *interp, char *name, int argc, char **argv, Tk_ImageType *typePtr, Tk_ImageMaster master, ClientData *clientDataPtr));static ClientData ImgPhotoGet _ANSI_ARGS_((Tk_Window tkwin, ClientData clientData));static void ImgPhotoDisplay _ANSI_ARGS_((ClientData clientData, Display *display, Drawable drawable, int imageX, int imageY, int width, int height, int drawableX, int drawableY));static void ImgPhotoFree _ANSI_ARGS_((ClientData clientData, Display *display));static void ImgPhotoDelete _ANSI_ARGS_((ClientData clientData));Tk_ImageType tkPhotoImageType = { "photo", /* name */ ImgPhotoCreate, /* createProc */ ImgPhotoGet, /* getProc */ ImgPhotoDisplay, /* displayProc */ ImgPhotoFree, /* freeProc */ ImgPhotoDelete, /* deleteProc */ (Tk_ImageType *) NULL /* nextPtr */};/* * Default configuration */#define DEF_PHOTO_GAMMA "1"#define DEF_PHOTO_HEIGHT "0"#define DEF_PHOTO_PALETTE ""#define DEF_PHOTO_WIDTH "0"/* * Information used for parsing configuration specifications: */static Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_STRING, "-data", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(PhotoMaster, dataString), TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-format", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(PhotoMaster, format), TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK}, {TK_CONFIG_DOUBLE, "-gamma", (char *) NULL, (char *) NULL, DEF_PHOTO_GAMMA, Tk_Offset(PhotoMaster, gamma), 0}, {TK_CONFIG_INT, "-height", (char *) NULL, (char *) NULL, DEF_PHOTO_HEIGHT, Tk_Offset(PhotoMaster, userHeight), 0}, {TK_CONFIG_UID, "-palette", (char *) NULL, (char *) NULL, DEF_PHOTO_PALETTE, Tk_Offset(PhotoMaster, palette), 0}, {TK_CONFIG_INT, "-width", (char *) NULL, (char *) NULL, DEF_PHOTO_WIDTH, Tk_Offset(PhotoMaster, userWidth), 0}, {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, 0}};/* * Hash table used to hash from (display, colormap, palette, gamma) * to ColorTable address. */static Tcl_HashTable imgPhotoColorHash;static int imgPhotoColorHashInitialized;#define N_COLOR_HASH (sizeof(ColorTableId) / sizeof(int))/* * Pointer to the first in the list of known photo image formats. */static Tk_PhotoImageFormat *formatList = NULL;/* * Forward declarations */static int ImgPhotoCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv));static int ParseSubcommandOptions _ANSI_ARGS_(( struct SubcommandOptions *optPtr, Tcl_Interp *interp, int allowedOptions, int *indexPtr, int argc, char **argv));static void ImgPhotoCmdDeletedProc _ANSI_ARGS_(( ClientData clientData));static int ImgPhotoConfigureMaster _ANSI_ARGS_(( Tcl_Interp *interp, PhotoMaster *masterPtr, int argc, char **argv, int flags));static void ImgPhotoConfigureInstance _ANSI_ARGS_(( PhotoInstance *instancePtr));static void ImgPhotoSetSize _ANSI_ARGS_((PhotoMaster *masterPtr, int width, int height));static void ImgPhotoInstanceSetSize _ANSI_ARGS_(( PhotoInstance *instancePtr));static int IsValidPalette _ANSI_ARGS_((PhotoInstance *instancePtr, char *palette));static int CountBits _ANSI_ARGS_((pixel mask));static void GetColorTable _ANSI_ARGS_((PhotoInstance *instancePtr));static void FreeColorTable _ANSI_ARGS_((ColorTable *colorPtr));static void AllocateColors _ANSI_ARGS_((ColorTable *colorPtr));static void DisposeColorTable _ANSI_ARGS_((ClientData clientData));static void DisposeInstance _ANSI_ARGS_((ClientData clientData));static int ReclaimColors _ANSI_ARGS_((ColorTableId *id, int numColors));static int MatchFileFormat _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Channel chan, char *fileName, char *formatString, Tk_PhotoImageFormat **imageFormatPtr, int *widthPtr, int *heightPtr));static int MatchStringFormat _ANSI_ARGS_((Tcl_Interp *interp, char *string, char *formatString, Tk_PhotoImageFormat **imageFormatPtr, int *widthPtr, int *heightPtr));static void Dither _ANSI_ARGS_((PhotoMaster *masterPtr, int x, int y, int width, int height));static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr, int x, int y, int width, int height));#undef MIN#define MIN(a, b) ((a) < (b)? (a): (b))#undef MAX#define MAX(a, b) ((a) > (b)? (a): (b))/* *---------------------------------------------------------------------- * * Tk_CreatePhotoImageFormat -- * * This procedure is invoked by an image file handler to register * a new photo image format and the procedures that handle the * new format. The procedure is typically invoked during * Tcl_AppInit. * * Results: * None. * * Side effects: * The new image file format is entered into a table used in the * photo image "read" and "write" subcommands. * *---------------------------------------------------------------------- */voidTk_CreatePhotoImageFormat(formatPtr) Tk_PhotoImageFormat *formatPtr; /* Structure describing the format. All of * the fields except "nextPtr" must be filled * in by caller. Must not have been passed * to Tk_CreatePhotoImageFormat previously. */{ Tk_PhotoImageFormat *copyPtr; copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat)); *copyPtr = *formatPtr; copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1)); strcpy(copyPtr->name, formatPtr->name); copyPtr->nextPtr = formatList; formatList = copyPtr;}/* *---------------------------------------------------------------------- * * ImgPhotoCreate -- * * This procedure is called by the Tk image code to create * a new photo image. * * Results: * A standard Tcl result.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -