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-2019 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 /* 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) == MagickFalse) 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 >= 255) 556 { 557 stitches=(PointInfo *) RelinquishMagickMemory(stitches); 558 ThrowReaderException(ResourceLimitError,"CorruptImage"); 559 } 560 (void) ReadBlobByte(image); 561 continue; 562 } 563 if ((x & 0x80) == 0) 564 { 565 /* 566 Normal stitch. 567 */ 568 if ((x & 0x40) != 0) 569 x-=0x80; 570 } 571 else 572 { 573 /* 574 Jump stitch. 575 */ 576 x=((x & 0x0f) << 8)+y; 577 if ((x & 0x800) != 0) 578 x-=0x1000; 579 y=ReadBlobByte(image); 580 } 581 if ((y & 0x80) == 0) 582 { 583 /* 584 Normal stitch. 585 */ 586 if ((y & 0x40) != 0) 587 y-=0x80; 588 } 589 else 590 { 591 /* 592 Jump stitch. 593 */ 594 y=((y & 0x0f) << 8)+ReadBlobByte(image); 595 if ((y & 0x800) != 0) 596 y-=0x1000; 597 } 598 /* 599 Note stitch (x,y). 600 */ 601 x+=delta_x; 602 y+=delta_y; 603 delta_x=x; 604 delta_y=y; 605 stitches[i].x=(double) x; 606 stitches[i].y=(double) y; 607 if ((double) x < bounds.x1) 608 bounds.x1=(double) x; 609 if ((double) x > bounds.x2) 610 bounds.x2=(double) x; 611 if ((double) y < bounds.y1) 612 bounds.y1=(double) y; 613 if ((double) y > bounds.y2) 614 bounds.y2=(double) y; 615 i++; 616 if (i >= (ssize_t) number_stitches) 617 { 618 /* 619 Make room for more stitches. 620 */ 621 number_stitches<<=1; 622 stitches=(PointInfo *) ResizeQuantumMemory(stitches,(size_t) 623 number_stitches,sizeof(*stitches)); 624 if (stitches == (PointInfo *) NULL) 625 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 626 } 627 } 628 j++; 629 blocks[j].offset=(ssize_t) i; 630 number_blocks=(size_t) j; 631 image->columns=bounds.x2-bounds.x1; 632 image->rows=bounds.y2-bounds.y1; 633 status=SetImageExtent(image,image->columns,image->rows,exception); 634 if (status == MagickFalse) 635 { 636 stitches=(PointInfo *) RelinquishMagickMemory(stitches); 637 return(DestroyImageList(image)); 638 } 639 /* 640 Write stitches as SVG file. 641 */ 642 file=(FILE *) NULL; 643 unique_file=AcquireUniqueFileResource(filename); 644 if (unique_file != -1) 645 file=fdopen(unique_file,"wb"); 646 if ((unique_file == -1) || (file == (FILE *) NULL)) 647 ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile"); 648 (void) FormatLocaleFile(file,"<?xml version=\"1.0\"?>\n"); 649 (void) FormatLocaleFile(file,"<svg xmlns=\"http://www.w3.org/2000/svg\" " 650 "xlink=\"http://www.w3.org/1999/xlink\" " 651 "ev=\"http://www.w3.org/2001/xml-events\" version=\"1.1\" " 652 "baseProfile=\"full\" width=\"%g\" height=\"%g\">\n",(double) 653 image->columns,(double) image->rows); 654 for (i=0; i < (ssize_t) number_blocks; i++) 655 { 656 offset=blocks[i].offset; 657 (void) FormatLocaleFile(file," <path stroke=\"#%02x%02x%02x\" " 658 "fill=\"none\" d=\"M %g %g",blocks[i].color->red,blocks[i].color->green, 659 blocks[i].color->blue,stitches[offset].x-bounds.x1, 660 stitches[offset].y-bounds.y1); 661 for (j=1; j < (ssize_t) (blocks[i+1].offset-offset); j++) 662 (void) FormatLocaleFile(file," L %g %g",stitches[offset+j].x-bounds.x1, 663 stitches[offset+j].y-bounds.y1); 664 (void) FormatLocaleFile(file,"\"/>\n"); 665 } 666 (void) FormatLocaleFile(file,"</svg>\n"); 667 (void) fclose(file); 668 stitches=(PointInfo *) RelinquishMagickMemory(stitches); 669 (void) CloseBlob(image); 670 image=DestroyImage(image); 671 /* 672 Read SVG file. 673 */ 674 read_info=CloneImageInfo(image_info); 675 SetImageInfoBlob(read_info,(void *) NULL,0); 676 (void) FormatLocaleString(read_info->filename,MagickPathExtent,"svg:%s", 677 filename); 678 image=ReadImage(read_info,exception); 679 if (image != (Image *) NULL) 680 { 681 (void) CopyMagickString(image->filename,image_info->filename, 682 MagickPathExtent); 683 (void) CopyMagickString(image->magick_filename,image_info->filename, 684 MagickPathExtent); 685 (void) CopyMagickString(image->magick,"PES",MagickPathExtent); 686 } 687 read_info=DestroyImageInfo(read_info); 688 (void) RelinquishUniqueFileResource(filename); 689 return(GetFirstImageInList(image)); 690 } 691 692 /* 694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 695 % % 696 % % 697 % % 698 % R e g i s t e r P E S I m a g e % 699 % % 700 % % 701 % % 702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 703 % 704 % RegisterPESImage() adds attributes for the PES image format to 705 % the list of supported formats. The attributes include the image format 706 % tag, a method to read and/or write the format, whether the format 707 % supports the saving of more than one frame to the same file or blob, 708 % whether the format supports native in-memory I/O, and a brief 709 % description of the format. 710 % 711 % The format of the RegisterPESImage method is: 712 % 713 % size_t RegisterPESImage(void) 714 % 715 */ 716 ModuleExport size_t RegisterPESImage(void) 717 { 718 MagickInfo 719 *entry; 720 721 entry=AcquireMagickInfo("PES","PES","Embrid Embroidery Format"); 722 entry->decoder=(DecodeImageHandler *) ReadPESImage; 723 entry->magick=(IsImageFormatHandler *) IsPES; 724 (void) RegisterMagickInfo(entry); 725 return(MagickImageCoderSignature); 726 } 727 728 /* 730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 731 % % 732 % % 733 % % 734 % U n r e g i s t e r P E S I m a g e % 735 % % 736 % % 737 % % 738 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 739 % 740 % UnregisterPESImage() removes format registrations made by the 741 % PES module from the list of supported formats. 742 % 743 % The format of the UnregisterPESImage method is: 744 % 745 % UnregisterPESImage(void) 746 % 747 */ 748 ModuleExport void UnregisterPESImage(void) 749 { 750 (void) UnregisterMagickInfo("PES"); 751 } 752