Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                            PPPP   EEEEE  SSSSS                              %
      7 %                            P   P  E      SS                                 %
      8 %                            PPPP   EEE     SSS                               %
      9 %                            P      E         SS                              %
     10 %                            P      EEEEE  SSSSS                              %
     11 %                                                                             %
     12 %                                                                             %
     13 %                     Read/Write Brother PES Image Format                     %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                                 July 2009                                   %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     21 %  dedicated to making software imaging solutions freely available.           %
     22 %                                                                             %
     23 %  You may not use this file except in compliance with the License.  You may  %
     24 %  obtain a copy of the License at                                            %
     25 %                                                                             %
     26 %    http://www.imagemagick.org/script/license.php                            %
     27 %                                                                             %
     28 %  Unless required by applicable law or agreed to in writing, software        %
     29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     31 %  See the License for the specific language governing permissions and        %
     32 %  limitations under the License.                                             %
     33 %                                                                             %
     34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     35 %
     36 %  The PES format was derived from Robert Heel's PHP script (see
     37 %  http://bobosch.dyndns.org/embroidery/showFile.php?pes.php) and pesconvert
     38 %  (see http://torvalds-family.blogspot.com/2010/01/embroidery-gaah.html).
     39 %
     40 */
     41 
     42 /*
     44   Include declarations.
     45 */
     46 #include "MagickCore/studio.h"
     47 #include "MagickCore/property.h"
     48 #include "MagickCore/blob.h"
     49 #include "MagickCore/blob-private.h"
     50 #include "MagickCore/cache.h"
     51 #include "MagickCore/client.h"
     52 #include "MagickCore/colorspace.h"
     53 #include "MagickCore/constitute.h"
     54 #include "MagickCore/decorate.h"
     55 #include "MagickCore/exception.h"
     56 #include "MagickCore/exception-private.h"
     57 #include "MagickCore/gem.h"
     58 #include "MagickCore/geometry.h"
     59 #include "MagickCore/image.h"
     60 #include "MagickCore/image-private.h"
     61 #include "MagickCore/list.h"
     62 #include "MagickCore/magick.h"
     63 #include "MagickCore/memory_.h"
     64 #include "MagickCore/monitor.h"
     65 #include "MagickCore/monitor-private.h"
     66 #include "MagickCore/montage.h"
     67 #include "MagickCore/resize.h"
     68 #include "MagickCore/shear.h"
     69 #include "MagickCore/quantum-private.h"
     70 #include "MagickCore/static.h"
     71 #include "MagickCore/string_.h"
     72 #include "MagickCore/module.h"
     73 #include "MagickCore/resource_.h"
     74 #include "MagickCore/transform.h"
     75 #include "MagickCore/utility.h"
     76 
     77 /*
     79   Typedef declarations.
     80 */
     81 typedef struct _PESColorInfo
     82 {
     83   const unsigned char
     84     red,
     85     green,
     86     blue,
     87     alpha;
     88 } PESColorInfo;
     89 
     90 typedef struct _PESBlockInfo
     91 {
     92   const PESColorInfo
     93     *color;
     94 
     95   ssize_t
     96     offset;
     97 } PESBlockInfo;
     98 
     99 /*
    101   PES Colors.
    102 */
    103 static const PESColorInfo
    104   PESColor[256] =
    105   {
    106     {   0,   0,   0, 1 },
    107     {  14,  31, 124, 1 },
    108     {  10,  85, 163, 1 },
    109     {  48, 135, 119, 1 },
    110     {  75, 107, 175, 1 },
    111     { 237,  23,  31, 1 },
    112     { 209,  92,   0, 1 },
    113     { 145,  54, 151, 1 },
    114     { 228, 154, 203, 1 },
    115     { 145,  95, 172, 1 },
    116     { 157, 214, 125, 1 },
    117     { 232, 169,   0, 1 },
    118     { 254, 186,  53, 1 },
    119     { 255, 255,   0, 1 },
    120     { 112, 188,  31, 1 },
    121     { 192, 148,   0, 1 },
    122     { 168, 168, 168, 1 },
    123     { 123, 111,   0, 1 },
    124     { 255, 255, 179, 1 },
    125     {  79,  85,  86, 1 },
    126     {   0,   0,   0, 1 },
    127     {  11,  61, 145, 1 },
    128     { 119,   1, 118, 1 },
    129     {  41,  49,  51, 1 },
    130     {  42,  19,   1, 1 },
    131     { 246,  74, 138, 1 },
    132     { 178, 118,  36, 1 },
    133     { 252, 187, 196, 1 },
    134     { 254,  55,  15, 1 },
    135     { 240, 240, 240, 1 },
    136     { 106,  28, 138, 1 },
    137     { 168, 221, 196, 1 },
    138     {  37, 132, 187, 1 },
    139     { 254, 179,  67, 1 },
    140     { 255, 240, 141, 1 },
    141     { 208, 166,  96, 1 },
    142     { 209,  84,   0, 1 },
    143     { 102, 186,  73, 1 },
    144     {  19,  74,  70, 1 },
    145     { 135, 135, 135, 1 },
    146     { 216, 202, 198, 1 },
    147     {  67,  86,   7, 1 },
    148     { 254, 227, 197, 1 },
    149     { 249, 147, 188, 1 },
    150     {   0,  56,  34, 1 },
    151     { 178, 175, 212, 1 },
    152     { 104, 106, 176, 1 },
    153     { 239, 227, 185, 1 },
    154     { 247,  56, 102, 1 },
    155     { 181,  76, 100, 1 },
    156     {  19,  43,  26, 1 },
    157     { 199,   1,  85, 1 },
    158     { 254, 158,  50, 1 },
    159     { 168, 222, 235, 1 },
    160     {   0, 103,  26, 1 },
    161     {  78,  41, 144, 1 },
    162     {  47, 126,  32, 1 },
    163     { 253, 217, 222, 1 },
    164     { 255, 217,  17, 1 },
    165     {   9,  91, 166, 1 },
    166     { 240, 249, 112, 1 },
    167     { 227, 243,  91, 1 },
    168     { 255, 200, 100, 1 },
    169     { 255, 200, 150, 1 },
    170     { 255, 200, 200, 1 },
    171     {   0,   0,   0, 1 },
    172     {   0,   0,   0, 1 },
    173     {   0,   0,   0, 1 },
    174     {   0,   0,   0, 1 },
    175     {   0,   0,   0, 1 },
    176     {   0,   0,   0, 1 },
    177     {   0,   0,   0, 1 },
    178     {   0,   0,   0, 1 },
    179     {   0,   0,   0, 1 },
    180     {   0,   0,   0, 1 },
    181     {   0,   0,   0, 1 },
    182     {   0,   0,   0, 1 },
    183     {   0,   0,   0, 1 },
    184     {   0,   0,   0, 1 },
    185     {   0,   0,   0, 1 },
    186     {   0,   0,   0, 1 },
    187     {   0,   0,   0, 1 },
    188     {   0,   0,   0, 1 },
    189     {   0,   0,   0, 1 },
    190     {   0,   0,   0, 1 },
    191     {   0,   0,   0, 1 },
    192     {   0,   0,   0, 1 },
    193     {   0,   0,   0, 1 },
    194     {   0,   0,   0, 1 },
    195     {   0,   0,   0, 1 },
    196     {   0,   0,   0, 1 },
    197     {   0,   0,   0, 1 },
    198     {   0,   0,   0, 1 },
    199     {   0,   0,   0, 1 },
    200     {   0,   0,   0, 1 },
    201     {   0,   0,   0, 1 },
    202     {   0,   0,   0, 1 },
    203     {   0,   0,   0, 1 },
    204     {   0,   0,   0, 1 },
    205     {   0,   0,   0, 1 },
    206     {   0,   0,   0, 1 },
    207     {   0,   0,   0, 1 },
    208     {   0,   0,   0, 1 },
    209     {   0,   0,   0, 1 },
    210     {   0,   0,   0, 1 },
    211     {   0,   0,   0, 1 },
    212     {   0,   0,   0, 1 },
    213     {   0,   0,   0, 1 },
    214     {   0,   0,   0, 1 },
    215     {   0,   0,   0, 1 },
    216     {   0,   0,   0, 1 },
    217     {   0,   0,   0, 1 },
    218     {   0,   0,   0, 1 },
    219     {   0,   0,   0, 1 },
    220     {   0,   0,   0, 1 },
    221     {   0,   0,   0, 1 },
    222     {   0,   0,   0, 1 },
    223     {   0,   0,   0, 1 },
    224     {   0,   0,   0, 1 },
    225     {   0,   0,   0, 1 },
    226     {   0,   0,   0, 1 },
    227     {   0,   0,   0, 1 },
    228     {   0,   0,   0, 1 },
    229     {   0,   0,   0, 1 },
    230     {   0,   0,   0, 1 },
    231     {   0,   0,   0, 1 },
    232     {   0,   0,   0, 1 },
    233     {   0,   0,   0, 1 },
    234     {   0,   0,   0, 1 },
    235     {   0,   0,   0, 1 },
    236     {   0,   0,   0, 1 },
    237     {   0,   0,   0, 1 },
    238     {   0,   0,   0, 1 },
    239     {   0,   0,   0, 1 },
    240     {   0,   0,   0, 1 },
    241     {   0,   0,   0, 1 },
    242     {   0,   0,   0, 1 },
    243     {   0,   0,   0, 1 },
    244     {   0,   0,   0, 1 },
    245     {   0,   0,   0, 1 },
    246     {   0,   0,   0, 1 },
    247     {   0,   0,   0, 1 },
    248     {   0,   0,   0, 1 },
    249     {   0,   0,   0, 1 },
    250     {   0,   0,   0, 1 },
    251     {   0,   0,   0, 1 },
    252     {   0,   0,   0, 1 },
    253     {   0,   0,   0, 1 },
    254     {   0,   0,   0, 1 },
    255     {   0,   0,   0, 1 },
    256     {   0,   0,   0, 1 },
    257     {   0,   0,   0, 1 },
    258     {   0,   0,   0, 1 },
    259     {   0,   0,   0, 1 },
    260     {   0,   0,   0, 1 },
    261     {   0,   0,   0, 1 },
    262     {   0,   0,   0, 1 },
    263     {   0,   0,   0, 1 },
    264     {   0,   0,   0, 1 },
    265     {   0,   0,   0, 1 },
    266     {   0,   0,   0, 1 },
    267     {   0,   0,   0, 1 },
    268     {   0,   0,   0, 1 },
    269     {   0,   0,   0, 1 },
    270     {   0,   0,   0, 1 },
    271     {   0,   0,   0, 1 },
    272     {   0,   0,   0, 1 },
    273     {   0,   0,   0, 1 },
    274     {   0,   0,   0, 1 },
    275     {   0,   0,   0, 1 },
    276     {   0,   0,   0, 1 },
    277     {   0,   0,   0, 1 },
    278     {   0,   0,   0, 1 },
    279     {   0,   0,   0, 1 },
    280     {   0,   0,   0, 1 },
    281     {   0,   0,   0, 1 },
    282     {   0,   0,   0, 1 },
    283     {   0,   0,   0, 1 },
    284     {   0,   0,   0, 1 },
    285     {   0,   0,   0, 1 },
    286     {   0,   0,   0, 1 },
    287     {   0,   0,   0, 1 },
    288     {   0,   0,   0, 1 },
    289     {   0,   0,   0, 1 },
    290     {   0,   0,   0, 1 },
    291     {   0,   0,   0, 1 },
    292     {   0,   0,   0, 1 },
    293     {   0,   0,   0, 1 },
    294     {   0,   0,   0, 1 },
    295     {   0,   0,   0, 1 },
    296     {   0,   0,   0, 1 },
    297     {   0,   0,   0, 1 },
    298     {   0,   0,   0, 1 },
    299     {   0,   0,   0, 1 },
    300     {   0,   0,   0, 1 },
    301     {   0,   0,   0, 1 },
    302     {   0,   0,   0, 1 },
    303     {   0,   0,   0, 1 },
    304     {   0,   0,   0, 1 },
    305     {   0,   0,   0, 1 },
    306     {   0,   0,   0, 1 },
    307     {   0,   0,   0, 1 },
    308     {   0,   0,   0, 1 },
    309     {   0,   0,   0, 1 },
    310     {   0,   0,   0, 1 },
    311     {   0,   0,   0, 1 },
    312     {   0,   0,   0, 1 },
    313     {   0,   0,   0, 1 },
    314     {   0,   0,   0, 1 },
    315     {   0,   0,   0, 1 },
    316     {   0,   0,   0, 1 },
    317     {   0,   0,   0, 1 },
    318     {   0,   0,   0, 1 },
    319     {   0,   0,   0, 1 },
    320     {   0,   0,   0, 1 },
    321     {   0,   0,   0, 1 },
    322     {   0,   0,   0, 1 },
    323     {   0,   0,   0, 1 },
    324     {   0,   0,   0, 1 },
    325     {   0,   0,   0, 1 },
    326     {   0,   0,   0, 1 },
    327     {   0,   0,   0, 1 },
    328     {   0,   0,   0, 1 },
    329     {   0,   0,   0, 1 },
    330     {   0,   0,   0, 1 },
    331     {   0,   0,   0, 1 },
    332     {   0,   0,   0, 1 },
    333     {   0,   0,   0, 1 },
    334     {   0,   0,   0, 1 },
    335     {   0,   0,   0, 1 },
    336     {   0,   0,   0, 1 },
    337     {   0,   0,   0, 1 },
    338     {   0,   0,   0, 1 },
    339     {   0,   0,   0, 1 },
    340     {   0,   0,   0, 1 },
    341     {   0,   0,   0, 1 },
    342     {   0,   0,   0, 1 },
    343     {   0,   0,   0, 1 },
    344     {   0,   0,   0, 1 },
    345     {   0,   0,   0, 1 },
    346     {   0,   0,   0, 1 },
    347     {   0,   0,   0, 1 },
    348     {   0,   0,   0, 1 },
    349     {   0,   0,   0, 1 },
    350     {   0,   0,   0, 1 },
    351     {   0,   0,   0, 1 },
    352     {   0,   0,   0, 1 },
    353     {   0,   0,   0, 1 },
    354     {   0,   0,   0, 1 },
    355     {   0,   0,   0, 1 },
    356     {   0,   0,   0, 1 },
    357     {   0,   0,   0, 1 },
    358     {   0,   0,   0, 1 },
    359     {   0,   0,   0, 1 },
    360     {   0,   0,   0, 1 },
    361     {   0,   0,   0, 1 }
    362   };
    363 
    364 /*
    366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    367 %                                                                             %
    368 %                                                                             %
    369 %                                                                             %
    370 %   I s P E S                                                                 %
    371 %                                                                             %
    372 %                                                                             %
    373 %                                                                             %
    374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    375 %
    376 %  IsPES() returns MagickTrue if the image format type, identified by the
    377 %  magick string, is PES.
    378 %
    379 %  The format of the IsPES method is:
    380 %
    381 %      MagickBooleanType IsPES(const unsigned char *magick,const size_t length)
    382 %
    383 %  A description of each parameter follows:
    384 %
    385 %    o magick: compare image format pattern against these bytes.
    386 %
    387 %    o length: Specifies the length of the magick string.
    388 %
    389 */
    390 static MagickBooleanType IsPES(const unsigned char *magick,const size_t length)
    391 {
    392   if (length < 4)
    393     return(MagickFalse);
    394   if (LocaleNCompare((const char *) magick,"#PES",4) == 0)
    395     return(MagickTrue);
    396   return(MagickFalse);
    397 }
    398 
    399 /*
    401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    402 %                                                                             %
    403 %                                                                             %
    404 %                                                                             %
    405 %   R e a d P E S I m a g e                                                   %
    406 %                                                                             %
    407 %                                                                             %
    408 %                                                                             %
    409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    410 %
    411 %  ReadPESImage() reads a Brother PES image file and returns it.  It allocates
    412 %  the memory necessary for the new Image structure and returns a pointer to
    413 %  the new image.
    414 %
    415 %  The format of the ReadPESImage method is:
    416 %
    417 %      image=ReadPESImage(image_info)
    418 %
    419 %  A description of each parameter follows:
    420 %
    421 %    o image_info: the image info.
    422 %
    423 %    o exception: return any errors or warnings in this structure.
    424 %
    425 */
    426 static Image *ReadPESImage(const ImageInfo *image_info,ExceptionInfo *exception)
    427 {
    428   char
    429     filename[MagickPathExtent];
    430 
    431   FILE
    432     *file;
    433 
    434   Image
    435     *image;
    436 
    437   ImageInfo
    438     *read_info;
    439 
    440   int
    441     delta_x,
    442     delta_y,
    443     j,
    444     unique_file,
    445     x,
    446     y;
    447 
    448   MagickBooleanType
    449     status;
    450 
    451   PESBlockInfo
    452     blocks[256];
    453 
    454   PointInfo
    455     *stitches;
    456 
    457   SegmentInfo
    458     bounds;
    459 
    460   register ssize_t
    461     i;
    462 
    463   size_t
    464     number_blocks,
    465     number_colors,
    466     number_stitches;
    467 
    468   ssize_t
    469     count,
    470     offset;
    471 
    472   unsigned char
    473     magick[4],
    474     version[4];
    475 
    476   /*
    477     Open image file.
    478   */
    479   assert(image_info != (const ImageInfo *) NULL);
    480   assert(image_info->signature == MagickCoreSignature);
    481   if (image_info->debug != MagickFalse)
    482     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    483       image_info->filename);
    484   assert(exception != (ExceptionInfo *) NULL);
    485   assert(exception->signature == MagickCoreSignature);
    486   image=AcquireImage(image_info,exception);
    487   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    488   if (status == MagickFalse)
    489     {
    490       image=DestroyImageList(image);
    491       return((Image *) NULL);
    492     }
    493   /*
    494     Verify PES identifier.
    495   */
    496   count=ReadBlob(image,4,magick);
    497   if ((count != 4) || (LocaleNCompare((char *) magick,"#PES",4) != 0))
    498     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    499   count=ReadBlob(image,4,version);
    500   offset=ReadBlobLSBSignedLong(image);
    501   if (DiscardBlobBytes(image,offset+36) == MagickFalse)
    502     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    503       image->filename);
    504   if (EOFBlob(image) != MagickFalse)
    505     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
    506   /*
    507     Get PES colors.
    508   */
    509   number_colors=(size_t) ReadBlobByte(image)+1;
    510   for (i=0; i < (ssize_t) number_colors; i++)
    511   {
    512     j=ReadBlobByte(image);
    513     blocks[i].color=PESColor+(j < 0 ? 0 : j);
    514     blocks[i].offset=0;
    515   }
    516   for ( ; i < 256L; i++)
    517   {
    518     blocks[i].offset=0;
    519     blocks[i].color=PESColor;
    520   }
    521   if (DiscardBlobBytes(image,532L-number_colors-21) == MagickFalse)
    522     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    523       image->filename);
    524   if (EOFBlob(image) != MagickFalse)
    525     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
    526   /*
    527     Stitch away.
    528   */
    529   number_stitches=64;
    530   stitches=(PointInfo *) AcquireQuantumMemory(number_stitches,
    531     sizeof(*stitches));
    532   if (stitches == (PointInfo *) NULL)
    533     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    534   bounds.x1=65535.0;
    535   bounds.y1=65535.0;
    536   bounds.x2=(-65535.0);
    537   bounds.y2=(-65535.0);
    538   i=0;
    539   j=0;
    540   delta_x=0;
    541   delta_y=0;
    542   while (EOFBlob(image) != EOF)
    543   {
    544     x=ReadBlobByte(image);
    545     y=ReadBlobByte(image);
    546     if ((x == 0xff) && (y == 0))
    547       break;
    548     if ((x == 254) && (y == 176))
    549       {
    550         /*
    551           Start a new stitch block.
    552         */
    553         j++;
    554         blocks[j].offset=(ssize_t) i;
    555         if (j >= 256)
    556           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    557         (void) ReadBlobByte(image);
    558         continue;
    559       }
    560     if ((x & 0x80) == 0)
    561       {
    562         /*
    563           Normal stitch.
    564         */
    565         if ((x & 0x40) != 0)
    566           x-=0x80;
    567       }
    568     else
    569       {
    570         /*
    571           Jump stitch.
    572         */
    573         x=((x & 0x0f) << 8)+y;
    574         if ((x & 0x800) != 0)
    575           x-=0x1000;
    576         y=ReadBlobByte(image);
    577       }
    578     if ((y & 0x80) == 0)
    579       {
    580         /*
    581           Normal stitch.
    582         */
    583         if ((y & 0x40) != 0)
    584           y-=0x80;
    585       }
    586     else
    587       {
    588         /*
    589           Jump stitch.
    590         */
    591         y=((y & 0x0f) << 8)+ReadBlobByte(image);
    592         if ((y & 0x800) != 0)
    593           y-=0x1000;
    594       }
    595     /*
    596       Note stitch (x,y).
    597     */
    598     x+=delta_x;
    599     y+=delta_y;
    600     delta_x=x;
    601     delta_y=y;
    602     stitches[i].x=(double) x;
    603     stitches[i].y=(double) y;
    604     if ((double) x < bounds.x1)
    605       bounds.x1=(double) x;
    606     if ((double) x > bounds.x2)
    607       bounds.x2=(double) x;
    608     if ((double) y < bounds.y1)
    609       bounds.y1=(double) y;
    610     if ((double) y > bounds.y2)
    611       bounds.y2=(double) y;
    612     i++;
    613     if (i >= (ssize_t) number_stitches)
    614       {
    615         /*
    616           Make room for more stitches.
    617         */
    618         number_stitches<<=1;
    619         stitches=(PointInfo *)  ResizeQuantumMemory(stitches,(size_t)
    620           number_stitches,sizeof(*stitches));
    621         if (stitches == (PointInfo *) NULL)
    622           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    623      }
    624   }
    625   j++;
    626   blocks[j].offset=(ssize_t) i;
    627   number_blocks=(size_t) j;
    628   /*
    629     Write stitches as SVG file.
    630   */
    631   file=(FILE *) NULL;
    632   unique_file=AcquireUniqueFileResource(filename);
    633   if (unique_file != -1)
    634     file=fdopen(unique_file,"wb");
    635   if ((unique_file == -1) || (file == (FILE *) NULL))
    636     ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile");
    637   (void) FormatLocaleFile(file,"<?xml version=\"1.0\"?>\n");
    638   (void) FormatLocaleFile(file,"<svg xmlns=\"http://www.w3.org/2000/svg\" "
    639     "xlink=\"http://www.w3.org/1999/xlink\" "
    640     "ev=\"http://www.w3.org/2001/xml-events\" version=\"1.1\" "
    641     "baseProfile=\"full\" width=\"%g\" height=\"%g\">\n",bounds.x2-bounds.x1,
    642     bounds.y2-bounds.y1);
    643   for (i=0; i < (ssize_t) number_blocks; i++)
    644   {
    645     offset=blocks[i].offset;
    646     (void) FormatLocaleFile(file,"  <path stroke=\"#%02x%02x%02x\" "
    647       "fill=\"none\" d=\"M %g %g",blocks[i].color->red,blocks[i].color->green,
    648       blocks[i].color->blue,stitches[offset].x-bounds.x1,
    649       stitches[offset].y-bounds.y1);
    650     for (j=1; j < (ssize_t) (blocks[i+1].offset-offset); j++)
    651       (void) FormatLocaleFile(file," L %g %g",stitches[offset+j].x-bounds.x1,
    652         stitches[offset+j].y-bounds.y1);
    653     (void) FormatLocaleFile(file,"\"/>\n");
    654   }
    655   (void) FormatLocaleFile(file,"</svg>\n");
    656   (void) fclose(file);
    657   (void) CloseBlob(image);
    658   image=DestroyImage(image);
    659   /*
    660     Read SVG file.
    661   */
    662   read_info=CloneImageInfo(image_info);
    663   SetImageInfoBlob(read_info,(void *) NULL,0);
    664   (void) FormatLocaleString(read_info->filename,MagickPathExtent,"svg:%s",
    665     filename);
    666   image=ReadImage(read_info,exception);
    667   if (image != (Image *) NULL)
    668     {
    669       (void) CopyMagickString(image->filename,image_info->filename,
    670         MagickPathExtent);
    671       (void) CopyMagickString(image->magick_filename,image_info->filename,
    672         MagickPathExtent);
    673       (void) CopyMagickString(image->magick,"PES",MagickPathExtent);
    674     }
    675   read_info=DestroyImageInfo(read_info);
    676   (void) RelinquishUniqueFileResource(filename);
    677   return(GetFirstImageInList(image));
    678 }
    679 
    680 /*
    682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    683 %                                                                             %
    684 %                                                                             %
    685 %                                                                             %
    686 %   R e g i s t e r P E S I m a g e                                           %
    687 %                                                                             %
    688 %                                                                             %
    689 %                                                                             %
    690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    691 %
    692 %  RegisterPESImage() adds attributes for the PES image format to
    693 %  the list of supported formats.  The attributes include the image format
    694 %  tag, a method to read and/or write the format, whether the format
    695 %  supports the saving of more than one frame to the same file or blob,
    696 %  whether the format supports native in-memory I/O, and a brief
    697 %  description of the format.
    698 %
    699 %  The format of the RegisterPESImage method is:
    700 %
    701 %      size_t RegisterPESImage(void)
    702 %
    703 */
    704 ModuleExport size_t RegisterPESImage(void)
    705 {
    706   MagickInfo
    707     *entry;
    708 
    709   entry=AcquireMagickInfo("PES","PES","Embrid Embroidery Format");
    710   entry->decoder=(DecodeImageHandler *) ReadPESImage;
    711   entry->magick=(IsImageFormatHandler *) IsPES;
    712   (void) RegisterMagickInfo(entry);
    713   return(MagickImageCoderSignature);
    714 }
    715 
    716 /*
    718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    719 %                                                                             %
    720 %                                                                             %
    721 %                                                                             %
    722 %   U n r e g i s t e r P E S I m a g e                                       %
    723 %                                                                             %
    724 %                                                                             %
    725 %                                                                             %
    726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    727 %
    728 %  UnregisterPESImage() removes format registrations made by the
    729 %  PES module from the list of supported formats.
    730 %
    731 %  The format of the UnregisterPESImage method is:
    732 %
    733 %      UnregisterPESImage(void)
    734 %
    735 */
    736 ModuleExport void UnregisterPESImage(void)
    737 {
    738   (void) UnregisterMagickInfo("PES");
    739 }
    740