|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% H H TTTTT M M L %
|
|
|
% H H T MM MM L %
|
|
|
% HHHHH T M M M L %
|
|
|
% H H T M M L %
|
|
|
% H H T M M LLLLL %
|
|
|
% %
|
|
|
% %
|
|
|
% Write A Client-Side Image Map Using %
|
|
|
% Image Montage & Directory Information. %
|
|
|
% %
|
|
|
% Software Design %
|
|
|
% Cristy %
|
|
|
% July 1992 %
|
|
|
% %
|
|
|
% %
|
|
|
% Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
|
|
|
% dedicated to making software imaging solutions freely available. %
|
|
|
% %
|
|
|
% You may not use this file except in compliance with the License. You may %
|
|
|
% obtain a copy of the License at %
|
|
|
% %
|
|
|
% https://imagemagick.org/script/license.php %
|
|
|
% %
|
|
|
% Unless required by applicable law or agreed to in writing, software %
|
|
|
% distributed under the License is distributed on an "AS IS" BASIS, %
|
|
|
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
|
|
|
% See the License for the specific language governing permissions and %
|
|
|
% limitations under the License. %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
%
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
Include declarations.
|
|
|
*/
|
|
|
#include "MagickCore/studio.h"
|
|
|
#include "MagickCore/blob.h"
|
|
|
#include "MagickCore/blob-private.h"
|
|
|
#include "MagickCore/color-private.h"
|
|
|
#include "MagickCore/colorspace.h"
|
|
|
#include "MagickCore/colorspace-private.h"
|
|
|
#include "MagickCore/constitute.h"
|
|
|
#include "MagickCore/exception.h"
|
|
|
#include "MagickCore/exception-private.h"
|
|
|
#include "MagickCore/geometry.h"
|
|
|
#include "MagickCore/list.h"
|
|
|
#include "MagickCore/magick.h"
|
|
|
#include "MagickCore/memory_.h"
|
|
|
#include "MagickCore/paint.h"
|
|
|
#include "MagickCore/property.h"
|
|
|
#include "MagickCore/quantum-private.h"
|
|
|
#include "MagickCore/static.h"
|
|
|
#include "MagickCore/string_.h"
|
|
|
#include "MagickCore/module.h"
|
|
|
#include "MagickCore/utility.h"
|
|
|
|
|
|
/*
|
|
|
Forward declarations.
|
|
|
*/
|
|
|
static MagickBooleanType
|
|
|
WriteHTMLImage(const ImageInfo *,Image *,ExceptionInfo *);
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% I s H T M L %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% IsHTML() returns MagickTrue if the image format type, identified by the
|
|
|
% magick string, is HTML.
|
|
|
%
|
|
|
% The format of the IsHTML method is:
|
|
|
%
|
|
|
% MagickBooleanType IsHTML(const unsigned char *magick,const size_t length)
|
|
|
%
|
|
|
% A description of each parameter follows:
|
|
|
%
|
|
|
% o magick: compare image format pattern against these bytes.
|
|
|
%
|
|
|
% o length: Specifies the length of the magick string.
|
|
|
%
|
|
|
*/
|
|
|
static MagickBooleanType IsHTML(const unsigned char *magick,const size_t length)
|
|
|
{
|
|
|
if (length < 6)
|
|
|
return(MagickFalse);
|
|
|
if (LocaleNCompare((char *) magick+1,"html",5) == 0)
|
|
|
return(MagickTrue);
|
|
|
return(MagickFalse);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% R e g i s t e r H T M L I m a g e %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% RegisterHTMLImage() adds properties for the HTML image format to
|
|
|
% the list of supported formats. The properties include the image format
|
|
|
% tag, a method to read and/or write the format, whether the format
|
|
|
% supports the saving of more than one frame to the same file or blob,
|
|
|
% whether the format supports native in-memory I/O, and a brief
|
|
|
% description of the format.
|
|
|
%
|
|
|
% The format of the RegisterHTMLImage method is:
|
|
|
%
|
|
|
% size_t RegisterHTMLImage(void)
|
|
|
%
|
|
|
*/
|
|
|
ModuleExport size_t RegisterHTMLImage(void)
|
|
|
{
|
|
|
MagickInfo
|
|
|
*entry;
|
|
|
|
|
|
entry=AcquireMagickInfo("HTML","HTM",
|
|
|
"Hypertext Markup Language and a client-side image map");
|
|
|
entry->encoder=(EncodeImageHandler *) WriteHTMLImage;
|
|
|
entry->magick=(IsImageFormatHandler *) IsHTML;
|
|
|
entry->flags^=CoderAdjoinFlag;
|
|
|
(void) RegisterMagickInfo(entry);
|
|
|
entry=AcquireMagickInfo("HTML","HTML",
|
|
|
"Hypertext Markup Language and a client-side image map");
|
|
|
entry->encoder=(EncodeImageHandler *) WriteHTMLImage;
|
|
|
entry->magick=(IsImageFormatHandler *) IsHTML;
|
|
|
entry->flags^=CoderAdjoinFlag;
|
|
|
(void) RegisterMagickInfo(entry);
|
|
|
entry=AcquireMagickInfo("HTML","SHTML",
|
|
|
"Hypertext Markup Language and a client-side image map");
|
|
|
entry->encoder=(EncodeImageHandler *) WriteHTMLImage;
|
|
|
entry->magick=(IsImageFormatHandler *) IsHTML;
|
|
|
entry->flags^=CoderAdjoinFlag;
|
|
|
(void) RegisterMagickInfo(entry);
|
|
|
return(MagickImageCoderSignature);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% U n r e g i s t e r H T M L I m a g e %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% UnregisterHTMLImage() removes format registrations made by the
|
|
|
% HTML module from the list of supported formats.
|
|
|
%
|
|
|
% The format of the UnregisterHTMLImage method is:
|
|
|
%
|
|
|
% UnregisterHTMLImage(void)
|
|
|
%
|
|
|
*/
|
|
|
ModuleExport void UnregisterHTMLImage(void)
|
|
|
{
|
|
|
(void) UnregisterMagickInfo("HTM");
|
|
|
(void) UnregisterMagickInfo("HTML");
|
|
|
(void) UnregisterMagickInfo("SHTML");
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
% W r i t e H T M L I m a g e %
|
|
|
% %
|
|
|
% %
|
|
|
% %
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
%
|
|
|
% WriteHTMLImage() writes an image in the HTML encoded image format.
|
|
|
%
|
|
|
% The format of the WriteHTMLImage method is:
|
|
|
%
|
|
|
% MagickBooleanType WriteHTMLImage(const ImageInfo *image_info,
|
|
|
% Image *image,ExceptionInfo *exception)
|
|
|
%
|
|
|
% A description of each parameter follows.
|
|
|
%
|
|
|
% o image_info: the image info.
|
|
|
%
|
|
|
% o image: The image.
|
|
|
%
|
|
|
% o exception: return any errors or warnings in this structure.
|
|
|
%
|
|
|
*/
|
|
|
static MagickBooleanType WriteHTMLImage(const ImageInfo *image_info,
|
|
|
Image *image,ExceptionInfo *exception)
|
|
|
{
|
|
|
char
|
|
|
basename[MagickPathExtent],
|
|
|
buffer[MagickPathExtent],
|
|
|
filename[MagickPathExtent],
|
|
|
mapname[MagickPathExtent],
|
|
|
url[MagickPathExtent];
|
|
|
|
|
|
Image
|
|
|
*next;
|
|
|
|
|
|
ImageInfo
|
|
|
*write_info;
|
|
|
|
|
|
MagickBooleanType
|
|
|
status;
|
|
|
|
|
|
RectangleInfo
|
|
|
geometry;
|
|
|
|
|
|
char
|
|
|
*p;
|
|
|
|
|
|
/*
|
|
|
Open image.
|
|
|
*/
|
|
|
assert(image_info != (const ImageInfo *) NULL);
|
|
|
assert(image_info->signature == MagickCoreSignature);
|
|
|
assert(image != (Image *) NULL);
|
|
|
assert(image->signature == MagickCoreSignature);
|
|
|
if (image->debug != MagickFalse)
|
|
|
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
|
|
|
image_info->filename);
|
|
|
assert(exception != (ExceptionInfo *) NULL);
|
|
|
assert(exception->signature == MagickCoreSignature);
|
|
|
status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
|
|
|
if (status == MagickFalse)
|
|
|
return(status);
|
|
|
(void) CloseBlob(image);
|
|
|
(void) TransformImageColorspace(image,sRGBColorspace,exception);
|
|
|
*url='\0';
|
|
|
if ((LocaleCompare(image_info->magick,"FTP") == 0) ||
|
|
|
(LocaleCompare(image_info->magick,"HTTP") == 0))
|
|
|
{
|
|
|
/*
|
|
|
Extract URL base from filename.
|
|
|
*/
|
|
|
p=strrchr(image->filename,'/');
|
|
|
if (p != (char *) NULL)
|
|
|
{
|
|
|
p++;
|
|
|
(void) CopyMagickString(url,image_info->magick,MagickPathExtent);
|
|
|
(void) ConcatenateMagickString(url,":",MagickPathExtent);
|
|
|
url[strlen(url)+p-image->filename]='\0';
|
|
|
(void) ConcatenateMagickString(url,image->filename,
|
|
|
p-image->filename+2);
|
|
|
(void) CopyMagickString(image->filename,p,MagickPathExtent);
|
|
|
}
|
|
|
}
|
|
|
/*
|
|
|
Refer to image map file.
|
|
|
*/
|
|
|
(void) CopyMagickString(filename,image->filename,MagickPathExtent);
|
|
|
AppendImageFormat("map",filename);
|
|
|
GetPathComponent(filename,BasePath,basename);
|
|
|
(void) CopyMagickString(mapname,basename,MagickPathExtent);
|
|
|
(void) CopyMagickString(image->filename,image_info->filename,
|
|
|
MagickPathExtent);
|
|
|
(void) CopyMagickString(filename,image->filename,MagickPathExtent);
|
|
|
write_info=CloneImageInfo(image_info);
|
|
|
*write_info->magick='\0';
|
|
|
write_info->adjoin=MagickTrue;
|
|
|
status=MagickTrue;
|
|
|
if (LocaleCompare(image_info->magick,"SHTML") != 0)
|
|
|
{
|
|
|
const char
|
|
|
*value;
|
|
|
|
|
|
/*
|
|
|
Open output image file.
|
|
|
*/
|
|
|
assert(exception != (ExceptionInfo *) NULL);
|
|
|
status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
|
|
|
if (status == MagickFalse)
|
|
|
return(status);
|
|
|
/*
|
|
|
Write the HTML image file.
|
|
|
*/
|
|
|
(void) WriteBlobString(image,"<?xml version=\"1.0\" "
|
|
|
"encoding=\"US-ASCII\"?>\n");
|
|
|
(void) WriteBlobString(image,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML "
|
|
|
"1.0 Strict//EN\" "
|
|
|
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n");
|
|
|
(void) WriteBlobString(image,"<html>\n");
|
|
|
(void) WriteBlobString(image,"<head>\n");
|
|
|
value=GetImageProperty(image,"label",exception);
|
|
|
if (value != (const char *) NULL)
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,"<title>%s</title>\n",
|
|
|
value);
|
|
|
else
|
|
|
{
|
|
|
GetPathComponent(filename,BasePath,basename);
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,
|
|
|
"<title>%s</title>\n",basename);
|
|
|
}
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
(void) WriteBlobString(image,"</head>\n");
|
|
|
(void) WriteBlobString(image,"<body style=\"text-align: center;\">\n");
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,"<h1>%s</h1>\n",
|
|
|
image->filename);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
(void) WriteBlobString(image,"<div>\n");
|
|
|
(void) CopyMagickString(filename,image->filename,MagickPathExtent);
|
|
|
AppendImageFormat("png",filename);
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,"<img usemap=\"#%s\" "
|
|
|
"src=\"%s\" style=\"border: 0;\" alt=\"Image map\" />\n",mapname,
|
|
|
filename);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
/*
|
|
|
Determine the size and location of each image tile.
|
|
|
*/
|
|
|
SetGeometry(image,&geometry);
|
|
|
if (image->montage != (char *) NULL)
|
|
|
(void) ParseAbsoluteGeometry(image->montage,&geometry);
|
|
|
/*
|
|
|
Write an image map.
|
|
|
*/
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,
|
|
|
"<map id=\"%s\" name=\"%s\">\n",mapname,mapname);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent," <area href=\"%s",
|
|
|
url);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
if (image->directory == (char *) NULL)
|
|
|
{
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,
|
|
|
"%s\" shape=\"rect\" coords=\"0,0,%.20g,%.20g\" alt=\"\" />\n",
|
|
|
image->filename,(double) geometry.width-1,(double) geometry.height-
|
|
|
1);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
}
|
|
|
else
|
|
|
for (p=image->directory; *p != '\0'; p++)
|
|
|
if (*p != '\xff')
|
|
|
(void) WriteBlobByte(image,(unsigned char) *p);
|
|
|
else
|
|
|
{
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,"\" shape="
|
|
|
"\"rect\" coords=\"%.20g,%.20g,%.20g,%.20g\" alt=\"\" />\n",
|
|
|
(double) geometry.x,(double) geometry.y,(double) (geometry.x+
|
|
|
geometry.width-1),(double) (geometry.y+geometry.height-1));
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
if (*(p+1) != '\0')
|
|
|
{
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,
|
|
|
" <area href=%s\"",url);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
}
|
|
|
geometry.x+=(ssize_t) geometry.width;
|
|
|
if ((geometry.x+4) >= (ssize_t) image->columns)
|
|
|
{
|
|
|
geometry.x=0;
|
|
|
geometry.y+=(ssize_t) geometry.height;
|
|
|
}
|
|
|
}
|
|
|
(void) WriteBlobString(image,"</map>\n");
|
|
|
(void) CopyMagickString(filename,image->filename,MagickPathExtent);
|
|
|
(void) WriteBlobString(image,"</div>\n");
|
|
|
(void) WriteBlobString(image,"</body>\n");
|
|
|
(void) WriteBlobString(image,"</html>\n");
|
|
|
(void) CloseBlob(image);
|
|
|
/*
|
|
|
Write the image as PNG.
|
|
|
*/
|
|
|
(void) CopyMagickString(image->filename,filename,MagickPathExtent);
|
|
|
AppendImageFormat("png",image->filename);
|
|
|
next=GetNextImageInList(image);
|
|
|
image->next=NewImageList();
|
|
|
(void) CopyMagickString(image->magick,"PNG",MagickPathExtent);
|
|
|
(void) WriteImage(write_info,image,exception);
|
|
|
image->next=next;
|
|
|
/*
|
|
|
Determine image map filename.
|
|
|
*/
|
|
|
GetPathComponent(image->filename,BasePath,filename);
|
|
|
(void) ConcatenateMagickString(filename,"_map.shtml",MagickPathExtent);
|
|
|
(void) CopyMagickString(image->filename,filename,MagickPathExtent);
|
|
|
}
|
|
|
/*
|
|
|
Open image map.
|
|
|
*/
|
|
|
status=OpenBlob(write_info,image,WriteBinaryBlobMode,exception);
|
|
|
if (status == MagickFalse)
|
|
|
return(status);
|
|
|
write_info=DestroyImageInfo(write_info);
|
|
|
/*
|
|
|
Determine the size and location of each image tile.
|
|
|
*/
|
|
|
SetGeometry(image,&geometry);
|
|
|
if (image->montage != (char *) NULL)
|
|
|
(void) ParseAbsoluteGeometry(image->montage,&geometry);
|
|
|
/*
|
|
|
Write an image map.
|
|
|
*/
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,
|
|
|
"<map id=\"%s\" name=\"%s\">\n",mapname,mapname);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent," <area href=\"%s",url);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
if (image->directory == (char *) NULL)
|
|
|
{
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,
|
|
|
"%s\" shape=\"rect\" coords=\"0,0,%.20g,%.20g\" alt=\"\" />\n",
|
|
|
image->filename,(double) geometry.width-1,(double) geometry.height-1);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
}
|
|
|
else
|
|
|
for (p=image->directory; *p != '\0'; p++)
|
|
|
if (*p != '\xff')
|
|
|
(void) WriteBlobByte(image,(unsigned char) *p);
|
|
|
else
|
|
|
{
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,"\" shape=\"rect\""
|
|
|
" coords=\"%.20g,%.20g,%.20g,%.20g\" alt=\"\" />\n",
|
|
|
(double) geometry.x,(double) geometry.y,geometry.x+(double)
|
|
|
geometry.width-1,geometry.y+(double) geometry.height-1);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
if (*(p+1) != '\0')
|
|
|
{
|
|
|
(void) FormatLocaleString(buffer,MagickPathExtent,
|
|
|
" <area href=%s\"",url);
|
|
|
(void) WriteBlobString(image,buffer);
|
|
|
}
|
|
|
geometry.x+=(ssize_t) geometry.width;
|
|
|
if ((geometry.x+4) >= (ssize_t) image->columns)
|
|
|
{
|
|
|
geometry.x=0;
|
|
|
geometry.y+=(ssize_t) geometry.height;
|
|
|
}
|
|
|
}
|
|
|
(void) WriteBlobString(image,"</map>\n");
|
|
|
(void) CloseBlob(image);
|
|
|
(void) CopyMagickString(image->filename,filename,MagickPathExtent);
|
|
|
return(status);
|
|
|
}
|