summaryrefslogtreecommitdiff
path: root/coders/pes.c
diff options
context:
space:
mode:
authorcristy <urban-warrior@git.imagemagick.org>2010-01-25 01:44:27 +0000
committercristy <urban-warrior@git.imagemagick.org>2010-01-25 01:44:27 +0000
commit85256d123fadd574aa9c4db6af1e1b2f392a25c0 (patch)
tree252ab7706f5289f605fa52ed3b0821e44f9951df /coders/pes.c
parent6bee28a6a940ade91b9fd81847ca67b487ab6c08 (diff)
downloadImageMagick-85256d123fadd574aa9c4db6af1e1b2f392a25c0.tar.gz
Diffstat (limited to 'coders/pes.c')
-rw-r--r--coders/pes.c419
1 files changed, 401 insertions, 18 deletions
diff --git a/coders/pes.c b/coders/pes.c
index c09d3fb68..20a3701a2 100644
--- a/coders/pes.c
+++ b/coders/pes.c
@@ -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).
%
@@ -69,26 +69,38 @@
#include "magick/static.h"
#include "magick/string_.h"
#include "magick/module.h"
+#include "magick/resource_.h"
#include "magick/transform.h"
#include "magick/utility.h"
/*
- 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;
+
+/*
+ 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 }
};
/*
@@ -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));
}