html.c revision 386d8ba8d33c6860ecaf9532706c855e8ae34aab
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-2015 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 "MagickCore/studio.h" 44#include "MagickCore/blob.h" 45#include "MagickCore/blob-private.h" 46#include "MagickCore/color-private.h" 47#include "MagickCore/colorspace.h" 48#include "MagickCore/colorspace-private.h" 49#include "MagickCore/constitute.h" 50#include "MagickCore/exception.h" 51#include "MagickCore/exception-private.h" 52#include "MagickCore/geometry.h" 53#include "MagickCore/list.h" 54#include "MagickCore/magick.h" 55#include "MagickCore/memory_.h" 56#include "MagickCore/paint.h" 57#include "MagickCore/property.h" 58#include "MagickCore/quantum-private.h" 59#include "MagickCore/static.h" 60#include "MagickCore/string_.h" 61#include "MagickCore/module.h" 62#include "MagickCore/utility.h" 63 64/* 65 Forward declarations. 66*/ 67static MagickBooleanType 68 WriteHTMLImage(const ImageInfo *,Image *,ExceptionInfo *); 69 70/* 71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 72% % 73% % 74% % 75% I s H T M L % 76% % 77% % 78% % 79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 80% 81% IsHTML() returns MagickTrue if the image format type, identified by the 82% magick string, is HTML. 83% 84% The format of the IsHTML method is: 85% 86% MagickBooleanType IsHTML(const unsigned char *magick,const size_t length) 87% 88% A description of each parameter follows: 89% 90% o magick: compare image format pattern against these bytes. 91% 92% o length: Specifies the length of the magick string. 93% 94*/ 95static MagickBooleanType IsHTML(const unsigned char *magick,const size_t length) 96{ 97 if (length < 5) 98 return(MagickFalse); 99 if (LocaleNCompare((char *) magick,"<html",5) == 0) 100 return(MagickTrue); 101 return(MagickFalse); 102} 103 104/* 105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 106% % 107% % 108% % 109% R e g i s t e r H T M L I m a g e % 110% % 111% % 112% % 113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 114% 115% RegisterHTMLImage() adds properties for the HTML image format to 116% the list of supported formats. The properties include the image format 117% tag, a method to read and/or write the format, whether the format 118% supports the saving of more than one frame to the same file or blob, 119% whether the format supports native in-memory I/O, and a brief 120% description of the format. 121% 122% The format of the RegisterHTMLImage method is: 123% 124% size_t RegisterHTMLImage(void) 125% 126*/ 127ModuleExport size_t RegisterHTMLImage(void) 128{ 129 MagickInfo 130 *entry; 131 132 entry=SetMagickInfo("HTM"); 133 entry->encoder=(EncodeImageHandler *) WriteHTMLImage; 134 entry->magick=(IsImageFormatHandler *) IsHTML; 135 entry->flags^=CoderAdjoinFlag; 136 entry->description=ConstantString( 137 "Hypertext Markup Language and a client-side image map"); 138 entry->module=ConstantString("HTML"); 139 (void) RegisterMagickInfo(entry); 140 entry=SetMagickInfo("HTML"); 141 entry->encoder=(EncodeImageHandler *) WriteHTMLImage; 142 entry->magick=(IsImageFormatHandler *) IsHTML; 143 entry->flags^=CoderAdjoinFlag; 144 entry->description=ConstantString( 145 "Hypertext Markup Language and a client-side image map"); 146 entry->module=ConstantString("HTML"); 147 (void) RegisterMagickInfo(entry); 148 entry=SetMagickInfo("SHTML"); 149 entry->encoder=(EncodeImageHandler *) WriteHTMLImage; 150 entry->magick=(IsImageFormatHandler *) IsHTML; 151 entry->flags^=CoderAdjoinFlag; 152 entry->description=ConstantString( 153 "Hypertext Markup Language and a client-side image map"); 154 entry->module=ConstantString("HTML"); 155 (void) RegisterMagickInfo(entry); 156 return(MagickImageCoderSignature); 157} 158 159/* 160%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 161% % 162% % 163% % 164% U n r e g i s t e r H T M L I m a g e % 165% % 166% % 167% % 168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 169% 170% UnregisterHTMLImage() removes format registrations made by the 171% HTML module from the list of supported formats. 172% 173% The format of the UnregisterHTMLImage method is: 174% 175% UnregisterHTMLImage(void) 176% 177*/ 178ModuleExport void UnregisterHTMLImage(void) 179{ 180 (void) UnregisterMagickInfo("HTM"); 181 (void) UnregisterMagickInfo("HTML"); 182 (void) UnregisterMagickInfo("SHTML"); 183} 184 185/* 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*/ 212static MagickBooleanType WriteHTMLImage(const ImageInfo *image_info, 213 Image *image,ExceptionInfo *exception) 214{ 215 char 216 basename[MaxTextExtent], 217 buffer[MaxTextExtent], 218 filename[MaxTextExtent], 219 mapname[MaxTextExtent], 220 url[MaxTextExtent]; 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 == MagickSignature); 242 assert(image != (Image *) NULL); 243 assert(image->signature == MagickSignature); 244 if (image->debug != MagickFalse) 245 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 246 image_info->filename); 247 assert(exception != (ExceptionInfo *) NULL); 248 assert(exception->signature == MagickSignature); 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,MaxTextExtent); 266 (void) ConcatenateMagickString(url,":",MaxTextExtent); 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,MaxTextExtent); 271 } 272 } 273 /* 274 Refer to image map file. 275 */ 276 (void) CopyMagickString(filename,image->filename,MaxTextExtent); 277 AppendImageFormat("map",filename); 278 GetPathComponent(filename,BasePath,basename); 279 (void) CopyMagickString(mapname,basename,MaxTextExtent); 280 (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent); 281 (void) CopyMagickString(filename,image->filename,MaxTextExtent); 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,MaxTextExtent,"<title>%s</title>\n", 311 value); 312 else 313 { 314 GetPathComponent(filename,BasePath,basename); 315 (void) FormatLocaleString(buffer,MaxTextExtent, 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,MaxTextExtent,"<h1>%s</h1>\n", 322 image->filename); 323 (void) WriteBlobString(image,buffer); 324 (void) WriteBlobString(image,"<div>\n"); 325 (void) CopyMagickString(filename,image->filename,MaxTextExtent); 326 AppendImageFormat("png",filename); 327 (void) FormatLocaleString(buffer,MaxTextExtent,"<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,MaxTextExtent, 341 "<map id=\"%s\" name=\"%s\">\n",mapname,mapname); 342 (void) WriteBlobString(image,buffer); 343 (void) FormatLocaleString(buffer,MaxTextExtent," <area href=\"%s",url); 344 (void) WriteBlobString(image,buffer); 345 if (image->directory == (char *) NULL) 346 { 347 (void) FormatLocaleString(buffer,MaxTextExtent, 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,MaxTextExtent,"\" 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,MaxTextExtent, 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,MaxTextExtent); 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,MaxTextExtent); 387 AppendImageFormat("png",image->filename); 388 next=GetNextImageInList(image); 389 image->next=NewImageList(); 390 (void) CopyMagickString(image->magick,"PNG",MaxTextExtent); 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",MaxTextExtent); 398 (void) CopyMagickString(image->filename,filename,MaxTextExtent); 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,MaxTextExtent, 417 "<map id=\"%s\" name=\"%s\">\n",mapname,mapname); 418 (void) WriteBlobString(image,buffer); 419 (void) FormatLocaleString(buffer,MaxTextExtent," <area href=\"%s",url); 420 (void) WriteBlobString(image,buffer); 421 if (image->directory == (char *) NULL) 422 { 423 (void) FormatLocaleString(buffer,MaxTextExtent, 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,MaxTextExtent,"\" 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,MaxTextExtent, 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,MaxTextExtent); 455 return(status); 456} 457