Coverage Report

Created: 2026-09-28 06:47

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