blob: 0025f0d12b6954f399d1413df2d8cffb39ff2169 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% U U IIIII L %
7% U U I L %
8% U U I L %
9% U U I L %
10% UUU IIIII LLLLL %
11% %
12% %
13% Write X-Motif UIL Table. %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#include "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/blob-private.h"
45#include "magick/cache.h"
46#include "magick/color.h"
47#include "magick/color-private.h"
48#include "magick/colorspace.h"
49#include "magick/exception.h"
50#include "magick/exception-private.h"
51#include "magick/image-private.h"
52#include "magick/magick.h"
53#include "magick/memory_.h"
54#include "magick/monitor.h"
55#include "magick/monitor-private.h"
56#include "magick/pixel-private.h"
57#include "magick/quantum-private.h"
58#include "magick/static.h"
59#include "magick/string_.h"
60#include "magick/module.h"
61#include "magick/utility.h"
62
63/*
64 Forward declarations.
65*/
66static MagickBooleanType
67 WriteUILImage(const ImageInfo *,Image *);
68
69/*
70%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71% %
72% %
73% %
74% R e g i s t e r U I L I m a g e %
75% %
76% %
77% %
78%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79%
80% RegisterUILImage() adds attributes for the UIL image format to
81% the list of supported formats. The attributes include the image format
82% tag, a method to read and/or write the format, whether the format
83% supports the saving of more than one frame to the same file or blob,
84% whether the format supports native in-memory I/O, and a brief
85% description of the format.
86%
87% The format of the RegisterUILImage method is:
88%
cristybb503372010-05-27 20:51:26 +000089% size_t RegisterUILImage(void)
cristy3ed852e2009-09-05 21:47:34 +000090%
91*/
cristybb503372010-05-27 20:51:26 +000092ModuleExport size_t RegisterUILImage(void)
cristy3ed852e2009-09-05 21:47:34 +000093{
94 MagickInfo
95 *entry;
96
97 entry=SetMagickInfo("UIL");
98 entry->encoder=(EncodeImageHandler *) WriteUILImage;
99 entry->adjoin=MagickFalse;
100 entry->description=ConstantString("X-Motif UIL table");
101 entry->module=ConstantString("UIL");
102 (void) RegisterMagickInfo(entry);
103 return(MagickImageCoderSignature);
104}
105
106/*
107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108% %
109% %
110% %
111% U n r e g i s t e r U I L I m a g e %
112% %
113% %
114% %
115%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116%
117% UnregisterUILImage() removes format registrations made by the
118% UIL module from the list of supported formats.
119%
120% The format of the UnregisterUILImage method is:
121%
122% UnregisterUILImage(void)
123%
124*/
125ModuleExport void UnregisterUILImage(void)
126{
127 (void) UnregisterMagickInfo("UIL");
128}
129
130/*
131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132% %
133% %
134% %
135% W r i t e U I L I m a g e %
136% %
137% %
138% %
139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140%
141% Procedure WriteUILImage() writes an image to a file in the X-Motif UIL table
142% format.
143%
144% The format of the WriteUILImage method is:
145%
146% MagickBooleanType WriteUILImage(const ImageInfo *image_info,Image *image)
147%
148% A description of each parameter follows.
149%
150% o image_info: the image info.
151%
152% o image: The image.
153%
154*/
155static MagickBooleanType WriteUILImage(const ImageInfo *image_info,Image *image)
156{
157#define MaxCixels 92
158
159 char
160 basename[MaxTextExtent],
161 buffer[MaxTextExtent],
162 name[MaxTextExtent],
cristybd899c22009-11-26 23:51:49 +0000163 *symbol;
cristy3ed852e2009-09-05 21:47:34 +0000164
165 ExceptionInfo
166 *exception;
167
168 int
169 j;
170
cristybb503372010-05-27 20:51:26 +0000171 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000172 k,
173 y;
174
175 MagickBooleanType
176 status,
177 transparent;
178
179 MagickPixelPacket
180 pixel;
181
182 MagickSizeType
183 number_pixels;
184
185 register const IndexPacket
186 *indexes;
187
188 register const PixelPacket
189 *p;
190
cristybb503372010-05-27 20:51:26 +0000191 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000192 i,
193 x;
194
195 static const char
196 Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk"
197 "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
198
cristybb503372010-05-27 20:51:26 +0000199 size_t
cristy3ed852e2009-09-05 21:47:34 +0000200 characters_per_pixel,
201 colors;
202
203 /*
204 Open output image file.
205 */
206 assert(image_info != (const ImageInfo *) NULL);
207 assert(image_info->signature == MagickSignature);
208 assert(image != (Image *) NULL);
209 assert(image->signature == MagickSignature);
210 if (image->debug != MagickFalse)
211 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
212 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
213 if (status == MagickFalse)
214 return(status);
215 if (image->colorspace != RGBColorspace)
216 (void) TransformImageColorspace(image,RGBColorspace);
217 exception=(&image->exception);
218 transparent=MagickFalse;
219 i=0;
220 p=(const PixelPacket *) NULL;
221 if (image->storage_class == PseudoClass)
222 colors=image->colors;
223 else
224 {
225 unsigned char
226 *matte_image;
227
228 /*
229 Convert DirectClass to PseudoClass image.
230 */
231 matte_image=(unsigned char *) NULL;
232 if (image->matte != MagickFalse)
233 {
234 /*
235 Map all the transparent pixels.
236 */
237 number_pixels=(MagickSizeType) image->columns*image->rows;
238 if (number_pixels != ((MagickSizeType) (size_t) number_pixels))
239 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
240 matte_image=(unsigned char *) AcquireQuantumMemory(image->columns,
241 image->rows*sizeof(*matte_image));
242 if (matte_image == (unsigned char *) NULL)
243 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000244 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000245 {
246 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
247 if (p == (const PixelPacket *) NULL)
248 break;
cristybb503372010-05-27 20:51:26 +0000249 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000250 {
251 matte_image[i]=(unsigned char)
252 (p->opacity == (Quantum) TransparentOpacity ? 1 : 0);
253 if (matte_image[i] != 0)
254 transparent=MagickTrue;
255 i++;
256 p++;
257 }
258 }
259 }
260 (void) SetImageType(image,PaletteType);
261 colors=image->colors;
262 if (transparent != MagickFalse)
263 {
264 register IndexPacket
265 *indexes;
266
267 register PixelPacket
268 *q;
269
270 colors++;
cristybb503372010-05-27 20:51:26 +0000271 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000272 {
273 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
274 if (q == (PixelPacket *) NULL)
275 break;
276 indexes=GetAuthenticIndexQueue(image);
cristybb503372010-05-27 20:51:26 +0000277 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000278 {
279 if (matte_image[i] != 0)
280 indexes[x]=(IndexPacket) image->colors;
281 p++;
282 }
283 }
284 }
285 if (matte_image != (unsigned char *) NULL)
286 matte_image=(unsigned char *) RelinquishMagickMemory(matte_image);
287 }
288 /*
289 Compute the character per pixel.
290 */
291 characters_per_pixel=1;
cristybb503372010-05-27 20:51:26 +0000292 for (k=MaxCixels; (ssize_t) colors > k; k*=MaxCixels)
cristy3ed852e2009-09-05 21:47:34 +0000293 characters_per_pixel++;
294 /*
295 UIL header.
296 */
cristybd899c22009-11-26 23:51:49 +0000297 symbol=AcquireString("");
cristy3ed852e2009-09-05 21:47:34 +0000298 (void) WriteBlobString(image,"/* UIL */\n");
299 GetPathComponent(image->filename,BasePath,basename);
300 (void) FormatMagickString(buffer,MaxTextExtent,
301 "value\n %s_ct : color_table(\n",basename);
302 (void) WriteBlobString(image,buffer);
303 GetMagickPixelPacket(image,&pixel);
cristybb503372010-05-27 20:51:26 +0000304 for (i=0; i < (ssize_t) colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000305 {
306 /*
307 Define UIL color.
308 */
309 SetMagickPixelPacket(image,image->colormap+i,(IndexPacket *) NULL,&pixel);
310 pixel.colorspace=RGBColorspace;
311 pixel.depth=8;
312 pixel.opacity=(MagickRealType) OpaqueOpacity;
313 GetColorTuple(&pixel,MagickTrue,name);
314 if (transparent != MagickFalse)
cristybb503372010-05-27 20:51:26 +0000315 if (i == (ssize_t) (colors-1))
cristy3ed852e2009-09-05 21:47:34 +0000316 (void) CopyMagickString(name,"None",MaxTextExtent);
317 /*
318 Write UIL color.
319 */
320 k=i % MaxCixels;
321 symbol[0]=Cixel[k];
322 for (j=1; j < (int) characters_per_pixel; j++)
323 {
324 k=((i-k)/MaxCixels) % MaxCixels;
325 symbol[j]=Cixel[k];
326 }
327 symbol[j]='\0';
cristybd899c22009-11-26 23:51:49 +0000328 (void) SubstituteString(&symbol,"'","''");
cristy3ed852e2009-09-05 21:47:34 +0000329 if (LocaleCompare(name,"None") == 0)
330 (void) FormatMagickString(buffer,MaxTextExtent,
331 " background color = '%s'",symbol);
332 else
333 (void) FormatMagickString(buffer,MaxTextExtent,
334 " color('%s',%s) = '%s'",name,
335 PixelIntensityToQuantum(image->colormap+i) <
336 ((Quantum) QuantumRange/2) ? "background" : "foreground",symbol);
337 (void) WriteBlobString(image,buffer);
338 (void) FormatMagickString(buffer,MaxTextExtent,"%s",
cristybb503372010-05-27 20:51:26 +0000339 (i == (ssize_t) (colors-1) ? ");\n" : ",\n"));
cristy3ed852e2009-09-05 21:47:34 +0000340 (void) WriteBlobString(image,buffer);
341 }
342 /*
343 Define UIL pixels.
344 */
345 GetPathComponent(image->filename,BasePath,basename);
346 (void) FormatMagickString(buffer,MaxTextExtent,
347 " %s_icon : icon(color_table = %s_ct,\n",basename,basename);
348 (void) WriteBlobString(image,buffer);
cristybb503372010-05-27 20:51:26 +0000349 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000350 {
351 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
352 if (p == (const PixelPacket *) NULL)
353 break;
354 indexes=GetVirtualIndexQueue(image);
355 (void) WriteBlobString(image," \"");
cristybb503372010-05-27 20:51:26 +0000356 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000357 {
cristybb503372010-05-27 20:51:26 +0000358 k=((ssize_t) indexes[x] % MaxCixels);
cristy3ed852e2009-09-05 21:47:34 +0000359 symbol[0]=Cixel[k];
360 for (j=1; j < (int) characters_per_pixel; j++)
361 {
362 k=(((int) indexes[x]-k)/MaxCixels) % MaxCixels;
363 symbol[j]=Cixel[k];
364 }
365 symbol[j]='\0';
366 (void) CopyMagickString(buffer,symbol,MaxTextExtent);
367 (void) WriteBlobString(image,buffer);
368 p++;
369 }
370 (void) FormatMagickString(buffer,MaxTextExtent,"\"%s\n",
cristybb503372010-05-27 20:51:26 +0000371 (y == (ssize_t) (image->rows-1) ? ");" : ","));
cristy3ed852e2009-09-05 21:47:34 +0000372 (void) WriteBlobString(image,buffer);
cristycee97112010-05-28 00:44:52 +0000373 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
374 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000375 if (status == MagickFalse)
376 break;
377 }
cristybd899c22009-11-26 23:51:49 +0000378 symbol=DestroyString(symbol);
cristy3ed852e2009-09-05 21:47:34 +0000379 (void) CloseBlob(image);
380 return(MagickTrue);
381}