Home | History | Annotate | Download | only in coders
      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 %                                   Cristy                                    %
     18 %                                 July 1992                                   %
     19 %                                                                             %
     20 %                                                                             %
     21 %  Copyright 1999-2016 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 /*
     42   Include declarations.
     43 */
     44 #include "MagickCore/studio.h"
     45 #include "MagickCore/blob.h"
     46 #include "MagickCore/blob-private.h"
     47 #include "MagickCore/color-private.h"
     48 #include "MagickCore/colorspace.h"
     49 #include "MagickCore/colorspace-private.h"
     50 #include "MagickCore/constitute.h"
     51 #include "MagickCore/exception.h"
     52 #include "MagickCore/exception-private.h"
     53 #include "MagickCore/geometry.h"
     54 #include "MagickCore/list.h"
     55 #include "MagickCore/magick.h"
     56 #include "MagickCore/memory_.h"
     57 #include "MagickCore/paint.h"
     58 #include "MagickCore/property.h"
     59 #include "MagickCore/quantum-private.h"
     60 #include "MagickCore/static.h"
     61 #include "MagickCore/string_.h"
     62 #include "MagickCore/module.h"
     63 #include "MagickCore/utility.h"
     64 
     65 /*
     67   Forward declarations.
     68 */
     69 static MagickBooleanType
     70   WriteHTMLImage(const ImageInfo *,Image *,ExceptionInfo *);
     71 
     72 /*
     74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     75 %                                                                             %
     76 %                                                                             %
     77 %                                                                             %
     78 %   I s H T M L                                                               %
     79 %                                                                             %
     80 %                                                                             %
     81 %                                                                             %
     82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     83 %
     84 %  IsHTML() returns MagickTrue if the image format type, identified by the
     85 %  magick string, is HTML.
     86 %
     87 %  The format of the IsHTML method is:
     88 %
     89 %      MagickBooleanType IsHTML(const unsigned char *magick,const size_t length)
     90 %
     91 %  A description of each parameter follows:
     92 %
     93 %    o magick: compare image format pattern against these bytes.
     94 %
     95 %    o length: Specifies the length of the magick string.
     96 %
     97 */
     98 static MagickBooleanType IsHTML(const unsigned char *magick,const size_t length)
     99 {
    100   if (length < 5)
    101     return(MagickFalse);
    102   if (LocaleNCompare((char *) magick,"<html",5) == 0)
    103     return(MagickTrue);
    104   return(MagickFalse);
    105 }
    106 
    107 /*
    109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    110 %                                                                             %
    111 %                                                                             %
    112 %                                                                             %
    113 %   R e g i s t e r H T M L I m a g e                                         %
    114 %                                                                             %
    115 %                                                                             %
    116 %                                                                             %
    117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    118 %
    119 %  RegisterHTMLImage() adds properties for the HTML image format to
    120 %  the list of supported formats.  The properties include the image format
    121 %  tag, a method to read and/or write the format, whether the format
    122 %  supports the saving of more than one frame to the same file or blob,
    123 %  whether the format supports native in-memory I/O, and a brief
    124 %  description of the format.
    125 %
    126 %  The format of the RegisterHTMLImage method is:
    127 %
    128 %      size_t RegisterHTMLImage(void)
    129 %
    130 */
    131 ModuleExport size_t RegisterHTMLImage(void)
    132 {
    133   MagickInfo
    134     *entry;
    135 
    136   entry=AcquireMagickInfo("HTML","HTM",
    137     "Hypertext Markup Language and a client-side image map");
    138   entry->encoder=(EncodeImageHandler *) WriteHTMLImage;
    139   entry->magick=(IsImageFormatHandler *) IsHTML;
    140   entry->flags^=CoderAdjoinFlag;
    141   (void) RegisterMagickInfo(entry);
    142   entry=AcquireMagickInfo("HTML","HTML",
    143     "Hypertext Markup Language and a client-side image map");
    144   entry->encoder=(EncodeImageHandler *) WriteHTMLImage;
    145   entry->magick=(IsImageFormatHandler *) IsHTML;
    146   entry->flags^=CoderAdjoinFlag;
    147   (void) RegisterMagickInfo(entry);
    148   entry=AcquireMagickInfo("HTML","SHTML",
    149     "Hypertext Markup Language and a client-side image map");
    150   entry->encoder=(EncodeImageHandler *) WriteHTMLImage;
    151   entry->magick=(IsImageFormatHandler *) IsHTML;
    152   entry->flags^=CoderAdjoinFlag;
    153   (void) RegisterMagickInfo(entry);
    154   return(MagickImageCoderSignature);
    155 }
    156 
    157 /*
    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 
    184 /*
    186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    187 %                                                                             %
    188 %                                                                             %
    189 %                                                                             %
    190 %   W r i t e H T M L I m a g e                                               %
    191 %                                                                             %
    192 %                                                                             %
    193 %                                                                             %
    194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    195 %
    196 %  WriteHTMLImage() writes an image in the HTML encoded image format.
    197 %
    198 %  The format of the WriteHTMLImage method is:
    199 %
    200 %      MagickBooleanType WriteHTMLImage(const ImageInfo *image_info,
    201 %        Image *image,ExceptionInfo *exception)
    202 %
    203 %  A description of each parameter follows.
    204 %
    205 %    o image_info: the image info.
    206 %
    207 %    o image:  The image.
    208 %
    209 %    o exception: return any errors or warnings in this structure.
    210 %
    211 */
    212 static MagickBooleanType WriteHTMLImage(const ImageInfo *image_info,
    213   Image *image,ExceptionInfo *exception)
    214 {
    215   char
    216     basename[MagickPathExtent],
    217     buffer[MagickPathExtent],
    218     filename[MagickPathExtent],
    219     mapname[MagickPathExtent],
    220     url[MagickPathExtent];
    221 
    222   Image
    223     *next;
    224 
    225   ImageInfo
    226     *write_info;
    227 
    228   MagickBooleanType
    229     status;
    230 
    231   RectangleInfo
    232     geometry;
    233 
    234   register char
    235     *p;
    236 
    237   /*
    238     Open image.
    239   */
    240   assert(image_info != (const ImageInfo *) NULL);
    241   assert(image_info->signature == MagickCoreSignature);
    242   assert(image != (Image *) NULL);
    243   assert(image->signature == MagickCoreSignature);
    244   if (image->debug != MagickFalse)
    245     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    246       image_info->filename);
    247   assert(exception != (ExceptionInfo *) NULL);
    248   assert(exception->signature == MagickCoreSignature);
    249   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
    250   if (status == MagickFalse)
    251     return(status);
    252   (void) CloseBlob(image);
    253   (void) TransformImageColorspace(image,sRGBColorspace,exception);
    254   *url='\0';
    255   if ((LocaleCompare(image_info->magick,"FTP") == 0) ||
    256       (LocaleCompare(image_info->magick,"HTTP") == 0))
    257     {
    258       /*
    259         Extract URL base from filename.
    260       */
    261       p=strrchr(image->filename,'/');
    262       if (p != (char *) NULL)
    263         {
    264           p++;
    265           (void) CopyMagickString(url,image_info->magick,MagickPathExtent);
    266           (void) ConcatenateMagickString(url,":",MagickPathExtent);
    267           url[strlen(url)+p-image->filename]='\0';
    268           (void) ConcatenateMagickString(url,image->filename,
    269             p-image->filename+2);
    270           (void) CopyMagickString(image->filename,p,MagickPathExtent);
    271         }
    272     }
    273   /*
    274     Refer to image map file.
    275   */
    276   (void) CopyMagickString(filename,image->filename,MagickPathExtent);
    277   AppendImageFormat("map",filename);
    278   GetPathComponent(filename,BasePath,basename);
    279   (void) CopyMagickString(mapname,basename,MagickPathExtent);
    280   (void) CopyMagickString(image->filename,image_info->filename,MagickPathExtent);
    281   (void) CopyMagickString(filename,image->filename,MagickPathExtent);
    282   write_info=CloneImageInfo(image_info);
    283   *write_info->magick='\0';
    284   write_info->adjoin=MagickTrue;
    285   status=MagickTrue;
    286   if (LocaleCompare(image_info->magick,"SHTML") != 0)
    287     {
    288       const char
    289         *value;
    290 
    291       /*
    292         Open output image file.
    293       */
    294       assert(exception != (ExceptionInfo *) NULL);
    295       status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
    296       if (status == MagickFalse)
    297         return(status);
    298       /*
    299         Write the HTML image file.
    300       */
    301       (void) WriteBlobString(image,"<?xml version=\"1.0\" "
    302         "encoding=\"US-ASCII\"?>\n");
    303       (void) WriteBlobString(image,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML "
    304         "1.0 Strict//EN\" "
    305         "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n");
    306       (void) WriteBlobString(image,"<html>\n");
    307       (void) WriteBlobString(image,"<head>\n");
    308       value=GetImageProperty(image,"label",exception);
    309       if (value != (const char *) NULL)
    310         (void) FormatLocaleString(buffer,MagickPathExtent,"<title>%s</title>\n",
    311           value);
    312       else
    313         {
    314           GetPathComponent(filename,BasePath,basename);
    315           (void) FormatLocaleString(buffer,MagickPathExtent,
    316             "<title>%s</title>\n",basename);
    317         }
    318       (void) WriteBlobString(image,buffer);
    319       (void) WriteBlobString(image,"</head>\n");
    320       (void) WriteBlobString(image,"<body style=\"text-align: center;\">\n");
    321       (void) FormatLocaleString(buffer,MagickPathExtent,"<h1>%s</h1>\n",
    322         image->filename);
    323       (void) WriteBlobString(image,buffer);
    324       (void) WriteBlobString(image,"<div>\n");
    325       (void) CopyMagickString(filename,image->filename,MagickPathExtent);
    326       AppendImageFormat("png",filename);
    327       (void) FormatLocaleString(buffer,MagickPathExtent,"<img usemap=\"#%s\" "
    328         "src=\"%s\" style=\"border: 0;\" alt=\"Image map\" />\n",mapname,
    329         filename);
    330       (void) WriteBlobString(image,buffer);
    331       /*
    332         Determine the size and location of each image tile.
    333       */
    334       SetGeometry(image,&geometry);
    335       if (image->montage != (char *) NULL)
    336         (void) ParseAbsoluteGeometry(image->montage,&geometry);
    337       /*
    338         Write an image map.
    339       */
    340       (void) FormatLocaleString(buffer,MagickPathExtent,
    341         "<map id=\"%s\" name=\"%s\">\n",mapname,mapname);
    342       (void) WriteBlobString(image,buffer);
    343       (void) FormatLocaleString(buffer,MagickPathExtent,"  <area href=\"%s",url);
    344       (void) WriteBlobString(image,buffer);
    345       if (image->directory == (char *) NULL)
    346         {
    347           (void) FormatLocaleString(buffer,MagickPathExtent,
    348             "%s\" shape=\"rect\" coords=\"0,0,%.20g,%.20g\" alt=\"\" />\n",
    349             image->filename,(double) geometry.width-1,(double) geometry.height-
    350             1);
    351           (void) WriteBlobString(image,buffer);
    352         }
    353       else
    354         for (p=image->directory; *p != '\0'; p++)
    355           if (*p != '\n')
    356             (void) WriteBlobByte(image,(unsigned char) *p);
    357           else
    358             {
    359               (void) FormatLocaleString(buffer,MagickPathExtent,"\" shape="
    360                 "\"rect\" coords=\"%.20g,%.20g,%.20g,%.20g\" alt=\"\" />\n",
    361                 (double) geometry.x,(double) geometry.y,(double) (geometry.x+
    362                 geometry.width-1),(double) (geometry.y+geometry.height-1));
    363               (void) WriteBlobString(image,buffer);
    364               if (*(p+1) != '\0')
    365                 {
    366                   (void) FormatLocaleString(buffer,MagickPathExtent,
    367                     "  <area href=%s\"",url);
    368                   (void) WriteBlobString(image,buffer);
    369                 }
    370               geometry.x+=(ssize_t) geometry.width;
    371               if ((geometry.x+4) >= (ssize_t) image->columns)
    372                 {
    373                   geometry.x=0;
    374                   geometry.y+=(ssize_t) geometry.height;
    375                 }
    376             }
    377       (void) WriteBlobString(image,"</map>\n");
    378       (void) CopyMagickString(filename,image->filename,MagickPathExtent);
    379       (void) WriteBlobString(image,"</div>\n");
    380       (void) WriteBlobString(image,"</body>\n");
    381       (void) WriteBlobString(image,"</html>\n");
    382       (void) CloseBlob(image);
    383       /*
    384         Write the image as PNG.
    385       */
    386       (void) CopyMagickString(image->filename,filename,MagickPathExtent);
    387       AppendImageFormat("png",image->filename);
    388       next=GetNextImageInList(image);
    389       image->next=NewImageList();
    390       (void) CopyMagickString(image->magick,"PNG",MagickPathExtent);
    391       (void) WriteImage(write_info,image,exception);
    392       image->next=next;
    393       /*
    394         Determine image map filename.
    395       */
    396       GetPathComponent(image->filename,BasePath,filename);
    397       (void) ConcatenateMagickString(filename,"_map.shtml",MagickPathExtent);
    398       (void) CopyMagickString(image->filename,filename,MagickPathExtent);
    399     }
    400   /*
    401     Open image map.
    402   */
    403   status=OpenBlob(write_info,image,WriteBinaryBlobMode,exception);
    404   if (status == MagickFalse)
    405     return(status);
    406   write_info=DestroyImageInfo(write_info);
    407   /*
    408     Determine the size and location of each image tile.
    409   */
    410   SetGeometry(image,&geometry);
    411   if (image->montage != (char *) NULL)
    412     (void) ParseAbsoluteGeometry(image->montage,&geometry);
    413   /*
    414     Write an image map.
    415   */
    416   (void) FormatLocaleString(buffer,MagickPathExtent,
    417     "<map id=\"%s\" name=\"%s\">\n",mapname,mapname);
    418   (void) WriteBlobString(image,buffer);
    419   (void) FormatLocaleString(buffer,MagickPathExtent,"  <area href=\"%s",url);
    420   (void) WriteBlobString(image,buffer);
    421   if (image->directory == (char *) NULL)
    422     {
    423       (void) FormatLocaleString(buffer,MagickPathExtent,
    424         "%s\" shape=\"rect\" coords=\"0,0,%.20g,%.20g\" alt=\"\" />\n",
    425         image->filename,(double) geometry.width-1,(double) geometry.height-1);
    426       (void) WriteBlobString(image,buffer);
    427     }
    428   else
    429     for (p=image->directory; *p != '\0'; p++)
    430       if (*p != '\n')
    431         (void) WriteBlobByte(image,(unsigned char) *p);
    432       else
    433         {
    434           (void) FormatLocaleString(buffer,MagickPathExtent,"\" shape=\"rect\""
    435             " coords=\"%.20g,%.20g,%.20g,%.20g\" alt=\"\" />\n",
    436             (double) geometry.x,(double) geometry.y,geometry.x+(double)
    437             geometry.width-1,geometry.y+(double) geometry.height-1);
    438           (void) WriteBlobString(image,buffer);
    439           if (*(p+1) != '\0')
    440             {
    441               (void) FormatLocaleString(buffer,MagickPathExtent,
    442                 "  <area href=%s\"",url);
    443               (void) WriteBlobString(image,buffer);
    444             }
    445           geometry.x+=(ssize_t) geometry.width;
    446           if ((geometry.x+4) >= (ssize_t) image->columns)
    447             {
    448               geometry.x=0;
    449               geometry.y+=(ssize_t) geometry.height;
    450             }
    451         }
    452   (void) WriteBlobString(image,"</map>\n");
    453   (void) CloseBlob(image);
    454   (void) CopyMagickString(image->filename,filename,MagickPathExtent);
    455   return(status);
    456 }
    457