xpm.c revision c6da28e61bb609d2b2cfdcc7752106c973415edb
1b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant/* 2b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant% % 4b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant% % 5b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant% % 6b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant% X X PPPP M M % 7b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant% X X P P MM MM % 8b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant% X PPPP M M M % 9b9f2cc816dc3e5369507db9509bea6d10b524a94Howard Hinnant% X X P M M % 1047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% X X P M M % 1147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 1247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 1347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% Read/Write X Windows system Pixmap Format % 1447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 1547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% Software Design % 1647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% John Cristy % 1747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% July 1992 % 1847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 1960a178840d23fbf169a22fde1cef5e558ef232f9Howard Hinnant% % 2047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization % 2147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% dedicated to making software imaging solutions freely available. % 2247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 2347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% You may not use this file except in compliance with the License. You may % 2447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% obtain a copy of the License at % 2547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 2647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% http://www.imagemagick.org/script/license.php % 2747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 2847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% Unless required by applicable law or agreed to in writing, software % 2947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% distributed under the License is distributed on an "AS IS" BASIS, % 3047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 3147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% See the License for the specific language governing permissions and % 3247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% limitations under the License. % 3347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 3447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 3647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 3747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow*/ 3847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 3947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow/* 4047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow Include declarations. 4147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow*/ 4247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/studio.h" 4347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/blob.h" 4447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/blob-private.h" 4547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/cache.h" 4647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/color.h" 4747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/color-private.h" 4847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/colormap.h" 4947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/colorspace.h" 5047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/exception.h" 5147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/exception-private.h" 5247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/geometry.h" 5347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/image.h" 5447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/image-private.h" 5547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/list.h" 5647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/magick.h" 5747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/memory_.h" 5847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/monitor.h" 5947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/monitor-private.h" 6047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/pixel-private.h" 6147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/quantize.h" 6247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/quantum-private.h" 6347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/resize.h" 6447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/resource_.h" 6547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/splay-tree.h" 6647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/static.h" 6747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/string_.h" 6847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/module.h" 6947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/threshold.h" 7047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#include "magick/utility.h" 7147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 7247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow/* 7347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow Forward declarations. 7447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow*/ 7547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowstatic MagickBooleanType 7647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow WritePICONImage(const ImageInfo *,Image *), 7747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow WriteXPMImage(const ImageInfo *,Image *); 7847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 7947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow/* 8047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 8247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 8347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 8447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% I s X P M % 8547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 8647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 8747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 8847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 9047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% IsXPM() returns MagickTrue if the image format type, identified by the 9147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% magick string, is XPM. 9247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 9347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% The format of the IsXPM method is: 9447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 9547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% MagickBooleanType IsXPM(const unsigned char *magick,const size_t length) 9647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 9747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% A description of each parameter follows: 9847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 9947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% o magick: compare image format pattern against these bytes. or 10047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% blob. 10147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 10247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% o length: Specifies the length of the magick string. 10347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 10447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow*/ 10547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowstatic MagickBooleanType IsXPM(const unsigned char *magick,const size_t length) 10647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow{ 10747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow if (length < 9) 10847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow return(MagickFalse); 10947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow if (LocaleNCompare((char *) magick+1,"* XPM *",7) == 0) 11047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow return(MagickTrue); 11147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow return(MagickFalse); 11247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow} 11347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 11447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow/* 11547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 11747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 11847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 11947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% R e a d X P M I m a g e % 12047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 12147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 12247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% % 12347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 12547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% ReadXPMImage() reads an X11 pixmap image file and returns it. It 12647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% allocates the memory necessary for the new Image structure and returns a 12747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% pointer to the new image. 12847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 12947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% The format of the ReadXPMImage method is: 13047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 13147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception) 13247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 13347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% A description of each parameter follows: 13447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 13547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% o image_info: the image info. 13647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 13747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% o exception: return any errors or warnings in this structure. 13847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow% 13947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow*/ 14047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 14147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowstatic int CompareXPMColor(const void *target,const void *source) 14247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow{ 14347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow const char 14447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow *p, 14547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow *q; 14647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 14747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow p=(const char *) target; 14847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow q=(const char *) source; 14947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow return(strcmp(p,q)); 15047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow} 15147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 15247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowstatic char *CopyXPMColor(char *destination,const char *source,size_t length) 15347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow{ 15447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow while (length-- && (*source != '\0')) 15547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow *destination++=(*source++); 15647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow *destination='\0'; 15747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow return(destination-length); 15847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow} 15947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 16047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowstatic char *NextXPMLine(char *p) 16147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow{ 16247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow assert(p != (char*)NULL); 16347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow p=strchr(p,'\n'); 16447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow if (p != (char *) NULL) 16547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow p++; 16647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow return(p); 16747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow} 16847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 16947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowstatic inline size_t MagickMin(const size_t x,const size_t y) 17047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow{ 17147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow if (x < y) 17247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow return(x); 17347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow return(y); 17447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow} 17547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 17647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clowstatic char *ParseXPMColor(char *color) 17747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow{ 17847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow#define NumberTargets 6 17947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 18047c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow register char 18147c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow *p, 18247c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow *r; 18347c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 18447c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow register const char 18547c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow *q; 18647c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 18747c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow register ssize_t 18847c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow i; 18947c29eb784f53ff170074ea00cd238e0e95af82fMarshall Clow 190 static const char 191 *targets[NumberTargets] = { "c ", "g ", "g4 ", "m ", "b ", "s " }; 192 193 for (i=0; i < NumberTargets; i++) 194 { 195 p=color; 196 for (q=targets[i]; *p != '\0'; p++) 197 { 198 if (*p == '\n') 199 break; 200 if (*p != *q) 201 continue; 202 if (isspace((int) ((unsigned char) (*(p-1)))) == 0) 203 continue; 204 r=p; 205 for ( ; ; ) 206 { 207 if (*q == '\0') 208 return(p); 209 if (*r++ != *q++) 210 break; 211 } 212 q=targets[i]; 213 } 214 } 215 return((char *) NULL); 216} 217 218static Image *ReadXPMImage(const ImageInfo *image_info,ExceptionInfo *exception) 219{ 220 char 221 key[MaxTextExtent], 222 target[MaxTextExtent], 223 *xpm_buffer; 224 225 Image 226 *image; 227 228 MagickBooleanType 229 active, 230 status; 231 232 register char 233 *p, 234 *q, 235 *next; 236 237 register IndexPacket 238 *indexes; 239 240 register ssize_t 241 x; 242 243 register PixelPacket 244 *r; 245 246 size_t 247 length; 248 249 SplayTreeInfo 250 *xpm_colors; 251 252 ssize_t 253 count, 254 j, 255 y; 256 257 unsigned long 258 colors, 259 columns, 260 rows, 261 width; 262 263 /* 264 Open image file. 265 */ 266 assert(image_info != (const ImageInfo *) NULL); 267 assert(image_info->signature == MagickSignature); 268 if (image_info->debug != MagickFalse) 269 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 270 image_info->filename); 271 assert(exception != (ExceptionInfo *) NULL); 272 assert(exception->signature == MagickSignature); 273 image=AcquireImage(image_info); 274 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 275 if (status == MagickFalse) 276 { 277 image=DestroyImageList(image); 278 return((Image *) NULL); 279 } 280 /* 281 Read XPM file. 282 */ 283 length=MaxTextExtent; 284 xpm_buffer=(char *) AcquireQuantumMemory((size_t) length,sizeof(*xpm_buffer)); 285 p=xpm_buffer; 286 if (xpm_buffer != (char *) NULL) 287 while (ReadBlobString(image,p) != (char *) NULL) 288 { 289 if ((*p == '#') && ((p == xpm_buffer) || (*(p-1) == '\n'))) 290 continue; 291 if ((*p == '}') && (*(p+1) == ';')) 292 break; 293 p+=strlen(p); 294 if ((size_t) (p-xpm_buffer+MaxTextExtent) < length) 295 continue; 296 length<<=1; 297 xpm_buffer=(char *) ResizeQuantumMemory(xpm_buffer,length+MaxTextExtent, 298 sizeof(*xpm_buffer)); 299 if (xpm_buffer == (char *) NULL) 300 break; 301 p=xpm_buffer+strlen(xpm_buffer); 302 } 303 if (xpm_buffer == (char *) NULL) 304 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 305 /* 306 Remove comments. 307 */ 308 count=0; 309 for (p=xpm_buffer; *p != '\0'; p++) 310 { 311 if (*p != '"') 312 continue; 313 count=(ssize_t) sscanf(p+1,"%lu %lu %lu %lu",&columns,&rows,&colors,&width); 314 image->columns=columns; 315 image->rows=rows; 316 image->colors=colors; 317 if (count == 4) 318 break; 319 } 320 if ((count != 4) || (width > 10) || (image->columns == 0) || 321 (image->rows == 0) || (image->colors == 0)) 322 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 323 image->depth=16; 324 /* 325 Remove unquoted characters. 326 */ 327 active=MagickFalse; 328 q=xpm_buffer; 329 while (*p != '\0') 330 { 331 if (*p++ == '"') 332 { 333 if (active != MagickFalse) 334 *q++='\n'; 335 active=active != MagickFalse ? MagickFalse : MagickTrue; 336 } 337 if (active != MagickFalse) 338 *q++=(*p); 339 } 340 *q='\0'; 341 /* 342 Initialize image structure. 343 */ 344 xpm_colors=NewSplayTree(CompareXPMColor,RelinquishMagickMemory, 345 (void *(*)(void *)) NULL); 346 if (AcquireImageColormap(image,image->colors) == MagickFalse) 347 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 348 /* 349 Read image colormap. 350 */ 351 next=NextXPMLine(xpm_buffer); 352 for (j=0; (j < (ssize_t) image->colors) && (next != (char*) NULL); j++) 353 { 354 p=next; 355 next=NextXPMLine(p); 356 (void) CopyXPMColor(key,p,MagickMin((size_t) width,MaxTextExtent)); 357 status=AddValueToSplayTree(xpm_colors,ConstantString(key),(void *) j); 358 /* 359 Parse color. 360 */ 361 (void) CopyMagickString(target,"gray",MaxTextExtent); 362 q=ParseXPMColor(p+width); 363 if (q != (char *) NULL) 364 { 365 while ((isspace((int) ((unsigned char) *q)) == 0) && (*q != '\0')) 366 q++; 367 if (next != (char *) NULL) 368 (void) CopyXPMColor(target,q,MagickMin((size_t) (next-q), 369 MaxTextExtent)); 370 else 371 (void) CopyMagickString(target,q,MaxTextExtent); 372 q=ParseXPMColor(target); 373 if (q != (char *) NULL) 374 *q='\0'; 375 } 376 StripString(target); 377 if (LocaleCompare(target,"none") == 0) 378 { 379 image->storage_class=DirectClass; 380 image->matte=MagickTrue; 381 } 382 status=QueryColorCompliance(target,AllCompliance,&image->colormap[j], 383 exception); 384 if (status == MagickFalse) 385 break; 386 } 387 if (j < (ssize_t) image->colors) 388 ThrowReaderException(CorruptImageError,"CorruptImage"); 389 j=0; 390 if (image_info->ping == MagickFalse) 391 { 392 /* 393 Read image pixels. 394 */ 395 for (y=0; y < (ssize_t) image->rows; y++) 396 { 397 p=NextXPMLine(p); 398 if (p == (char *) NULL) 399 break; 400 r=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 401 if (r == (PixelPacket *) NULL) 402 break; 403 indexes=GetAuthenticIndexQueue(image); 404 for (x=0; x < (ssize_t) image->columns; x++) 405 { 406 (void) CopyXPMColor(key,p,(size_t) width); 407 j=(ssize_t) GetValueFromSplayTree(xpm_colors,key); 408 if (image->storage_class == PseudoClass) 409 SetIndexPixelComponent(indexes+x,j); 410 *r=image->colormap[j]; 411 r++; 412 p+=width; 413 } 414 if (SyncAuthenticPixels(image,exception) == MagickFalse) 415 break; 416 } 417 if (y < (ssize_t) image->rows) 418 ThrowReaderException(CorruptImageError,"NotEnoughPixelData"); 419 } 420 /* 421 Relinquish resources. 422 */ 423 xpm_colors=DestroySplayTree(xpm_colors); 424 (void) CloseBlob(image); 425 return(GetFirstImageInList(image)); 426} 427 428/* 429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 430% % 431% % 432% % 433% R e g i s t e r X P M I m a g e % 434% % 435% % 436% % 437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 438% 439% RegisterXPMImage() adds attributes for the XPM image format to 440% the list of supported formats. The attributes include the image format 441% tag, a method to read and/or write the format, whether the format 442% supports the saving of more than one frame to the same file or blob, 443% whether the format supports native in-memory I/O, and a brief 444% description of the format. 445% 446% The format of the RegisterXPMImage method is: 447% 448% size_t RegisterXPMImage(void) 449% 450*/ 451ModuleExport size_t RegisterXPMImage(void) 452{ 453 MagickInfo 454 *entry; 455 456 entry=SetMagickInfo("PICON"); 457 entry->decoder=(DecodeImageHandler *) ReadXPMImage; 458 entry->encoder=(EncodeImageHandler *) WritePICONImage; 459 entry->adjoin=MagickFalse; 460 entry->description=ConstantString("Personal Icon"); 461 entry->module=ConstantString("XPM"); 462 (void) RegisterMagickInfo(entry); 463 entry=SetMagickInfo("PM"); 464 entry->decoder=(DecodeImageHandler *) ReadXPMImage; 465 entry->encoder=(EncodeImageHandler *) WriteXPMImage; 466 entry->adjoin=MagickFalse; 467 entry->stealth=MagickTrue; 468 entry->description=ConstantString("X Windows system pixmap (color)"); 469 entry->module=ConstantString("XPM"); 470 (void) RegisterMagickInfo(entry); 471 entry=SetMagickInfo("XPM"); 472 entry->decoder=(DecodeImageHandler *) ReadXPMImage; 473 entry->encoder=(EncodeImageHandler *) WriteXPMImage; 474 entry->magick=(IsImageFormatHandler *) IsXPM; 475 entry->adjoin=MagickFalse; 476 entry->description=ConstantString("X Windows system pixmap (color)"); 477 entry->module=ConstantString("XPM"); 478 (void) RegisterMagickInfo(entry); 479 return(MagickImageCoderSignature); 480} 481 482/* 483%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 484% % 485% % 486% % 487% U n r e g i s t e r X P M I m a g e % 488% % 489% % 490% % 491%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 492% 493% UnregisterXPMImage() removes format registrations made by the 494% XPM module from the list of supported formats. 495% 496% The format of the UnregisterXPMImage method is: 497% 498% UnregisterXPMImage(void) 499% 500*/ 501ModuleExport void UnregisterXPMImage(void) 502{ 503 (void) UnregisterMagickInfo("PICON"); 504 (void) UnregisterMagickInfo("PM"); 505 (void) UnregisterMagickInfo("XPM"); 506} 507 508/* 509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 510% % 511% % 512% % 513% W r i t e P I C O N I m a g e % 514% % 515% % 516% % 517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 518% 519% WritePICONImage() writes an image to a file in the Personal Icon format. 520% 521% The format of the WritePICONImage method is: 522% 523% MagickBooleanType WritePICONImage(const ImageInfo *image_info, 524% Image *image) 525% 526% A description of each parameter follows. 527% 528% o image_info: the image info. 529% 530% o image: The image. 531% 532*/ 533static MagickBooleanType WritePICONImage(const ImageInfo *image_info, 534 Image *image) 535{ 536#define ColormapExtent 155 537#define GraymapExtent 95 538#define PiconGeometry "48x48>" 539 540 static unsigned char 541 Colormap[]= 542 { 543 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x06, 0x00, 0x05, 0x00, 0xf4, 0x05, 544 0x00, 0x00, 0x00, 0x00, 0x2f, 0x4f, 0x4f, 0x70, 0x80, 0x90, 0x7e, 0x7e, 545 0x7e, 0xdc, 0xdc, 0xdc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 546 0xff, 0x1e, 0x90, 0xff, 0x87, 0xce, 0xeb, 0xe6, 0xe6, 0xfa, 0x00, 0xff, 547 0xff, 0x80, 0x00, 0x80, 0xb2, 0x22, 0x22, 0x2e, 0x8b, 0x57, 0x32, 0xcd, 548 0x32, 0x00, 0xff, 0x00, 0x98, 0xfb, 0x98, 0xff, 0x00, 0xff, 0xff, 0x00, 549 0x00, 0xff, 0x63, 0x47, 0xff, 0xa5, 0x00, 0xff, 0xd7, 0x00, 0xff, 0xff, 550 0x00, 0xee, 0x82, 0xee, 0xa0, 0x52, 0x2d, 0xcd, 0x85, 0x3f, 0xd2, 0xb4, 551 0x8c, 0xf5, 0xde, 0xb3, 0xff, 0xfa, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 552 0x00, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 553 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x05, 0x18, 0x20, 0x10, 0x08, 554 0x03, 0x51, 0x18, 0x07, 0x92, 0x28, 0x0b, 0xd3, 0x38, 0x0f, 0x14, 0x49, 555 0x13, 0x55, 0x59, 0x17, 0x96, 0x69, 0x1b, 0xd7, 0x85, 0x00, 0x3b, 556 }, 557 Graymap[]= 558 { 559 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x04, 0x00, 0x04, 0x00, 0xf3, 0x0f, 560 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x12, 0x21, 0x21, 0x21, 0x33, 0x33, 561 0x33, 0x45, 0x45, 0x45, 0x54, 0x54, 0x54, 0x66, 0x66, 0x66, 0x78, 0x78, 562 0x78, 0x87, 0x87, 0x87, 0x99, 0x99, 0x99, 0xab, 0xab, 0xab, 0xba, 0xba, 563 0xba, 0xcc, 0xcc, 0xcc, 0xde, 0xde, 0xde, 0xed, 0xed, 0xed, 0xff, 0xff, 564 0xff, 0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 565 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x0c, 0x10, 0x04, 0x31, 566 0x48, 0x31, 0x07, 0x25, 0xb5, 0x58, 0x73, 0x4f, 0x04, 0x00, 0x3b, 567 }; 568 569#define MaxCixels 92 570 571 static const char 572 Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" 573 "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; 574 575 char 576 buffer[MaxTextExtent], 577 basename[MaxTextExtent], 578 name[MaxTextExtent], 579 symbol[MaxTextExtent]; 580 581 ExceptionInfo 582 *exception; 583 584 Image 585 *affinity_image, 586 *picon; 587 588 ImageInfo 589 *blob_info; 590 591 MagickBooleanType 592 status, 593 transparent; 594 595 MagickPixelPacket 596 pixel; 597 598 QuantizeInfo 599 *quantize_info; 600 601 RectangleInfo 602 geometry; 603 604 register const IndexPacket 605 *indexes; 606 607 register const PixelPacket 608 *p; 609 610 register ssize_t 611 i, 612 x; 613 614 register PixelPacket 615 *q; 616 617 size_t 618 characters_per_pixel, 619 colors; 620 621 ssize_t 622 j, 623 k, 624 y; 625 626 /* 627 Open output image file. 628 */ 629 assert(image_info != (const ImageInfo *) NULL); 630 assert(image_info->signature == MagickSignature); 631 assert(image != (Image *) NULL); 632 assert(image->signature == MagickSignature); 633 if (image->debug != MagickFalse) 634 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 635 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); 636 if (status == MagickFalse) 637 return(status); 638 if (image->colorspace != RGBColorspace) 639 (void) TransformImageColorspace(image,RGBColorspace); 640 SetGeometry(image,&geometry); 641 (void) ParseMetaGeometry(PiconGeometry,&geometry.x,&geometry.y, 642 &geometry.width,&geometry.height); 643 picon=ResizeImage(image,geometry.width,geometry.height,TriangleFilter,1.0, 644 &image->exception); 645 blob_info=CloneImageInfo(image_info); 646 (void) AcquireUniqueFilename(blob_info->filename); 647 if ((image_info->type != TrueColorType) && 648 (IsGrayImage(image,&image->exception) != MagickFalse)) 649 affinity_image=BlobToImage(blob_info,Graymap,GraymapExtent, 650 &image->exception); 651 else 652 affinity_image=BlobToImage(blob_info,Colormap,ColormapExtent, 653 &image->exception); 654 (void) RelinquishUniqueFileResource(blob_info->filename); 655 blob_info=DestroyImageInfo(blob_info); 656 if ((picon == (Image *) NULL) || (affinity_image == (Image *) NULL)) 657 return(MagickFalse); 658 quantize_info=AcquireQuantizeInfo(image_info); 659 status=RemapImage(quantize_info,picon,affinity_image); 660 quantize_info=DestroyQuantizeInfo(quantize_info); 661 affinity_image=DestroyImage(affinity_image); 662 transparent=MagickFalse; 663 exception=(&image->exception); 664 if (picon->storage_class == PseudoClass) 665 { 666 (void) CompressImageColormap(picon); 667 if (picon->matte != MagickFalse) 668 transparent=MagickTrue; 669 } 670 else 671 { 672 /* 673 Convert DirectClass to PseudoClass picon. 674 */ 675 if (picon->matte != MagickFalse) 676 { 677 /* 678 Map all the transparent pixels. 679 */ 680 for (y=0; y < (ssize_t) picon->rows; y++) 681 { 682 q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception); 683 if (q == (PixelPacket *) NULL) 684 break; 685 for (x=0; x < (ssize_t) picon->columns; x++) 686 { 687 if (q->opacity == (Quantum) TransparentOpacity) 688 transparent=MagickTrue; 689 else 690 SetOpacityPixelComponent(q,OpaqueOpacity); 691 q++; 692 } 693 if (SyncAuthenticPixels(picon,exception) == MagickFalse) 694 break; 695 } 696 } 697 (void) SetImageType(picon,PaletteType); 698 } 699 colors=picon->colors; 700 if (transparent != MagickFalse) 701 { 702 register IndexPacket 703 *indexes; 704 705 colors++; 706 picon->colormap=(PixelPacket *) ResizeQuantumMemory((void **) 707 picon->colormap,(size_t) colors,sizeof(*picon->colormap)); 708 if (picon->colormap == (PixelPacket *) NULL) 709 ThrowWriterException(ResourceLimitError,"MemoryAllocationError"); 710 for (y=0; y < (ssize_t) picon->rows; y++) 711 { 712 q=GetAuthenticPixels(picon,0,y,picon->columns,1,exception); 713 if (q == (PixelPacket *) NULL) 714 break; 715 indexes=GetAuthenticIndexQueue(picon); 716 for (x=0; x < (ssize_t) picon->columns; x++) 717 { 718 if (q->opacity == (Quantum) TransparentOpacity) 719 SetIndexPixelComponent(indexes+x,picon->colors); 720 q++; 721 } 722 if (SyncAuthenticPixels(picon,exception) == MagickFalse) 723 break; 724 } 725 } 726 /* 727 Compute the character per pixel. 728 */ 729 characters_per_pixel=1; 730 for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels) 731 characters_per_pixel++; 732 /* 733 XPM header. 734 */ 735 (void) WriteBlobString(image,"/* XPM */\n"); 736 GetPathComponent(picon->filename,BasePath,basename); 737 (void) FormatMagickString(buffer,MaxTextExtent, 738 "static char *%s[] = {\n",basename); 739 (void) WriteBlobString(image,buffer); 740 (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n"); 741 (void) FormatMagickString(buffer,MaxTextExtent, 742 "\"%.20g %.20g %.20g %.20g\",\n",(double) picon->columns,(double) 743 picon->rows,(double) colors,(double) characters_per_pixel); 744 (void) WriteBlobString(image,buffer); 745 GetMagickPixelPacket(image,&pixel); 746 for (i=0; i < (ssize_t) colors; i++) 747 { 748 /* 749 Define XPM color. 750 */ 751 SetMagickPixelPacket(image,picon->colormap+i,(IndexPacket *) NULL,&pixel); 752 pixel.colorspace=RGBColorspace; 753 pixel.depth=8; 754 pixel.opacity=(MagickRealType) OpaqueOpacity; 755 (void) QueryMagickColorname(image,&pixel,XPMCompliance,name, 756 &image->exception); 757 if (transparent != MagickFalse) 758 { 759 if (i == (ssize_t) (colors-1)) 760 (void) CopyMagickString(name,"grey75",MaxTextExtent); 761 } 762 /* 763 Write XPM color. 764 */ 765 k=i % MaxCixels; 766 symbol[0]=Cixel[k]; 767 for (j=1; j < (ssize_t) characters_per_pixel; j++) 768 { 769 k=((i-k)/MaxCixels) % MaxCixels; 770 symbol[j]=Cixel[k]; 771 } 772 symbol[j]='\0'; 773 (void) FormatMagickString(buffer,MaxTextExtent,"\"%s c %s\",\n", 774 symbol,name); 775 (void) WriteBlobString(image,buffer); 776 } 777 /* 778 Define XPM pixels. 779 */ 780 (void) WriteBlobString(image,"/* pixels */\n"); 781 for (y=0; y < (ssize_t) picon->rows; y++) 782 { 783 p=GetVirtualPixels(picon,0,y,picon->columns,1,&picon->exception); 784 if (p == (const PixelPacket *) NULL) 785 break; 786 indexes=GetVirtualIndexQueue(picon); 787 (void) WriteBlobString(image,"\""); 788 for (x=0; x < (ssize_t) picon->columns; x++) 789 { 790 k=((ssize_t) GetIndexPixelComponent(indexes+x) % MaxCixels); 791 symbol[0]=Cixel[k]; 792 for (j=1; j < (ssize_t) characters_per_pixel; j++) 793 { 794 k=(((int) GetIndexPixelComponent(indexes+x)-k)/MaxCixels) % MaxCixels; 795 symbol[j]=Cixel[k]; 796 } 797 symbol[j]='\0'; 798 (void) CopyMagickString(buffer,symbol,MaxTextExtent); 799 (void) WriteBlobString(image,buffer); 800 } 801 (void) FormatMagickString(buffer,MaxTextExtent,"\"%s\n", 802 y == (ssize_t) (picon->rows-1) ? "" : ","); 803 (void) WriteBlobString(image,buffer); 804 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 805 picon->rows); 806 if (status == MagickFalse) 807 break; 808 } 809 picon=DestroyImage(picon); 810 (void) WriteBlobString(image,"};\n"); 811 (void) CloseBlob(image); 812 return(MagickTrue); 813} 814 815/* 816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 817% % 818% % 819% % 820% W r i t e X P M I m a g e % 821% % 822% % 823% % 824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 825% 826% WriteXPMImage() writes an image to a file in the X pixmap format. 827% 828% The format of the WriteXPMImage method is: 829% 830% MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image) 831% 832% A description of each parameter follows. 833% 834% o image_info: the image info. 835% 836% o image: The image. 837% 838*/ 839static MagickBooleanType WriteXPMImage(const ImageInfo *image_info,Image *image) 840{ 841#define MaxCixels 92 842 843 static const char 844 Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" 845 "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; 846 847 char 848 buffer[MaxTextExtent], 849 basename[MaxTextExtent], 850 name[MaxTextExtent], 851 symbol[MaxTextExtent]; 852 853 MagickBooleanType 854 status; 855 856 MagickPixelPacket 857 pixel; 858 859 register const IndexPacket 860 *indexes; 861 862 register const PixelPacket 863 *p; 864 865 register ssize_t 866 i, 867 x; 868 869 size_t 870 characters_per_pixel; 871 872 ssize_t 873 j, 874 k, 875 opacity, 876 y; 877 878 /* 879 Open output image file. 880 */ 881 assert(image_info != (const ImageInfo *) NULL); 882 assert(image_info->signature == MagickSignature); 883 assert(image != (Image *) NULL); 884 assert(image->signature == MagickSignature); 885 if (image->debug != MagickFalse) 886 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 887 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); 888 if (status == MagickFalse) 889 return(status); 890 if (image->colorspace != RGBColorspace) 891 (void) TransformImageColorspace(image,RGBColorspace); 892 opacity=(-1); 893 if (image->matte == MagickFalse) 894 { 895 if ((image->storage_class == DirectClass) || (image->colors > 256)) 896 (void) SetImageType(image,PaletteType); 897 } 898 else 899 { 900 MagickRealType 901 alpha, 902 beta; 903 904 /* 905 Identify transparent colormap index. 906 */ 907 if ((image->storage_class == DirectClass) || (image->colors > 256)) 908 (void) SetImageType(image,PaletteBilevelMatteType); 909 for (i=0; i < (ssize_t) image->colors; i++) 910 if (image->colormap[i].opacity != OpaqueOpacity) 911 { 912 if (opacity < 0) 913 { 914 opacity=i; 915 continue; 916 } 917 alpha=(Quantum) TransparentOpacity-(MagickRealType) 918 image->colormap[i].opacity; 919 beta=(Quantum) TransparentOpacity-(MagickRealType) 920 image->colormap[opacity].opacity; 921 if (alpha < beta) 922 opacity=i; 923 } 924 if (opacity == -1) 925 { 926 (void) SetImageType(image,PaletteBilevelMatteType); 927 for (i=0; i < (ssize_t) image->colors; i++) 928 if (image->colormap[i].opacity != OpaqueOpacity) 929 { 930 if (opacity < 0) 931 { 932 opacity=i; 933 continue; 934 } 935 alpha=(Quantum) TransparentOpacity-(MagickRealType) 936 image->colormap[i].opacity; 937 beta=(Quantum) TransparentOpacity-(MagickRealType) 938 image->colormap[opacity].opacity; 939 if (alpha < beta) 940 opacity=i; 941 } 942 } 943 if (opacity >= 0) 944 { 945 image->colormap[opacity].red=image->transparent_color.red; 946 image->colormap[opacity].green=image->transparent_color.green; 947 image->colormap[opacity].blue=image->transparent_color.blue; 948 } 949 } 950 /* 951 Compute the character per pixel. 952 */ 953 characters_per_pixel=1; 954 for (k=MaxCixels; (ssize_t) image->colors > k; k*=MaxCixels) 955 characters_per_pixel++; 956 /* 957 XPM header. 958 */ 959 (void) WriteBlobString(image,"/* XPM */\n"); 960 GetPathComponent(image->filename,BasePath,basename); 961 if (isalnum((int) ((unsigned char) *basename)) == 0) 962 { 963 (void) FormatMagickString(buffer,MaxTextExtent,"xpm_%s",basename); 964 (void) CopyMagickString(basename,buffer,MaxTextExtent); 965 } 966 if (isalpha((int) ((unsigned char) basename[0])) == 0) 967 basename[0]='_'; 968 for (i=1; basename[i] != '\0'; i++) 969 if (isalnum((int) ((unsigned char) basename[i])) == 0) 970 basename[i]='_'; 971 (void) FormatMagickString(buffer,MaxTextExtent, 972 "static char *%s[] = {\n",basename); 973 (void) WriteBlobString(image,buffer); 974 (void) WriteBlobString(image,"/* columns rows colors chars-per-pixel */\n"); 975 (void) FormatMagickString(buffer,MaxTextExtent, 976 "\"%.20g %.20g %.20g %.20g \",\n",(double) image->columns,(double) 977 image->rows,(double) image->colors,(double) characters_per_pixel); 978 (void) WriteBlobString(image,buffer); 979 GetMagickPixelPacket(image,&pixel); 980 for (i=0; i < (ssize_t) image->colors; i++) 981 { 982 /* 983 Define XPM color. 984 */ 985 SetMagickPixelPacket(image,image->colormap+i,(IndexPacket *) NULL,&pixel); 986 pixel.colorspace=RGBColorspace; 987 pixel.depth=8; 988 pixel.opacity=(MagickRealType) OpaqueOpacity; 989 (void) QueryMagickColorname(image,&pixel,XPMCompliance,name, 990 &image->exception); 991 if (i == opacity) 992 (void) CopyMagickString(name,"None",MaxTextExtent); 993 /* 994 Write XPM color. 995 */ 996 k=i % MaxCixels; 997 symbol[0]=Cixel[k]; 998 for (j=1; j < (ssize_t) characters_per_pixel; j++) 999 { 1000 k=((i-k)/MaxCixels) % MaxCixels; 1001 symbol[j]=Cixel[k]; 1002 } 1003 symbol[j]='\0'; 1004 (void) FormatMagickString(buffer,MaxTextExtent,"\"%s c %s\",\n",symbol, 1005 name); 1006 (void) WriteBlobString(image,buffer); 1007 } 1008 /* 1009 Define XPM pixels. 1010 */ 1011 (void) WriteBlobString(image,"/* pixels */\n"); 1012 for (y=0; y < (ssize_t) image->rows; y++) 1013 { 1014 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); 1015 if (p == (const PixelPacket *) NULL) 1016 break; 1017 indexes=GetVirtualIndexQueue(image); 1018 (void) WriteBlobString(image,"\""); 1019 for (x=0; x < (ssize_t) image->columns; x++) 1020 { 1021 k=((ssize_t) GetIndexPixelComponent(indexes+x) % MaxCixels); 1022 symbol[0]=Cixel[k]; 1023 for (j=1; j < (ssize_t) characters_per_pixel; j++) 1024 { 1025 k=(((int) GetIndexPixelComponent(indexes+x)-k)/MaxCixels) % MaxCixels; 1026 symbol[j]=Cixel[k]; 1027 } 1028 symbol[j]='\0'; 1029 (void) CopyMagickString(buffer,symbol,MaxTextExtent); 1030 (void) WriteBlobString(image,buffer); 1031 } 1032 (void) FormatMagickString(buffer,MaxTextExtent,"\"%s\n", 1033 (y == (ssize_t) (image->rows-1) ? "" : ",")); 1034 (void) WriteBlobString(image,buffer); 1035 if (image->previous == (Image *) NULL) 1036 { 1037 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1038 image->rows); 1039 if (status == MagickFalse) 1040 break; 1041 } 1042 } 1043 (void) WriteBlobString(image,"};\n"); 1044 (void) CloseBlob(image); 1045 return(MagickTrue); 1046} 1047