/src/graphicsmagick/coders/uil.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2003-2025 GraphicsMagick Group |
3 | | % Copyright (C) 2002 ImageMagick Studio |
4 | | % Copyright 1991-1999 E. I. du Pont de Nemours and Company |
5 | | % |
6 | | % This program is covered by multiple licenses, which are described in |
7 | | % Copyright.txt. You should have received a copy of Copyright.txt with this |
8 | | % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
9 | | % |
10 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
11 | | % % |
12 | | % % |
13 | | % % |
14 | | % U U IIIII L % |
15 | | % U U I L % |
16 | | % U U I L % |
17 | | % U U I L % |
18 | | % UUU IIIII LLLLL % |
19 | | % % |
20 | | % % |
21 | | % Write X-Motif UIL Table % |
22 | | % % |
23 | | % % |
24 | | % Software Design % |
25 | | % John Cristy % |
26 | | % July 1992 % |
27 | | % % |
28 | | % % |
29 | | % % |
30 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
31 | | % |
32 | | % |
33 | | */ |
34 | | |
35 | | /* |
36 | | Include declarations. |
37 | | */ |
38 | | #include "magick/studio.h" |
39 | | #include "magick/blob.h" |
40 | | #include "magick/pixel_cache.h" |
41 | | #include "magick/color.h" |
42 | | #include "magick/color_lookup.h" |
43 | | #include "magick/magick.h" |
44 | | #include "magick/monitor.h" |
45 | | #include "magick/utility.h" |
46 | | #include "magick/static.h" |
47 | | |
48 | | /* |
49 | | Forward declarations. |
50 | | */ |
51 | | static unsigned int |
52 | | WriteUILImage(const ImageInfo *,Image *); |
53 | | |
54 | | /* |
55 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
56 | | % % |
57 | | % % |
58 | | % % |
59 | | % R e g i s t e r U I L I m a g e % |
60 | | % % |
61 | | % % |
62 | | % % |
63 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
64 | | % |
65 | | % Method RegisterUILImage adds attributes for the UIL image format to |
66 | | % the list of supported formats. The attributes include the image format |
67 | | % tag, a method to read and/or write the format, whether the format |
68 | | % supports the saving of more than one frame to the same file or blob, |
69 | | % whether the format supports native in-memory I/O, and a brief |
70 | | % description of the format. |
71 | | % |
72 | | % The format of the RegisterUILImage method is: |
73 | | % |
74 | | % RegisterUILImage(void) |
75 | | % |
76 | | */ |
77 | | ModuleExport void RegisterUILImage(void) |
78 | 0 | { |
79 | 0 | MagickInfo |
80 | 0 | *entry; |
81 | |
|
82 | 0 | entry=SetMagickInfo("UIL"); |
83 | 0 | entry->encoder=(EncoderHandler) WriteUILImage; |
84 | 0 | entry->adjoin=False; |
85 | 0 | entry->description="X-Motif UIL table"; |
86 | 0 | entry->module="UIL"; |
87 | 0 | entry->coder_class=UnstableCoderClass; |
88 | 0 | (void) RegisterMagickInfo(entry); |
89 | 0 | } |
90 | | |
91 | | /* |
92 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
93 | | % % |
94 | | % % |
95 | | % % |
96 | | % U n r e g i s t e r U I L I m a g e % |
97 | | % % |
98 | | % % |
99 | | % % |
100 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
101 | | % |
102 | | % Method UnregisterUILImage removes format registrations made by the |
103 | | % UIL module from the list of supported formats. |
104 | | % |
105 | | % The format of the UnregisterUILImage method is: |
106 | | % |
107 | | % UnregisterUILImage(void) |
108 | | % |
109 | | */ |
110 | | ModuleExport void UnregisterUILImage(void) |
111 | 0 | { |
112 | 0 | (void) UnregisterMagickInfo("UIL"); |
113 | 0 | } |
114 | | |
115 | | /* |
116 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
117 | | % % |
118 | | % % |
119 | | % % |
120 | | % W r i t e U I L I m a g e % |
121 | | % % |
122 | | % % |
123 | | % % |
124 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
125 | | % |
126 | | % Procedure WriteUILImage writes an image to a file in the X-Motif UIL table |
127 | | % format. |
128 | | % |
129 | | % The format of the WriteUILImage method is: |
130 | | % |
131 | | % unsigned int WriteUILImage(const ImageInfo *image_info,Image *image) |
132 | | % |
133 | | % A description of each parameter follows. |
134 | | % |
135 | | % o status: Method WriteUILImage return True if the image is written. |
136 | | % False is returned is there is a memory shortage or if the image file |
137 | | % fails to write. |
138 | | % |
139 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
140 | | % |
141 | | % o image: A pointer to an Image structure. |
142 | | % |
143 | | % |
144 | | */ |
145 | | static unsigned int WriteUILImage(const ImageInfo *image_info,Image *image) |
146 | 0 | { |
147 | 0 | #define MaxCixels 92 |
148 | |
|
149 | 0 | static const char |
150 | 0 | Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" |
151 | 0 | "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; |
152 | |
|
153 | 0 | char |
154 | 0 | basename[MaxTextExtent], |
155 | 0 | buffer[MaxTextExtent], |
156 | 0 | name[MaxTextExtent], |
157 | 0 | symbol[MaxTextExtent]; |
158 | |
|
159 | 0 | int |
160 | 0 | j; |
161 | |
|
162 | 0 | long |
163 | 0 | k, |
164 | 0 | y; |
165 | |
|
166 | 0 | register const PixelPacket |
167 | 0 | *p; |
168 | |
|
169 | 0 | register long |
170 | 0 | i, |
171 | 0 | x; |
172 | |
|
173 | 0 | unsigned int |
174 | 0 | status, |
175 | 0 | transparent; |
176 | |
|
177 | 0 | unsigned long |
178 | 0 | characters_per_pixel, |
179 | 0 | colors, |
180 | 0 | number_pixels; |
181 | | |
182 | | /* |
183 | | Open output image file. |
184 | | */ |
185 | 0 | assert(image_info != (const ImageInfo *) NULL); |
186 | 0 | assert(image_info->signature == MagickSignature); |
187 | 0 | assert(image != (Image *) NULL); |
188 | 0 | assert(image->signature == MagickSignature); |
189 | 0 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); |
190 | 0 | if (status == False) |
191 | 0 | ThrowWriterException(FileOpenError,UnableToOpenFile,image); |
192 | 0 | (void) TransformColorspace(image,RGBColorspace); |
193 | 0 | transparent=False; |
194 | 0 | i=0; |
195 | 0 | p=(const PixelPacket *) NULL; |
196 | 0 | if (image->storage_class == PseudoClass) |
197 | 0 | colors=image->colors; |
198 | 0 | else |
199 | 0 | { |
200 | 0 | unsigned char |
201 | 0 | *matte_image; |
202 | | |
203 | | /* |
204 | | Convert DirectClass to PseudoClass image. |
205 | | */ |
206 | 0 | matte_image=(unsigned char *) NULL; |
207 | 0 | if (image->matte) |
208 | 0 | { |
209 | | /* |
210 | | Map all the transparent pixels. |
211 | | */ |
212 | 0 | number_pixels=image->columns*image->rows; |
213 | 0 | matte_image=MagickAllocateResourceLimitedMemory(unsigned char *,number_pixels); |
214 | 0 | if (matte_image == (unsigned char *) NULL) |
215 | 0 | ThrowWriterException(ResourceLimitError,MemoryAllocationFailed, |
216 | 0 | image); |
217 | 0 | for (y=0; y < (long) image->rows; y++) |
218 | 0 | { |
219 | 0 | p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); |
220 | 0 | if (p == (const PixelPacket *) NULL) |
221 | 0 | break; |
222 | 0 | for (x=0; x < (long) image->columns; x++) |
223 | 0 | { |
224 | 0 | matte_image[i]=(unsigned char) (p->opacity == TransparentOpacity); |
225 | 0 | if (matte_image[i]) |
226 | 0 | transparent=True; |
227 | 0 | i++; |
228 | 0 | p++; |
229 | 0 | } |
230 | 0 | } |
231 | 0 | } |
232 | 0 | (void) SetImageType(image,PaletteType); |
233 | 0 | colors=image->colors; |
234 | 0 | if (transparent) |
235 | 0 | { |
236 | 0 | i=0; |
237 | 0 | colors++; |
238 | 0 | for (y=0; y < (long) image->rows; y++) |
239 | 0 | { |
240 | 0 | register IndexPacket |
241 | 0 | *indexes; |
242 | |
|
243 | 0 | p=GetImagePixelsEx(image,0,y,image->columns,1,&image->exception); |
244 | 0 | if (p == (const PixelPacket *) NULL) |
245 | 0 | break; |
246 | 0 | indexes=AccessMutableIndexes(image); |
247 | 0 | for (x=0; x < (long) image->columns; x++) |
248 | 0 | { |
249 | 0 | if (matte_image[i]) |
250 | 0 | indexes[x]=(IndexPacket) image->colors; |
251 | 0 | p++; |
252 | 0 | } |
253 | 0 | } |
254 | 0 | } |
255 | 0 | if (matte_image != (unsigned char *) NULL) |
256 | 0 | MagickFreeResourceLimitedMemory(unsigned char *,matte_image); |
257 | 0 | } |
258 | | /* |
259 | | Compute the character per pixel. |
260 | | */ |
261 | 0 | characters_per_pixel=1; |
262 | 0 | for (k=MaxCixels; (long) colors > k; k*=MaxCixels) |
263 | 0 | characters_per_pixel++; |
264 | | /* |
265 | | UIL header. |
266 | | */ |
267 | 0 | (void) WriteBlobString(image,"/* UIL */\n"); |
268 | 0 | GetPathComponent(image->filename,BasePath,basename); |
269 | 0 | FormatString(buffer,"value\n %.1024s_ct : color_table(\n",basename); |
270 | 0 | (void) WriteBlobString(image,buffer); |
271 | 0 | for (i=0; i < (long) image->colors; i++) |
272 | 0 | { |
273 | | /* |
274 | | Define UIL color. |
275 | | */ |
276 | 0 | (void) QueryColorname(image,image->colormap+i,X11Compliance,name, |
277 | 0 | &image->exception); |
278 | 0 | if (transparent) |
279 | 0 | if (i == (long) (colors-1)) |
280 | 0 | (void) strlcpy(name,"None",sizeof(name)); |
281 | | /* |
282 | | Write UIL color. |
283 | | */ |
284 | 0 | k=i % MaxCixels; |
285 | 0 | symbol[0]=Cixel[k]; |
286 | 0 | for (j=1; j < (int) characters_per_pixel; j++) |
287 | 0 | { |
288 | 0 | k=((i-k)/MaxCixels) % MaxCixels; |
289 | 0 | symbol[j]=Cixel[k]; |
290 | 0 | } |
291 | 0 | symbol[j]='\0'; |
292 | 0 | if (LocaleCompare(name,"None") == 0) |
293 | 0 | FormatString(buffer," background color = '%.1024s'",symbol); |
294 | 0 | else |
295 | 0 | FormatString(buffer," color('%.1024s',%.1024s) = '%.1024s'",name, |
296 | 0 | PixelIntensityToQuantum(image->colormap+i) < (((double) MaxRGB+1.0)/2.0) ? |
297 | 0 | "background" : "foreground",symbol); |
298 | 0 | (void) WriteBlobString(image,buffer); |
299 | 0 | FormatString(buffer,"%.1024s",(i == (long) (colors-1) ? ");\n" : ",\n")); |
300 | 0 | (void) WriteBlobString(image,buffer); |
301 | 0 | } |
302 | | /* |
303 | | Define UIL pixels. |
304 | | */ |
305 | 0 | GetPathComponent(image->filename,BasePath,basename); |
306 | 0 | FormatString(buffer, |
307 | 0 | " %.1024s_icon : icon(color_table = %.1024s_ct,\n",basename,basename); |
308 | 0 | (void) WriteBlobString(image,buffer); |
309 | 0 | for (y=0; y < (long) image->rows; y++) |
310 | 0 | { |
311 | 0 | register const IndexPacket |
312 | 0 | *indexes; |
313 | |
|
314 | 0 | p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); |
315 | 0 | if (p == (const PixelPacket *) NULL) |
316 | 0 | break; |
317 | 0 | indexes=AccessImmutableIndexes(image); |
318 | 0 | (void) WriteBlobString(image," \""); |
319 | 0 | for (x=0; x < (long) image->columns; x++) |
320 | 0 | { |
321 | 0 | k=(long) (indexes[x] % MaxCixels); |
322 | 0 | symbol[0]=Cixel[k]; |
323 | 0 | for (j=1; j < (int) characters_per_pixel; j++) |
324 | 0 | { |
325 | 0 | k=(((int) indexes[x]-k)/MaxCixels) % MaxCixels; |
326 | 0 | symbol[j]=Cixel[k]; |
327 | 0 | } |
328 | 0 | symbol[j]='\0'; |
329 | 0 | (void) strlcpy(buffer,symbol,MaxTextExtent); |
330 | 0 | (void) WriteBlobString(image,buffer); |
331 | 0 | p++; |
332 | 0 | } |
333 | 0 | FormatString(buffer,"\"%.1024s\n", |
334 | 0 | (y == (long) (image->rows-1) ? ");" : ",")); |
335 | 0 | (void) WriteBlobString(image,buffer); |
336 | 0 | if (QuantumTick(y,image->rows)) |
337 | 0 | if (!MagickMonitorFormatted(y,image->rows,&image->exception, |
338 | 0 | SaveImageText,image->filename, |
339 | 0 | image->columns,image->rows)) |
340 | 0 | break; |
341 | 0 | } |
342 | 0 | status &= CloseBlob(image); |
343 | 0 | return(status); |
344 | 0 | } |