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