]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Mon, 25 Jan 2010 01:44:27 +0000 (01:44 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Mon, 25 Jan 2010 01:44:27 +0000 (01:44 +0000)
coders/pes.c

index c09d3fb68da8796b2183dfe9ba07e41cabbcfbca..20a3701a23e9f5bbc53fe15647ee9cd76093ec83 100644 (file)
@@ -33,7 +33,7 @@
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  The PES coders is derived from Robert Heel's PHP script (see
+%  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 "magick/static.h"
 #include "magick/string_.h"
 #include "magick/module.h"
+#include "magick/resource_.h"
 #include "magick/transform.h"
 #include "magick/utility.h"
 \f
 /*
-  PES Colors.
+  Typedef declarations.
 */
-
 typedef struct _PESColorInfo
 {
-  unsigned char
+  const unsigned char
     red,
     green,
     blue,
     alpha;
 } PESColorInfo;
 
+typedef struct _PESBlockInfo
+{
+  const PESColorInfo
+    *color;
+
+  ssize_t
+    offset;
+} PESBlockInfo;
+\f
+/*
+  PES Colors.
+*/
 static const PESColorInfo
   PESColor[256] =
   {
-    {   0,   0,   0, 0 },
+    {   0,   0,   0, 1 },
     {  14,  31, 124, 1 },
     {  10,  85, 163, 1 },
     {  48, 135, 119, 1 },
@@ -152,7 +164,198 @@ static const PESColorInfo
     { 227, 243,  91, 1 },
     { 255, 200, 100, 1 },
     { 255, 200, 150, 1 },
-    { 255, 200, 200, 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 }
   };
 \f
 /*
@@ -217,30 +420,53 @@ static MagickBooleanType IsPES(const unsigned char *magick,const size_t length)
 */
 static Image *ReadPESImage(const ImageInfo *image_info,ExceptionInfo *exception)
 {
+  char
+    filename[MaxTextExtent];
+
+  FILE
+    *file;
+
   Image
     *image;
 
+  ImageInfo
+    *read_info;
+
+  int
+    delta_x,
+    delta_y,
+    j,
+    unique_file,
+    x,
+    y;
+
   MagickBooleanType
     status;
 
-  PESColorInfo
-    colors[256];
+  PESBlockInfo
+    blocks[256];
+
+  PointInfo
+    *stitches;
+
+  SegmentInfo
+    bounds;
 
   register long
     i;
 
   ssize_t
-    count;
-
-  size_t
-    length;
+    count,
+    offset;
 
   unsigned char
     magick[4],
     version[4];
 
   unsigned long
-    number_colors;    
+    number_blocks,
+    number_colors,
+    number_stitches;
 
   /*
     Open image file.
@@ -266,8 +492,8 @@ static Image *ReadPESImage(const ImageInfo *image_info,ExceptionInfo *exception)
   if ((count != 4) || (LocaleNCompare((char *) magick,"#PES",4) != 0))
     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   count=ReadBlob(image,4,version);
-  length=(size_t) ReadBlobLSBLong(image);
-  for (i=0; i < 37; i++)
+  offset=(ssize_t) ReadBlobLSBLong(image);
+  for (i=0; i < (offset+36); i++)
     if (ReadBlobByte(image) == EOF)
       break;
   if (EOFBlob(image) != MagickFalse)
@@ -275,14 +501,171 @@ static Image *ReadPESImage(const ImageInfo *image_info,ExceptionInfo *exception)
   /*
     Get PES colors.
   */
-  number_colors=ReadBlobByte(image)+1;
+  number_colors=(unsigned long) ReadBlobByte(image)+1;
   for (i=0; i < (long) number_colors; i++)
-    colors[i]=PESColor[ReadBlobByte(image)];
-  for (i=0; i < (532L-number_colors-49L); i++)
+  {
+    j=(int) ReadBlobByte(image);
+    blocks[i].color=PESColor+j;
+    blocks[i].offset=0;
+  }
+  for ( ; i < 256L; i++)
+    blocks[i].offset=0;
+  for (i=0; i < (long) (532L-number_colors-21); i++)
     if (ReadBlobByte(image) == EOF)
       break;
   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) != EOF)
+  {
+    x=(int) ReadBlobByte(image);
+    y=(int) 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 >= 256)
+          ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+        (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 >= (long) 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=(unsigned long) j;
+  /*
+    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) fprintf(file,"<?xml version=\"1.0\"?>\n");
+  (void) fprintf(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",bounds.x2-bounds.x1,
+    bounds.y2-bounds.y1);
+  for (i=0; i < (long) number_blocks; i++)
+  {
+    offset=blocks[i].offset;
+    (void) fprintf(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 < (long) (blocks[i+1].offset-offset); j++)
+      (void) fprintf(file," L %g %g",stitches[offset+j].x-bounds.x1,
+        stitches[offset+j].y-bounds.y1);
+    (void) fprintf(file,"\"/>\n");
+  }
+  (void) fprintf(file,"</svg>\n");
+  (void) fclose(file);
+  (void) CloseBlob(image);
+  image=DestroyImage(image);
+  /*
+    Read SVG file.
+  */
+  read_info=CloneImageInfo(image_info);
+  SetImageInfoBlob(read_info,(void *) NULL,0);
+  (void) FormatMagickString(read_info->filename,MaxTextExtent,"svg:%.1024s",
+    filename);
+  image=ReadImage(read_info,exception);
+  if (image != (Image *) NULL)
+    {
+      (void) CopyMagickString(image->filename,image_info->filename,
+        MaxTextExtent);
+      (void) CopyMagickString(image->magick_filename,image_info->filename,
+        MaxTextExtent);
+      (void) CopyMagickString(image->magick,"PES",MaxTextExtent);
+    }
+  read_info=DestroyImageInfo(read_info);
+  (void) RelinquishUniqueFileResource(filename);
   return(GetFirstImageInList(image));
 }
 \f