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-2021 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 %    https://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 /*
43   Include declarations.
44 */
45 #include "MagickCore/studio.h"
46 #include "MagickCore/property.h"
47 #include "MagickCore/blob.h"
48 #include "MagickCore/blob-private.h"
49 #include "MagickCore/cache.h"
50 #include "MagickCore/client.h"
51 #include "MagickCore/colorspace.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/decorate.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/gem.h"
57 #include "MagickCore/geometry.h"
58 #include "MagickCore/image.h"
59 #include "MagickCore/image-private.h"
60 #include "MagickCore/list.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/monitor.h"
64 #include "MagickCore/monitor-private.h"
65 #include "MagickCore/montage.h"
66 #include "MagickCore/resize.h"
67 #include "MagickCore/shear.h"
68 #include "MagickCore/quantum-private.h"
69 #include "MagickCore/static.h"
70 #include "MagickCore/string_.h"
71 #include "MagickCore/module.h"
72 #include "MagickCore/resource_.h"
73 #include "MagickCore/transform.h"
74 #include "MagickCore/utility.h"
75 
76 /*
77   Typedef declarations.
78 */
79 typedef struct _PESColorInfo
80 {
81   const unsigned char
82     red,
83     green,
84     blue,
85     alpha;
86 } PESColorInfo;
87 
88 typedef struct _PESBlockInfo
89 {
90   const PESColorInfo
91     *color;
92 
93   ssize_t
94     offset;
95 } PESBlockInfo;
96 
97 /*
98   PES Colors.
99 */
100 static const PESColorInfo
101   PESColor[256] =
102   {
103     {   0,   0,   0, 1 },
104     {  14,  31, 124, 1 },
105     {  10,  85, 163, 1 },
106     {  48, 135, 119, 1 },
107     {  75, 107, 175, 1 },
108     { 237,  23,  31, 1 },
109     { 209,  92,   0, 1 },
110     { 145,  54, 151, 1 },
111     { 228, 154, 203, 1 },
112     { 145,  95, 172, 1 },
113     { 157, 214, 125, 1 },
114     { 232, 169,   0, 1 },
115     { 254, 186,  53, 1 },
116     { 255, 255,   0, 1 },
117     { 112, 188,  31, 1 },
118     { 192, 148,   0, 1 },
119     { 168, 168, 168, 1 },
120     { 123, 111,   0, 1 },
121     { 255, 255, 179, 1 },
122     {  79,  85,  86, 1 },
123     {   0,   0,   0, 1 },
124     {  11,  61, 145, 1 },
125     { 119,   1, 118, 1 },
126     {  41,  49,  51, 1 },
127     {  42,  19,   1, 1 },
128     { 246,  74, 138, 1 },
129     { 178, 118,  36, 1 },
130     { 252, 187, 196, 1 },
131     { 254,  55,  15, 1 },
132     { 240, 240, 240, 1 },
133     { 106,  28, 138, 1 },
134     { 168, 221, 196, 1 },
135     {  37, 132, 187, 1 },
136     { 254, 179,  67, 1 },
137     { 255, 240, 141, 1 },
138     { 208, 166,  96, 1 },
139     { 209,  84,   0, 1 },
140     { 102, 186,  73, 1 },
141     {  19,  74,  70, 1 },
142     { 135, 135, 135, 1 },
143     { 216, 202, 198, 1 },
144     {  67,  86,   7, 1 },
145     { 254, 227, 197, 1 },
146     { 249, 147, 188, 1 },
147     {   0,  56,  34, 1 },
148     { 178, 175, 212, 1 },
149     { 104, 106, 176, 1 },
150     { 239, 227, 185, 1 },
151     { 247,  56, 102, 1 },
152     { 181,  76, 100, 1 },
153     {  19,  43,  26, 1 },
154     { 199,   1,  85, 1 },
155     { 254, 158,  50, 1 },
156     { 168, 222, 235, 1 },
157     {   0, 103,  26, 1 },
158     {  78,  41, 144, 1 },
159     {  47, 126,  32, 1 },
160     { 253, 217, 222, 1 },
161     { 255, 217,  17, 1 },
162     {   9,  91, 166, 1 },
163     { 240, 249, 112, 1 },
164     { 227, 243,  91, 1 },
165     { 255, 200, 100, 1 },
166     { 255, 200, 150, 1 },
167     { 255, 200, 200, 1 },
168     {   0,   0,   0, 1 },
169     {   0,   0,   0, 1 },
170     {   0,   0,   0, 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   };
360 
361 /*
362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363 %                                                                             %
364 %                                                                             %
365 %                                                                             %
366 %   I s P E S                                                                 %
367 %                                                                             %
368 %                                                                             %
369 %                                                                             %
370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
371 %
372 %  IsPES() returns MagickTrue if the image format type, identified by the
373 %  magick string, is PES.
374 %
375 %  The format of the IsPES method is:
376 %
377 %      MagickBooleanType IsPES(const unsigned char *magick,const size_t length)
378 %
379 %  A description of each parameter follows:
380 %
381 %    o magick: compare image format pattern against these bytes.
382 %
383 %    o length: Specifies the length of the magick string.
384 %
385 */
IsPES(const unsigned char * magick,const size_t length)386 static MagickBooleanType IsPES(const unsigned char *magick,const size_t length)
387 {
388   if (length < 4)
389     return(MagickFalse);
390   if (LocaleNCompare((const char *) magick,"#PES",4) == 0)
391     return(MagickTrue);
392   return(MagickFalse);
393 }
394 
395 /*
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397 %                                                                             %
398 %                                                                             %
399 %                                                                             %
400 %   R e a d P E S I m a g e                                                   %
401 %                                                                             %
402 %                                                                             %
403 %                                                                             %
404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405 %
406 %  ReadPESImage() reads a Brother PES image file and returns it.  It allocates
407 %  the memory necessary for the new Image structure and returns a pointer to
408 %  the new image.
409 %
410 %  The format of the ReadPESImage method is:
411 %
412 %      image=ReadPESImage(image_info)
413 %
414 %  A description of each parameter follows:
415 %
416 %    o image_info: the image info.
417 %
418 %    o exception: return any errors or warnings in this structure.
419 %
420 */
ReadPESImage(const ImageInfo * image_info,ExceptionInfo * exception)421 static Image *ReadPESImage(const ImageInfo *image_info,ExceptionInfo *exception)
422 {
423   char
424     filename[MagickPathExtent];
425 
426   FILE
427     *file;
428 
429   Image
430     *image;
431 
432   ImageInfo
433     *read_info;
434 
435   int
436     delta_x,
437     delta_y,
438     j,
439     unique_file,
440     x,
441     y;
442 
443   MagickBooleanType
444     status;
445 
446   PESBlockInfo
447     blocks[256];
448 
449   PointInfo
450     *stitches;
451 
452   SegmentInfo
453     bounds;
454 
455   ssize_t
456     i;
457 
458   size_t
459     number_blocks,
460     number_colors,
461     number_stitches;
462 
463   ssize_t
464     count,
465     offset;
466 
467   unsigned char
468     magick[4],
469     version[4];
470 
471   /*
472     Open image file.
473   */
474   assert(image_info != (const ImageInfo *) NULL);
475   assert(image_info->signature == MagickCoreSignature);
476   if (image_info->debug != MagickFalse)
477     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
478       image_info->filename);
479   assert(exception != (ExceptionInfo *) NULL);
480   assert(exception->signature == MagickCoreSignature);
481   image=AcquireImage(image_info,exception);
482   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
483   if (status == MagickFalse)
484     {
485       image=DestroyImageList(image);
486       return((Image *) NULL);
487     }
488   /*
489     Verify PES identifier.
490   */
491   count=ReadBlob(image,4,magick);
492   if ((count != 4) || (LocaleNCompare((char *) magick,"#PES",4) != 0))
493     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
494   count=ReadBlob(image,4,version);
495   offset=ReadBlobLSBSignedLong(image);
496   if (DiscardBlobBytes(image,offset+36) == MagickFalse)
497     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
498       image->filename);
499   if (EOFBlob(image) != MagickFalse)
500     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
501   /*
502     Get PES colors.
503   */
504   number_colors=(size_t) ReadBlobByte(image)+1;
505   for (i=0; i < (ssize_t) number_colors; i++)
506   {
507     j=ReadBlobByte(image);
508     blocks[i].color=PESColor+(j < 0 ? 0 : j);
509     blocks[i].offset=0;
510   }
511   for ( ; i < 256L; i++)
512   {
513     blocks[i].offset=0;
514     blocks[i].color=PESColor;
515   }
516   if (DiscardBlobBytes(image,532L-number_colors-21) == MagickFalse)
517     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
518       image->filename);
519   if (EOFBlob(image) != MagickFalse)
520     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
521   /*
522     Stitch away.
523   */
524   number_stitches=64;
525   stitches=(PointInfo *) AcquireQuantumMemory(number_stitches,
526     sizeof(*stitches));
527   if (stitches == (PointInfo *) NULL)
528     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
529   bounds.x1=65535.0;
530   bounds.y1=65535.0;
531   bounds.x2=(-65535.0);
532   bounds.y2=(-65535.0);
533   i=0;
534   j=0;
535   delta_x=0;
536   delta_y=0;
537   while (EOFBlob(image) == MagickFalse)
538   {
539     x=ReadBlobByte(image);
540     y=ReadBlobByte(image);
541     if ((x == 0xff) && (y == 0))
542       break;
543     if ((x == 254) && (y == 176))
544       {
545         /*
546           Start a new stitch block.
547         */
548         j++;
549         blocks[j].offset=(ssize_t) i;
550         if (j >= 255)
551           {
552             stitches=(PointInfo *) RelinquishMagickMemory(stitches);
553             ThrowReaderException(ResourceLimitError,"CorruptImage");
554           }
555         (void) ReadBlobByte(image);
556         continue;
557       }
558     if ((x & 0x80) == 0)
559       {
560         /*
561           Normal stitch.
562         */
563         if ((x & 0x40) != 0)
564           x-=0x80;
565       }
566     else
567       {
568         /*
569           Jump stitch.
570         */
571         x=((x & 0x0f) << 8)+y;
572         if ((x & 0x800) != 0)
573           x-=0x1000;
574         y=ReadBlobByte(image);
575       }
576     if ((y & 0x80) == 0)
577       {
578         /*
579           Normal stitch.
580         */
581         if ((y & 0x40) != 0)
582           y-=0x80;
583       }
584     else
585       {
586         /*
587           Jump stitch.
588         */
589         y=((y & 0x0f) << 8)+ReadBlobByte(image);
590         if ((y & 0x800) != 0)
591           y-=0x1000;
592       }
593     /*
594       Note stitch (x,y).
595     */
596     x+=delta_x;
597     y+=delta_y;
598     delta_x=x;
599     delta_y=y;
600     stitches[i].x=(double) x;
601     stitches[i].y=(double) y;
602     if ((double) x < bounds.x1)
603       bounds.x1=(double) x;
604     if ((double) x > bounds.x2)
605       bounds.x2=(double) x;
606     if ((double) y < bounds.y1)
607       bounds.y1=(double) y;
608     if ((double) y > bounds.y2)
609       bounds.y2=(double) y;
610     i++;
611     if (i >= (ssize_t) number_stitches)
612       {
613         /*
614           Make room for more stitches.
615         */
616         number_stitches<<=1;
617         stitches=(PointInfo *)  ResizeQuantumMemory(stitches,(size_t)
618           number_stitches,sizeof(*stitches));
619         if (stitches == (PointInfo *) NULL)
620           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
621      }
622   }
623   j++;
624   blocks[j].offset=(ssize_t) i;
625   number_blocks=(size_t) j;
626   image->columns=bounds.x2-bounds.x1;
627   image->rows=bounds.y2-bounds.y1;
628   status=SetImageExtent(image,image->columns,image->rows,exception);
629   if (status == MagickFalse)
630     {
631       stitches=(PointInfo *) RelinquishMagickMemory(stitches);
632       return(DestroyImageList(image));
633     }
634   /*
635     Write stitches as SVG file.
636   */
637   file=(FILE *) NULL;
638   unique_file=AcquireUniqueFileResource(filename);
639   if (unique_file != -1)
640     file=fdopen(unique_file,"wb");
641   if ((unique_file == -1) || (file == (FILE *) NULL))
642     ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile");
643   (void) FormatLocaleFile(file,"<?xml version=\"1.0\"?>\n");
644   (void) FormatLocaleFile(file,"<svg xmlns=\"http://www.w3.org/2000/svg\" "
645     "xlink=\"http://www.w3.org/1999/xlink\" "
646     "ev=\"http://www.w3.org/2001/xml-events\" version=\"1.1\" "
647     "baseProfile=\"full\" width=\"%g\" height=\"%g\">\n",(double)
648     image->columns,(double) image->rows);
649   for (i=0; i < (ssize_t) number_blocks; i++)
650   {
651     offset=blocks[i].offset;
652     (void) FormatLocaleFile(file,"  <path stroke=\"#%02x%02x%02x\" "
653       "fill=\"none\" d=\"M %g %g",blocks[i].color->red,blocks[i].color->green,
654       blocks[i].color->blue,stitches[offset].x-bounds.x1,
655       stitches[offset].y-bounds.y1);
656     for (j=1; j < (ssize_t) (blocks[i+1].offset-offset); j++)
657       (void) FormatLocaleFile(file," L %g %g",stitches[offset+j].x-bounds.x1,
658         stitches[offset+j].y-bounds.y1);
659     (void) FormatLocaleFile(file,"\"/>\n");
660   }
661   (void) FormatLocaleFile(file,"</svg>\n");
662   (void) fclose(file);
663   stitches=(PointInfo *) RelinquishMagickMemory(stitches);
664   (void) CloseBlob(image);
665   image=DestroyImage(image);
666   /*
667     Read SVG file.
668   */
669   read_info=CloneImageInfo(image_info);
670   SetImageInfoBlob(read_info,(void *) NULL,0);
671   (void) FormatLocaleString(read_info->filename,MagickPathExtent,"svg:%s",
672     filename);
673   image=ReadImage(read_info,exception);
674   if (image != (Image *) NULL)
675     {
676       (void) CopyMagickString(image->filename,image_info->filename,
677         MagickPathExtent);
678       (void) CopyMagickString(image->magick_filename,image_info->filename,
679         MagickPathExtent);
680       (void) CopyMagickString(image->magick,"PES",MagickPathExtent);
681     }
682   read_info=DestroyImageInfo(read_info);
683   (void) RelinquishUniqueFileResource(filename);
684   return(GetFirstImageInList(image));
685 }
686 
687 /*
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 %                                                                             %
690 %                                                                             %
691 %                                                                             %
692 %   R e g i s t e r P E S I m a g e                                           %
693 %                                                                             %
694 %                                                                             %
695 %                                                                             %
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697 %
698 %  RegisterPESImage() adds attributes for the PES image format to
699 %  the list of supported formats.  The attributes include the image format
700 %  tag, a method to read and/or write the format, whether the format
701 %  supports the saving of more than one frame to the same file or blob,
702 %  whether the format supports native in-memory I/O, and a brief
703 %  description of the format.
704 %
705 %  The format of the RegisterPESImage method is:
706 %
707 %      size_t RegisterPESImage(void)
708 %
709 */
RegisterPESImage(void)710 ModuleExport size_t RegisterPESImage(void)
711 {
712   MagickInfo
713     *entry;
714 
715   entry=AcquireMagickInfo("PES","PES","Embrid Embroidery Format");
716   entry->decoder=(DecodeImageHandler *) ReadPESImage;
717   entry->magick=(IsImageFormatHandler *) IsPES;
718   (void) RegisterMagickInfo(entry);
719   return(MagickImageCoderSignature);
720 }
721 
722 /*
723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724 %                                                                             %
725 %                                                                             %
726 %                                                                             %
727 %   U n r e g i s t e r P E S I m a g e                                       %
728 %                                                                             %
729 %                                                                             %
730 %                                                                             %
731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
732 %
733 %  UnregisterPESImage() removes format registrations made by the
734 %  PES module from the list of supported formats.
735 %
736 %  The format of the UnregisterPESImage method is:
737 %
738 %      UnregisterPESImage(void)
739 %
740 */
UnregisterPESImage(void)741 ModuleExport void UnregisterPESImage(void)
742 {
743   (void) UnregisterMagickInfo("PES");
744 }
745