html.c revision f2faecf9facdbbb14fcba373365f9f691a9658e0
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-2010 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
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
63/*
64  Forward declarations.
65*/
66static MagickBooleanType
67  WriteHTMLImage(const ImageInfo *,Image *);
68
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*/
94static 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
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*/
126ModuleExport 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
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*/
177ModuleExport void UnregisterHTMLImage(void)
178{
179  (void) UnregisterMagickInfo("HTM");
180  (void) UnregisterMagickInfo("HTML");
181  (void) UnregisterMagickInfo("SHTML");
182}
183
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*/
209static 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,%lu,%lu\" alt=\"\" />\n",
344            image->filename,(unsigned long) geometry.width-1,(unsigned long)
345            geometry.height-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,
355                "\" shape=\"rect\" coords=\"%ld,%ld,%ld,%ld\" alt=\"\" />\n",
356                (long) geometry.x,(long) geometry.y,(long) (geometry.x+
357                geometry.width-1),(long) (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+=geometry.width;
366              if ((geometry.x+4) >= (ssize_t) image->columns)
367                {
368                  geometry.x=0;
369                  geometry.y+=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,%lu,%lu\" alt=\"\" />\n",
420        image->filename,(unsigned long) geometry.width-1,(unsigned long)
421        geometry.height-1);
422      (void) WriteBlobString(image,buffer);
423    }
424  else
425    for (p=image->directory; *p != '\0'; p++)
426      if (*p != '\n')
427        (void) WriteBlobByte(image,(unsigned char) *p);
428      else
429        {
430          (void) FormatMagickString(buffer,MaxTextExtent,
431            "\" shape=\"rect\" coords=\"%ld,%ld,%ld,%ld\" alt=\"\" />\n",
432            (long) geometry.x,(long) geometry.y,geometry.x+(long)
433            geometry.width-1,geometry.y+(long) geometry.height-1);
434          (void) WriteBlobString(image,buffer);
435          if (*(p+1) != '\0')
436            {
437              (void) FormatMagickString(buffer,MaxTextExtent,
438                "  <area href=%s\"",url);
439              (void) WriteBlobString(image,buffer);
440            }
441          geometry.x+=geometry.width;
442          if ((geometry.x+4) >= (ssize_t) image->columns)
443            {
444              geometry.x=0;
445              geometry.y+=geometry.height;
446            }
447        }
448  (void) WriteBlobString(image,"</map>\n");
449  (void) CloseBlob(image);
450  (void) CopyMagickString(image->filename,filename,MaxTextExtent);
451  return(status);
452}
453