1 /******************************************************************************
2 * $Id: fgisPalette.c,v 1.2 2003-01-07 10:59:52 dron Exp $
4 * Project: fGIS core engine
5 * Purpose: palette handling
7 ******************************************************************************
9 * Copyright (C) 1997, Victor Wagner <vitus@ice.ru>
10 * Copyright (C) 2003, Andrey Kiselev <dron@remotesensing.org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26 *****************************************************************************
40 *# Default palette array
42 static int defarray[]={
46 static PALETTE default_palette=defarray;
48 * Creates new palette. Optionally fills from existing palette. If no existing
49 * palette supplied, all colors will be white
52 PALETTE new_palette(PALETTE copy_from)
53 { PALETTE new_p= (PALETTE)Tcl_Alloc(256*sizeof(int));
55 memcpy(new_p,copy_from,256*sizeof(int));
58 for (i=0,c=new_p;i<256;i++)
64 * Parses string, containing pallette in EPPL7 file format EPPL7
66 PALETTE parse_palette(Tcl_Interp *interp,char *string)
69 char *start=string,*end, line[80];
70 pal=new_palette(default_palette);
71 /* ASSIGNMENT INSIDE IF */
72 while (( end=strchr(start,'\n'))) {
74 if (n==0) continue; /*won't bother with empty lines */
76 strncpy(line,start,n);
78 if (sscanf(line,"%d %d %d %d",&index,&r,&g,&b)!=4) {
79 Tcl_Free((char *)pal);
82 if (index>255||index<0)
84 pal[index]=(r*255/1000)<<16|(g*255/1000)<<8|(b*255/1000);
89 * Returns index entry of palette in form #RRGGBB
94 char *Xcolor_string(PALETTE palette,int index)
96 static char buffer[24];
97 if(index>=0&&index<255)
101 sprintf(buffer,"#%06x",value);
105 * parses RGB specification in form #RRGGBB.
106 * Returns integer value or 0x1000000 in case of error.
108 int ParseRGB(Tcl_Interp *interp,char *spec)
109 { int val;char *endptr;
110 val= strtol(spec+1,&endptr,16);
111 if ((*endptr)||(spec[0]!='#')||(strlen(spec)!=7)) {
112 Tcl_SetResult(interp,"Only #RRGGBB color specification is supported",
119 * Implements "palette" fgis command.
120 * input - argv[1] subcommand, argv[2] parameter, if required.
126 * Returns (in interp result) - name of newly created palette
127 * Side effects: defines new Tcl command to handle this palette
129 EXPORT(int, Fgis_Palette)(ClientData data,Tcl_Interp *interp,int argc,char **argv)
132 Tcl_SetResult(interp,"Wrong # of args. Should be palette command ?arg?",
133 TCL_STATIC); return TCL_ERROR;
135 if (!strcmp(argv[1],"read")) {
136 Tcl_Channel f; /* no comments */
137 int size; /* return value from Tcl_Read. its size,yes but used just for
139 char buf[MAX_PALETTE_SIZE];/* place to hold readed file */
141 if (Fgis_CkArgs(interp,argc!=3,argv[0]," read filename")) return TCL_ERROR;
142 f=Tcl_OpenFileChannel(interp,argv[2],"r",0666);
143 if (!f) return TCL_ERROR;
144 size=Tcl_Read(f,buf,MAX_PALETTE_SIZE);
146 if (size==-1) {return TCL_ERROR;}
147 if (!(pal=parse_palette(interp,buf))) return TCL_ERROR;
148 } else if (!strcmp(argv[1],"parse")) {
149 if (Fgis_CkArgs(interp,argc!=3,argv[0]," parse string")) return TCL_ERROR;
150 if (!(pal=parse_palette(interp,argv[2]))) {
153 } else if (!strcmp(argv[1],"set")) {
154 int listc,i;char **listv;
155 if (Fgis_CkArgs(interp,argc!=3,argv[0]," set list")) return TCL_ERROR;
156 pal=new_palette(default_palette);
157 if (TCL_ERROR==Tcl_SplitList(interp,argv[2],&listc,&listv))
159 for (i=0;i<listc;i++) {
160 pal[i]=ParseRGB(interp,listv[i]);
161 if (pal[i]==0x1000000) { Tcl_Free((char *)listv);return TCL_ERROR;}
163 Tcl_Free((char *)listv);
164 } else if (!strcmp(argv[1],"copy")) {
166 if (Fgis_CkArgs(interp,argc!=3,argv[0]," copy palettename")) return TCL_ERROR;
167 oldpal=Fgis_GetPalette(interp,argv[2]);
170 pal=new_palette(oldpal);
171 } else if (!strcmp(argv[1],"blank")) {
172 if (Fgis_CkArgs(interp,argc!=2,argv[0]," blank")) return TCL_ERROR;
173 pal=new_palette(NULL);
176 sprintf(buffer,"Wrong option %s. Should be one of read parse set blank copy",
178 Tcl_SetResult(interp,buffer,TCL_VOLATILE);
181 return Fgis_CreateObjectCommand(interp,"palette",Fgis_PaletteObj,
182 (ClientData)pal, Fgis_DeletePalette);
185 * Obtain PALETTE pointer from name of command.
186 * Returns NULL in case of error.
189 EXPORT(PALETTE, Fgis_GetPalette)(Tcl_Interp *interp, char *name)
191 Tcl_CmdInfo info;char buffer[255]="Invalid palette: ";
192 if (!Tcl_GetCommandInfo(interp,name,&info)) return NULL;
193 if (info.proc!=&Fgis_PaletteObj) {
195 Tcl_SetResult(interp,buffer,TCL_VOLATILE);
198 return (PALETTE)(info.clientData);
202 * implements palette object command;
203 * Arguments argv[1]- subcommand argv[i] - parameters
204 * Checks subcommand and calls appropriate function
207 EXPORT(int, Fgis_PaletteObj)(ClientData data,Tcl_Interp *interp,int argc,char **argv)
210 PALETTE clr=(PALETTE)data;
213 /* default palette supposed to be in readonly memory */
214 read_only=clr==default_palette;
215 /* prepare command name for error message */
216 strcpy(buffer,argv[0]);
217 if (Fgis_CkArgs(interp,argc<2,argv[0]," command ?args?"))
219 if (!strcmp(argv[1],"print")) {
221 if (Fgis_CkArgs(interp,argc!=2,argv[0]," print"))
223 for (i=0;i<256;i++) {
224 sprintf(buffer,"%3d %4d %4d %4d\n", i,
225 (clr[i]>>16)*1000/255,
226 ((clr[i]>>8) & 0xFF)*1000/255,
227 (clr[i] & 0xff)*1000/255);
228 Tcl_AppendResult(interp,buffer,NULL);
232 if (!strcmp(argv[1],"get")) {
234 if (Fgis_CkArgs(interp,argc!=3,argv[0],
237 if (Tcl_GetInt(interp,argv[2],&index)==TCL_ERROR) return TCL_ERROR;
238 if (index<0||index>255) {
239 Tcl_SetResult(interp,"#ffffff",TCL_STATIC);
241 Tcl_SetResult(interp,Xcolor_string(clr,index),TCL_VOLATILE);
246 if (!strcmp(argv[1],"set")) {
249 Tcl_AppendResult(interp,argv[0]," is read only",NULL);
252 if (Fgis_CkArgs(interp,argc!=4,argv[0],
255 if (Tcl_GetInt(interp,argv[2],&index)==TCL_ERROR) return TCL_ERROR;
256 if (index<0||index>255) {
257 Tcl_SetResult(interp, "Palette index must be from 0 to 255",
261 if ((RGB=ParseRGB(interp,argv[3]))>0xFFFFFF) return TCL_ERROR;
266 if (!strcmp(argv[1],"list")) {
268 if (Fgis_CkArgs(interp,argc!=2,argv[0]," list"))
271 { Tcl_AppendElement(interp,Xcolor_string(clr,i));
276 if (!strcmp(argv[1],"delete")) {
277 if (Fgis_CkArgs(interp,argc!=2,argv[0]," delete")) return TCL_ERROR;
279 Tcl_AppendResult(interp,buffer," is read only",NULL);
282 Tcl_DeleteCommand(interp,argv[0]);
286 { Tcl_SetResult(interp,"Wrong option. Should be one of print, get, set, "
287 " list, delete", TCL_STATIC);
293 EXPORT(void, Fgis_DeletePalette)(ClientData data)
295 if (data == default_palette) return;
296 Tcl_Free((char *)data);