]> granicus.if.org Git - imagemagick/blob - coders/html.c
(no commit message)
[imagemagick] / coders / html.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                        H   H  TTTTT  M   M  L                               %
7 %                        H   H    T    MM MM  L                               %
8 %                        HHHHH    T    M M M  L                               %
9 %                        H   H    T    M   M  L                               %
10 %                        H   H    T    M   M  LLLLL                           %
11 %                                                                             %
12 %                                                                             %
13 %                  Write A Client-Side Image Map Using                        %
14 %                 Image Montage & Directory Information.                      %
15 %                                                                             %
16 %                              Software Design                                %
17 %                                John Cristy                                  %
18 %                                 July 1992                                   %
19 %                                                                             %
20 %                                                                             %
21 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
22 %  dedicated to making software imaging solutions freely available.           %
23 %                                                                             %
24 %  You may not use this file except in compliance with the License.  You may  %
25 %  obtain a copy of the License at                                            %
26 %                                                                             %
27 %    http://www.imagemagick.org/script/license.php                            %
28 %                                                                             %
29 %  Unless required by applicable law or agreed to in writing, software        %
30 %  distributed under the License is distributed on an "AS IS" BASIS,          %
31 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
32 %  See the License for the specific language governing permissions and        %
33 %  limitations under the License.                                             %
34 %                                                                             %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 %
37 %
38 */
39 \f
40 /*
41   Include declarations.
42 */
43 #include "magick/studio.h"
44 #include "magick/blob.h"
45 #include "magick/blob-private.h"
46 #include "magick/color-private.h"
47 #include "magick/colorspace.h"
48 #include "magick/constitute.h"
49 #include "magick/exception.h"
50 #include "magick/exception-private.h"
51 #include "magick/geometry.h"
52 #include "magick/list.h"
53 #include "magick/magick.h"
54 #include "magick/memory_.h"
55 #include "magick/paint.h"
56 #include "magick/property.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 \f
63 /*
64   Forward declarations.
65 */
66 static MagickBooleanType
67   WriteHTMLImage(const ImageInfo *,Image *);
68 \f
69 /*
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 %                                                                             %
72 %                                                                             %
73 %                                                                             %
74 %   I s H T M L                                                               %
75 %                                                                             %
76 %                                                                             %
77 %                                                                             %
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 %
80 %  IsHTML() returns MagickTrue if the image format type, identified by the
81 %  magick string, is HTML.
82 %
83 %  The format of the IsHTML method is:
84 %
85 %      MagickBooleanType IsHTML(const unsigned char *magick,const size_t length)
86 %
87 %  A description of each parameter follows:
88 %
89 %    o magick: compare image format pattern against these bytes.
90 %
91 %    o length: Specifies the length of the magick string.
92 %
93 */
94 static MagickBooleanType IsHTML(const unsigned char *magick,const size_t length)
95 {
96   if (length < 5)
97     return(MagickFalse);
98   if (LocaleNCompare((char *) magick,"<html",5) == 0)
99     return(MagickTrue);
100   return(MagickFalse);
101 }
102 \f
103 /*
104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
105 %                                                                             %
106 %                                                                             %
107 %                                                                             %
108 %   R e g i s t e r H T M L I m a g e                                         %
109 %                                                                             %
110 %                                                                             %
111 %                                                                             %
112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
113 %
114 %  RegisterHTMLImage() adds properties for the HTML image format to
115 %  the list of supported formats.  The properties include the image format
116 %  tag, a method to read and/or write the format, whether the format
117 %  supports the saving of more than one frame to the same file or blob,
118 %  whether the format supports native in-memory I/O, and a brief
119 %  description of the format.
120 %
121 %  The format of the RegisterHTMLImage method is:
122 %
123 %      size_t RegisterHTMLImage(void)
124 %
125 */
126 ModuleExport size_t RegisterHTMLImage(void)
127 {
128   MagickInfo
129     *entry;
130
131   entry=SetMagickInfo("HTM");
132   entry->encoder=(EncodeImageHandler *) WriteHTMLImage;
133   entry->magick=(IsImageFormatHandler *) IsHTML;
134   entry->adjoin=MagickFalse;
135   entry->description=ConstantString(
136     "Hypertext Markup Language and a client-side image map");
137   entry->module=ConstantString("HTML");
138   (void) RegisterMagickInfo(entry);
139   entry=SetMagickInfo("HTML");
140   entry->encoder=(EncodeImageHandler *) WriteHTMLImage;
141   entry->magick=(IsImageFormatHandler *) IsHTML;
142   entry->adjoin=MagickFalse;
143   entry->description=ConstantString(
144     "Hypertext Markup Language and a client-side image map");
145   entry->module=ConstantString("HTML");
146   (void) RegisterMagickInfo(entry);
147   entry=SetMagickInfo("SHTML");
148   entry->encoder=(EncodeImageHandler *) WriteHTMLImage;
149   entry->magick=(IsImageFormatHandler *) IsHTML;
150   entry->adjoin=MagickFalse;
151   entry->description=ConstantString(
152     "Hypertext Markup Language and a client-side image map");
153   entry->module=ConstantString("HTML");
154   (void) RegisterMagickInfo(entry);
155   return(MagickImageCoderSignature);
156 }
157 \f
158 /*
159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
160 %                                                                             %
161 %                                                                             %
162 %                                                                             %
163 %   U n r e g i s t e r H T M L I m a g e                                     %
164 %                                                                             %
165 %                                                                             %
166 %                                                                             %
167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 %
169 %  UnregisterHTMLImage() removes format registrations made by the
170 %  HTML module from the list of supported formats.
171 %
172 %  The format of the UnregisterHTMLImage method is:
173 %
174 %      UnregisterHTMLImage(void)
175 %
176 */
177 ModuleExport void UnregisterHTMLImage(void)
178 {
179   (void) UnregisterMagickInfo("HTM");
180   (void) UnregisterMagickInfo("HTML");
181   (void) UnregisterMagickInfo("SHTML");
182 }
183 \f
184 /*
185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186 %                                                                             %
187 %                                                                             %
188 %                                                                             %
189 %   W r i t e H T M L I m a g e                                               %
190 %                                                                             %
191 %                                                                             %
192 %                                                                             %
193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 %
195 %  WriteHTMLImage() writes an image in the HTML encoded image format.
196 %
197 %  The format of the WriteHTMLImage method is:
198 %
199 %      MagickBooleanType WriteHTMLImage(const ImageInfo *image_info,Image *image)
200 %
201 %  A description of each parameter follows.
202 %
203 %    o image_info: the image info.
204 %
205 %    o image:  The image.
206 %
207 %
208 */
209 static MagickBooleanType WriteHTMLImage(const ImageInfo *image_info,
210   Image *image)
211 {
212   char
213     basename[MaxTextExtent],
214     buffer[MaxTextExtent],
215     filename[MaxTextExtent],
216     mapname[MaxTextExtent],
217     url[MaxTextExtent];
218
219   Image
220     *next;
221
222   ImageInfo
223     *write_info;
224
225   MagickBooleanType
226     status;
227
228   RectangleInfo
229     geometry;
230
231   register char
232     *p;
233
234   /*
235     Open image.
236   */
237   assert(image_info != (const ImageInfo *) NULL);
238   assert(image_info->signature == MagickSignature);
239   assert(image != (Image *) NULL);
240   assert(image->signature == MagickSignature);
241   if (image->debug != MagickFalse)
242     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
243       image_info->filename);
244   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
245   if (status == MagickFalse)
246     return(status);
247   (void) CloseBlob(image);
248   if (image->colorspace != RGBColorspace)
249     (void) TransformImageColorspace(image,RGBColorspace);
250   *url='\0';
251   if ((LocaleCompare(image_info->magick,"FTP") == 0) ||
252       (LocaleCompare(image_info->magick,"HTTP") == 0))
253     {
254       /*
255         Extract URL base from filename.
256       */
257       p=strrchr(image->filename,'/');
258       if (p)
259         {
260           p++;
261           (void) CopyMagickString(url,image_info->magick,MaxTextExtent);
262           (void) ConcatenateMagickString(url,":",MaxTextExtent);
263           url[strlen(url)+p-image->filename]='\0';
264           (void) ConcatenateMagickString(url,image->filename,
265             p-image->filename+2);
266           (void) CopyMagickString(image->filename,p,MaxTextExtent);
267         }
268     }
269   /*
270     Refer to image map file.
271   */
272   (void) CopyMagickString(filename,image->filename,MaxTextExtent);
273   AppendImageFormat("map",filename);
274   GetPathComponent(filename,BasePath,basename);
275   (void) CopyMagickString(mapname,basename,MaxTextExtent);
276   (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
277   (void) CopyMagickString(filename,image->filename,MaxTextExtent);
278   write_info=CloneImageInfo(image_info);
279   write_info->adjoin=MagickTrue;
280   status=MagickTrue;
281   if (LocaleCompare(image_info->magick,"SHTML") != 0)
282     {
283       const char
284         *value;
285
286       /*
287         Open output image file.
288       */
289       status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
290       if (status == MagickFalse)
291         return(status);
292       /*
293         Write the HTML image file.
294       */
295       (void) WriteBlobString(image,"<?xml version=\"1.0\" "
296         "encoding=\"US-ASCII\"?>\n");
297       (void) WriteBlobString(image,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML "
298         "1.0 Strict//EN\" "
299         "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n");
300       (void) WriteBlobString(image,"<html>\n");
301       (void) WriteBlobString(image,"<head>\n");
302       value=GetImageProperty(image,"label");
303       if (value != (const char *) NULL)
304         (void) FormatMagickString(buffer,MaxTextExtent,"<title>%s</title>\n",
305           value);
306       else
307         {
308           GetPathComponent(filename,BasePath,basename);
309           (void) FormatMagickString(buffer,MaxTextExtent,
310             "<title>%s</title>\n",basename);
311         }
312       (void) WriteBlobString(image,buffer);
313       (void) WriteBlobString(image,"</head>\n");
314       (void) WriteBlobString(image,"<body style=\"text-align: center;\">\n");
315       (void) FormatMagickString(buffer,MaxTextExtent,"<h1>%s</h1>\n",
316         image->filename);
317       (void) WriteBlobString(image,buffer);
318       (void) WriteBlobString(image,"<div>\n");
319       (void) CopyMagickString(filename,image->filename,MaxTextExtent);
320       AppendImageFormat("png",filename);
321       (void) FormatMagickString(buffer,MaxTextExtent,"<img usemap=\"#%s\" "
322         "src=\"%s\" style=\"border: 0;\" alt=\"Image map\" />\n",mapname,
323         filename);
324       (void) WriteBlobString(image,buffer);
325       /*
326         Determine the size and location of each image tile.
327       */
328       SetGeometry(image,&geometry);
329       if (image->montage != (char *) NULL)
330         (void) ParseAbsoluteGeometry(image->montage,&geometry);
331       /*
332         Write an image map.
333       */
334       (void) FormatMagickString(buffer,MaxTextExtent,
335         "<map id=\"%s\" name=\"%s\">\n",mapname,mapname);
336       (void) WriteBlobString(image,buffer);
337       (void) FormatMagickString(buffer,MaxTextExtent,"  <area href=\"%s",
338         url);
339       (void) WriteBlobString(image,buffer);
340       if (image->directory == (char *) NULL)
341         {
342           (void) FormatMagickString(buffer,MaxTextExtent,
343             "%s\" shape=\"rect\" coords=\"0,0,%.20g,%.20g\" alt=\"\" />\n",
344             image->filename,(double) geometry.width-1,(double) geometry.height-
345             1);
346           (void) WriteBlobString(image,buffer);
347         }
348       else
349         for (p=image->directory; *p != '\0'; p++)
350           if (*p != '\n')
351             (void) WriteBlobByte(image,(unsigned char) *p);
352           else
353             {
354               (void) FormatMagickString(buffer,MaxTextExtent,"\" shape="
355                 "\"rect\" coords=\"%.20g,%.20g,%.20g,%.20g\" alt=\"\" />\n",
356                 (double) geometry.x,(double) geometry.y,(double) (geometry.x+
357                 geometry.width-1),(double) (geometry.y+geometry.height-1));
358               (void) WriteBlobString(image,buffer);
359               if (*(p+1) != '\0')
360                 {
361                   (void) FormatMagickString(buffer,MaxTextExtent,
362                     "  <area href=%s\"",url);
363                   (void) WriteBlobString(image,buffer);
364                 }
365               geometry.x+=(ssize_t) geometry.width;
366               if ((geometry.x+4) >= (ssize_t) image->columns)
367                 {
368                   geometry.x=0;
369                   geometry.y+=(ssize_t) geometry.height;
370                 }
371             }
372       (void) WriteBlobString(image,"</map>\n");
373       (void) CopyMagickString(filename,image->filename,MaxTextExtent);
374       (void) WriteBlobString(image,"</div>\n");
375       (void) WriteBlobString(image,"</body>\n");
376       (void) WriteBlobString(image,"</html>\n");
377       (void) CloseBlob(image);
378       /*
379         Write the image as PNG.
380       */
381       (void) CopyMagickString(image->filename,filename,MaxTextExtent);
382       AppendImageFormat("png",image->filename);
383       next=GetNextImageInList(image);
384       image->next=NewImageList();
385       (void) CopyMagickString(image->magick,"PNG",MaxTextExtent);
386       (void) WriteImage(write_info,image);
387       image->next=next;
388       /*
389         Determine image map filename.
390       */
391       GetPathComponent(image->filename,BasePath,filename);
392       (void) ConcatenateMagickString(filename,"_map.shtml",MaxTextExtent);
393       (void) CopyMagickString(image->filename,filename,MaxTextExtent);
394     }
395   /*
396     Open image map.
397   */
398   status=OpenBlob(write_info,image,WriteBinaryBlobMode,&image->exception);
399   if (status == MagickFalse)
400     return(status);
401   write_info=DestroyImageInfo(write_info);
402   /*
403     Determine the size and location of each image tile.
404   */
405   SetGeometry(image,&geometry);
406   if (image->montage != (char *) NULL)
407     (void) ParseAbsoluteGeometry(image->montage,&geometry);
408   /*
409     Write an image map.
410   */
411   (void) FormatMagickString(buffer,MaxTextExtent,
412     "<map id=\"%s\" name=\"%s\">\n",mapname,mapname);
413   (void) WriteBlobString(image,buffer);
414   (void) FormatMagickString(buffer,MaxTextExtent,"  <area href=\"%s",url);
415   (void) WriteBlobString(image,buffer);
416   if (image->directory == (char *) NULL)
417     {
418       (void) FormatMagickString(buffer,MaxTextExtent,
419         "%s\" shape=\"rect\" coords=\"0,0,%.20g,%.20g\" alt=\"\" />\n",
420         image->filename,(double) geometry.width-1,(double) geometry.height-1);
421       (void) WriteBlobString(image,buffer);
422     }
423   else
424     for (p=image->directory; *p != '\0'; p++)
425       if (*p != '\n')
426         (void) WriteBlobByte(image,(unsigned char) *p);
427       else
428         {
429           (void) FormatMagickString(buffer,MaxTextExtent,"\" shape=\"rect\""
430             " coords=\"%.20g,%.20g,%.20g,%.20g\" alt=\"\" />\n",
431             (double) geometry.x,(double) geometry.y,geometry.x+(double)
432             geometry.width-1,geometry.y+(double) geometry.height-1);
433           (void) WriteBlobString(image,buffer);
434           if (*(p+1) != '\0')
435             {
436               (void) FormatMagickString(buffer,MaxTextExtent,
437                 "  <area href=%s\"",url);
438               (void) WriteBlobString(image,buffer);
439             }
440           geometry.x+=(ssize_t) geometry.width;
441           if ((geometry.x+4) >= (ssize_t) image->columns)
442             {
443               geometry.x=0;
444               geometry.y+=(ssize_t) geometry.height;
445             }
446         }
447   (void) WriteBlobString(image,"</map>\n");
448   (void) CloseBlob(image);
449   (void) CopyMagickString(image->filename,filename,MaxTextExtent);
450   return(status);
451 }