/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%                            PPPP   EEEEE  SSSSS                              %
%                            P   P  E      SS                                 %
%                            PPPP   EEE     SSS                               %
%                            P      E         SS                              %
%                            P      EEEEE  SSSSS                              %
%                                                                             %
%                                                                             %
%                     Read/Write Brother PES Image Format                     %
%                                                                             %
%                              Software Design                                %
%                                   Cristy                                    %
%                                 July 2009                                   %
%                                                                             %
%                                                                             %
%  Copyright @ 2009 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.                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  The PES format was derived from Robert Heel's PHP script (see
%  http://bobosch.dyndns.org/embroidery/showFile.php?pes.php) and pesconvert
%  (see http://torvalds-family.blogspot.com/2010/01/embroidery-gaah.html).
%
*/

/*
  Include declarations.
*/
#include "MagickCore/studio.h"
#include "MagickCore/property.h"
#include "MagickCore/blob.h"
#include "MagickCore/blob-private.h"
#include "MagickCore/cache.h"
#include "MagickCore/client.h"
#include "MagickCore/colorspace.h"
#include "MagickCore/constitute.h"
#include "MagickCore/decorate.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/gem.h"
#include "MagickCore/geometry.h"
#include "MagickCore/image.h"
#include "MagickCore/image-private.h"
#include "MagickCore/list.h"
#include "MagickCore/magick.h"
#include "MagickCore/memory_.h"
#include "MagickCore/monitor.h"
#include "MagickCore/monitor-private.h"
#include "MagickCore/montage.h"
#include "MagickCore/resize.h"
#include "MagickCore/shear.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/static.h"
#include "MagickCore/string_.h"
#include "MagickCore/module.h"
#include "MagickCore/resource_.h"
#include "MagickCore/transform.h"
#include "MagickCore/utility.h"

/*
  Typedef declarations.
*/
typedef struct _PESColorInfo
{
  const unsigned char
    red,
    green,
    blue,
    alpha;
} PESColorInfo;

typedef struct _PESBlockInfo
{
  const PESColorInfo
    *color;

  ssize_t
    offset;
} PESBlockInfo;

/*
  PES Colors.
*/
static const PESColorInfo
  PESColor[256] =
  {
    {   0,   0,   0, 1 },
    {  14,  31, 124, 1 },
    {  10,  85, 163, 1 },
    {  48, 135, 119, 1 },
    {  75, 107, 175, 1 },
    { 237,  23,  31, 1 },
    { 209,  92,   0, 1 },
    { 145,  54, 151, 1 },
    { 228, 154, 203, 1 },
    { 145,  95, 172, 1 },
    { 157, 214, 125, 1 },
    { 232, 169,   0, 1 },
    { 254, 186,  53, 1 },
    { 255, 255,   0, 1 },
    { 112, 188,  31, 1 },
    { 192, 148,   0, 1 },
    { 168, 168, 168, 1 },
    { 123, 111,   0, 1 },
    { 255, 255, 179, 1 },
    {  79,  85,  86, 1 },
    {   0,   0,   0, 1 },
    {  11,  61, 145, 1 },
    { 119,   1, 118, 1 },
    {  41,  49,  51, 1 },
    {  42,  19,   1, 1 },
    { 246,  74, 138, 1 },
    { 178, 118,  36, 1 },
    { 252, 187, 196, 1 },
    { 254,  55,  15, 1 },
    { 240, 240, 240, 1 },
    { 106,  28, 138, 1 },
    { 168, 221, 196, 1 },
    {  37, 132, 187, 1 },
    { 254, 179,  67, 1 },
    { 255, 240, 141, 1 },
    { 208, 166,  96, 1 },
    { 209,  84,   0, 1 },
    { 102, 186,  73, 1 },
    {  19,  74,  70, 1 },
    { 135, 135, 135, 1 },
    { 216, 202, 198, 1 },
    {  67,  86,   7, 1 },
    { 254, 227, 197, 1 },
    { 249, 147, 188, 1 },
    {   0,  56,  34, 1 },
    { 178, 175, 212, 1 },
    { 104, 106, 176, 1 },
    { 239, 227, 185, 1 },
    { 247,  56, 102, 1 },
    { 181,  76, 100, 1 },
    {  19,  43,  26, 1 },
    { 199,   1,  85, 1 },
    { 254, 158,  50, 1 },
    { 168, 222, 235, 1 },
    {   0, 103,  26, 1 },
    {  78,  41, 144, 1 },
    {  47, 126,  32, 1 },
    { 253, 217, 222, 1 },
    { 255, 217,  17, 1 },
    {   9,  91, 166, 1 },
    { 240, 249, 112, 1 },
    { 227, 243,  91, 1 },
    { 255, 200, 100, 1 },
    { 255, 200, 150, 1 },
    { 255, 200, 200, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 },
    {   0,   0,   0, 1 }
  };

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   I s P E S                                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  IsPES() returns MagickTrue if the image format type, identified by the
%  magick string, is PES.
%
%  The format of the IsPES method is:
%
%      MagickBooleanType IsPES(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 IsPES(const unsigned char *magick,const size_t length)
{
  if (length < 4)
    return(MagickFalse);
  if (LocaleNCompare((const char *) magick,"#PES",4) == 0)
    return(MagickTrue);
  return(MagickFalse);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e a d P E S I m a g e                                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ReadPESImage() reads a Brother PES image file and returns it.  It allocates
%  the memory necessary for the new Image structure and returns a pointer to
%  the new image.
%
%  The format of the ReadPESImage method is:
%
%      image=ReadPESImage(image_info)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadPESImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
  char
    filename[MagickPathExtent];

  FILE
    *file;

  Image
    *image;

  ImageInfo
    *read_info;

  int
    delta_x,
    delta_y,
    j,
    unique_file,
    x,
    y;

  MagickBooleanType
    status;

  PESBlockInfo
    blocks[256];

  PointInfo
    *stitches;

  SegmentInfo
    bounds;

  ssize_t
    i;

  size_t
    number_blocks,
    number_colors,
    number_stitches;

  ssize_t
    count,
    offset;

  unsigned char
    magick[4],
    version[4];

  /*
    Open image file.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  if (IsEventLogging() != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  image=AcquireImage(image_info,exception);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  /*
    Verify PES identifier.
  */
  count=ReadBlob(image,4,magick);
  if ((count != 4) || (LocaleNCompare((char *) magick,"#PES",4) != 0))
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
  count=ReadBlob(image,4,version);
  offset=ReadBlobLSBSignedLong(image);
  if (DiscardBlobBytes(image,(MagickSizeType) (offset+36)) == MagickFalse)
    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
      image->filename);
  if (EOFBlob(image) != MagickFalse)
    ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
  /*
    Get PES colors.
  */
  number_colors=(size_t) ReadBlobByte(image)+1;
  for (i=0; i < (ssize_t) number_colors; i++)
  {
    j=ReadBlobByte(image);
    blocks[i].color=PESColor+(j < 0 ? 0 : j);
    blocks[i].offset=0;
  }
  for ( ; i < 256L; i++)
  {
    blocks[i].offset=0;
    blocks[i].color=PESColor;
  }
  if (DiscardBlobBytes(image,532L-number_colors-21) == MagickFalse)
    ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
      image->filename);
  if (EOFBlob(image) != MagickFalse)
    ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
  /*
    Stitch away.
  */
  number_stitches=64;
  stitches=(PointInfo *) AcquireQuantumMemory(number_stitches,
    sizeof(*stitches));
  if (stitches == (PointInfo *) NULL)
    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
  bounds.x1=65535.0;
  bounds.y1=65535.0;
  bounds.x2=(-65535.0);
  bounds.y2=(-65535.0);
  i=0;
  j=0;
  delta_x=0;
  delta_y=0;
  while (EOFBlob(image) == MagickFalse)
  {
    x=ReadBlobByte(image);
    y=ReadBlobByte(image);
    if ((x == 0xff) && (y == 0))
      break;
    if ((x == 254) && (y == 176))
      {
        /*
          Start a new stitch block.
        */
        j++;
        blocks[j].offset=(ssize_t) i;
        if (j >= 255)
          {
            stitches=(PointInfo *) RelinquishMagickMemory(stitches);
            ThrowReaderException(ResourceLimitError,"CorruptImage");
          }
        (void) ReadBlobByte(image);
        continue;
      }
    if ((x & 0x80) == 0)
      {
        /*
          Normal stitch.
        */
        if ((x & 0x40) != 0)
          x-=0x80;
      }
    else
      {
        /*
          Jump stitch.
        */
        x=((x & 0x0f) << 8)+y;
        if ((x & 0x800) != 0)
          x-=0x1000;
        y=ReadBlobByte(image);
      }
    if ((y & 0x80) == 0)
      {
        /*
          Normal stitch.
        */
        if ((y & 0x40) != 0)
          y-=0x80;
      }
    else
      {
        /*
          Jump stitch.
        */
        y=((y & 0x0f) << 8)+ReadBlobByte(image);
        if ((y & 0x800) != 0)
          y-=0x1000;
      }
    /*
      Note stitch (x,y).
    */
    x+=delta_x;
    y+=delta_y;
    delta_x=x;
    delta_y=y;
    stitches[i].x=(double) x;
    stitches[i].y=(double) y;
    if ((double) x < bounds.x1)
      bounds.x1=(double) x;
    if ((double) x > bounds.x2)
      bounds.x2=(double) x;
    if ((double) y < bounds.y1)
      bounds.y1=(double) y;
    if ((double) y > bounds.y2)
      bounds.y2=(double) y;
    i++;
    if (i >= (ssize_t) number_stitches)
      {
        /*
          Make room for more stitches.
        */
        number_stitches<<=1;
        stitches=(PointInfo *)  ResizeQuantumMemory(stitches,(size_t)
          number_stitches,sizeof(*stitches));
        if (stitches == (PointInfo *) NULL)
          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
     }
  }
  j++;
  blocks[j].offset=(ssize_t) i;
  number_blocks=(size_t) j;
  image->columns=bounds.x2-bounds.x1;
  image->rows=bounds.y2-bounds.y1;
  status=SetImageExtent(image,image->columns,image->rows,exception);
  if (status == MagickFalse)
    {
      stitches=(PointInfo *) RelinquishMagickMemory(stitches);
      return(DestroyImageList(image));
    }
  /*
    Write stitches as SVG file.
  */
  file=(FILE *) NULL;
  unique_file=AcquireUniqueFileResource(filename);
  if (unique_file != -1)
    file=fdopen(unique_file,"wb");
  if ((unique_file == -1) || (file == (FILE *) NULL))
    ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile");
  (void) FormatLocaleFile(file,"<?xml version=\"1.0\"?>\n");
  (void) FormatLocaleFile(file,"<svg xmlns=\"http://www.w3.org/2000/svg\" "
    "xlink=\"http://www.w3.org/1999/xlink\" "
    "ev=\"http://www.w3.org/2001/xml-events\" version=\"1.1\" "
    "baseProfile=\"full\" width=\"%g\" height=\"%g\">\n",(double)
    image->columns,(double) image->rows);
  for (i=0; i < (ssize_t) number_blocks; i++)
  {
    offset=blocks[i].offset;
    (void) FormatLocaleFile(file,"  <path stroke=\"#%02x%02x%02x\" "
      "fill=\"none\" d=\"M %g %g",blocks[i].color->red,blocks[i].color->green,
      blocks[i].color->blue,stitches[offset].x-bounds.x1,
      stitches[offset].y-bounds.y1);
    for (j=1; j < (ssize_t) (blocks[i+1].offset-offset); j++)
      (void) FormatLocaleFile(file," L %g %g",stitches[offset+j].x-bounds.x1,
        stitches[offset+j].y-bounds.y1);
    (void) FormatLocaleFile(file,"\"/>\n");
  }
  (void) FormatLocaleFile(file,"</svg>\n");
  (void) fclose(file);
  stitches=(PointInfo *) RelinquishMagickMemory(stitches);
  (void) CloseBlob(image);
  image=DestroyImage(image);
  /*
    Read SVG file.
  */
  read_info=CloneImageInfo(image_info);
  SetImageInfoBlob(read_info,(void *) NULL,0);
  (void) FormatLocaleString(read_info->filename,MagickPathExtent,"svg:%s",
    filename);
  image=ReadImage(read_info,exception);
  if (image != (Image *) NULL)
    {
      (void) CopyMagickString(image->filename,image_info->filename,
        MagickPathExtent);
      (void) CopyMagickString(image->magick_filename,image_info->filename,
        MagickPathExtent);
      (void) CopyMagickString(image->magick,"PES",MagickPathExtent);
    }
  read_info=DestroyImageInfo(read_info);
  (void) RelinquishUniqueFileResource(filename);
  return(GetFirstImageInList(image));
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   R e g i s t e r P E S I m a g e                                           %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  RegisterPESImage() adds attributes for the PES image format to
%  the list of supported formats.  The attributes 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 RegisterPESImage method is:
%
%      size_t RegisterPESImage(void)
%
*/
ModuleExport size_t RegisterPESImage(void)
{
  MagickInfo
    *entry;

  entry=AcquireMagickInfo("PES","PES","Embrid Embroidery Format");
  entry->decoder=(DecodeImageHandler *) ReadPESImage;
  entry->magick=(IsImageFormatHandler *) IsPES;
  (void) RegisterMagickInfo(entry);
  return(MagickImageCoderSignature);
}

/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   U n r e g i s t e r P E S I m a g e                                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  UnregisterPESImage() removes format registrations made by the
%  PES module from the list of supported formats.
%
%  The format of the UnregisterPESImage method is:
%
%      UnregisterPESImage(void)
%
*/
ModuleExport void UnregisterPESImage(void)
{
  (void) UnregisterMagickInfo("PES");
}
