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