line
stmt
bran
cond
sub
pod
time
code
1
package Image::Embroidery;
2
3
1
1
26489
use 5.006;
1
5
1
46
4
1
1
6
use strict;
1
2
1
50
5
1
1
6
use warnings;
1
2
1
32
6
1
1
6
use Carp;
1
2
1
196
7
1
1
1268
use IO::File;
1
19335
1
156
8
1
1
888
use Bit::Vector;
1
1464
1
47
9
1
1
3101
use Data::Dumper;
1
13589
1
110
10
11
=head1 NAME
12
13
Image::Embroidery - Parse and display embroidery data files
14
15
=head1 SYNOPSIS
16
17
use Image::Embroidery;
18
19
# Constructor
20
$emb = Image::Embroidery->new();
21
22
=head1 ABSTRACT
23
24
Parse and display embroidery data files
25
26
=head1 DESCRIPTION
27
28
This module can be used to read, write and (with GD)
29
display embroidery data files. It currently only supports
30
Tajima DST files, but if there is any interest it could
31
be expanded to deal with other formats. In its current form
32
it isn't ideal for creating or modifying patterns, but
33
I'm reluctant to put much effort into it until someone
34
tells me they are using it.
35
36
=head1 EXAMPLES
37
38
This is an example of using the module to manipulate a
39
data file and write out the changes.
40
41
use Image::Embroidery qw(:all);
42
43
$emb = Image::Embroidery->new();
44
45
$emb->read_file( '/path/to/embroidery.dst' ) or
46
die "Failed to read data file: $!";
47
48
# fiddle with the data structure some. this would make
49
# the 201st entry a normal stitch that went 5 units right,
50
# and 7 units up
51
$emb->{'data'}{'pattern'}[200] = [ $NORMAL, 5, 7 ];
52
53
# supply a new file name, or use the default of
54
# the original file name
55
$emb->write_file( '/path/to/new_embroidery.dst' ) or
56
die "Failed to write data file: $!";
57
58
59
This example demonstrates using GD to create an image
60
file using Image::Embroidery.
61
62
use Image::Embroidery;
63
use GD;
64
65
$emb = Image::Embroidery->new();
66
67
$emb->read_file( '/path/to/embroidery.dst' ) or
68
die "Failed to read data file: $!";
69
70
$im = new GD::Image( $emb->size() );
71
72
# the first color you allocate will be the background color
73
$black = $im->colorAllocate(0,0,0);
74
75
# the order in which you allocate the rest is irrelevant
76
$gray = $im->colorAllocate(128,128,128);
77
$red = $im->colorAllocate(255,0,0);
78
79
# you can control the thickness of the lines that are used to draw the
80
# image. the default thickness is 1, which will let you see individual
81
# stitches. The higher you set the thickness, the smoother the image will
82
# look. A thickness of 3 or 4 is good for showing what the finished product
83
# will look like
84
$im->setThickness(3);
85
86
# the order you specify the colors is the order in which they
87
# will be used. you must specify the correct number of colors
88
$emb->draw_logo($im, $gray, $red);
89
90
open(IMG, ">", "/path/to/embroidery.png");
91
# make sure you use binary mode when running on Windows
92
binmode(IMG);
93
print IMG $im->png;
94
close(IMG);
95
96
Converting from one format to another
97
98
$emb->read_file( '/path/to/embroidery.exp', 'exp' );
99
$emb->save_file( '/path/to/embroidery.dst', 'dst' );
100
101
=head1 METHODS
102
103
=over 4
104
105
=cut
106
107
1
4849
use vars qw(
108
$VERSION
109
@ISA
110
@EXPORT_OK
111
$NORMAL
112
$JUMP
113
$COLOR_CHANGE
114
1
1
19
);
1
3
115
116
require Exporter;
117
118
@ISA = qw(Exporter);
119
120
our %EXPORT_TAGS = ( 'all' => [ qw($NORMAL $JUMP $COLOR_CHANGE) ] );
121
122
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
123
124
$VERSION = '1.2';
125
126
$NORMAL = 0;
127
$JUMP = 1;
128
$COLOR_CHANGE = 2;
129
130
=item I
131
132
my $emb = Image::Embroidery->new();
133
134
The constructor.
135
=cut
136
sub new {
137
0
0
1
my $proto = shift;
138
0
0
my $class = ref($proto) || $proto;
139
0
my $self = {
140
ignore_header_coordinates => 0,
141
};
142
143
0
$self->{'filename'} = undef;
144
145
0
bless ($self, $class);
146
0
return $self;
147
}
148
149
=item I
150
151
$emb->read_file($filename);
152
$emb->read_file($filename, 'tajima');
153
154
Read an embroidery data file in the specified file format.
155
See FILE FORMATS for supported formats. Default is Tajima DST.
156
Returns 0 on failure, 1 on success.
157
158
=cut
159
sub read_file {
160
0
0
1
my ($self, $file, $type) = @_;
161
162
0
0
unless(defined($file)) { carp("No filename provided"); return 0; }
0
0
163
0
0
0
unless(-f "$file" and -r "$file") { carp("File $file unreadable or nonexistant"); return 0; }
0
0
164
0
0
0
my $fh = IO::File->new($file) or carp("Unable to open $file") and return 0;
165
166
0
$self->{'filename'} = $file;
167
168
0
0
$type = (defined($type)) ? lc($type) : 'tajima';
169
170
0
0
0
if($type eq 'tajima' or $type eq 'dst') {
0
0
171
0
return _read_tajima_file($self, $fh);
172
} elsif($type eq 'melco' or $type eq 'exp') {
173
0
return _read_melco_file($self, $fh);
174
} else {
175
0
carp("Request to read unknown file type!");
176
}
177
}
178
179
sub _read_melco_file {
180
0
0
my ($self, $fh) = @_;
181
0
my $record;
182
0
$self->{'data'} = {};
183
184
0
my $colorchange = '8001';
185
186
# i don't know why both of these can be used
187
# for a jump record.
188
0
my $jump1 = '8002';
189
0
my $jump2 = '8004';
190
191
# initialize pattern info, and set defaults for stuff that melco doesn't use (MX/MY/PD multi-volume data)
192
0
foreach my $field ('color_changes', 'stitches', '+X', '-X', '+Y', '-Y', 'MX', 'MY', 'PD') {
193
0
$self->{'data'}{$field} = 0;
194
}
195
0
$self->{'data'}{'label'} = 'FromMelco';
196
197
# current offset from the starting point
198
0
my $currentX = 0;
199
0
my $currentY = 0;
200
201
0
while($fh->read($record, 2)) {
202
0
$record = unpack('H4', $record);
203
204
0
my ($x, $y);
205
206
# remove empty records that are sometimes inserted after color
207
# changes.
208
0
0
0
if($record eq '0000') {
0
0
0
209
0
next;
210
} elsif($record eq $colorchange) {
211
0
push(@{$self->{'data'}{'pattern'}}, [ $COLOR_CHANGE ]);
0
212
0
$self->{'data'}{'color_changes'}++;
213
0
next;
214
} elsif($record eq $jump1 or $record eq $jump2) {
215
0
$fh->read($record, 2);
216
0
($x, $y) = _decode_melco_delta( unpack('H4', $record) );
217
0
push(@{$self->{'data'}{'pattern'}}, [ $JUMP, $x, $y ]);
0
218
# some generators insert 8080 records, but I don't know what they mean
219
} elsif($record =~ /^80/) {
220
0
$fh->read(undef, 2);
221
0
next;
222
} else {
223
0
($x, $y) = _decode_melco_delta($record);
224
225
0
push(@{$self->{'data'}{'pattern'}}, [ $NORMAL, $x, $y ]);
0
226
0
$self->{'data'}{'stitches'}++;
227
}
228
229
# keep track of how big the pattern is
230
0
$currentX += $x;
231
0
$currentY += $y;
232
0
0
if($currentX > $self->{'data'}{'+X'}) { $self->{'data'}{'+X'} = $currentX; }
0
233
0
0
if($currentX < $self->{'data'}{'-X'}) { $self->{'data'}{'-X'} = $currentX; }
0
234
0
0
if($currentY > $self->{'data'}{'+Y'}) { $self->{'data'}{'+Y'} = $currentY; }
0
235
0
0
if($currentY < $self->{'data'}{'-Y'}) { $self->{'data'}{'-Y'} = $currentY; }
0
236
}
237
238
# these are magnitudes, so remove the minus sign
239
0
$self->{'data'}{'-X'} = abs($self->{'data'}{'-X'});
240
0
$self->{'data'}{'-Y'} = abs($self->{'data'}{'-Y'});
241
242
# store the total size of the pattern
243
0
$self->{'data'}{'x_size'} = $self->{'data'}{'+X'} + $self->{'data'}{'-X'};
244
0
$self->{'data'}{'y_size'} = $self->{'data'}{'+Y'} + $self->{'data'}{'-Y'};
245
246
# last position
247
0
$self->{'data'}{'AX'} = $currentX;
248
0
$self->{'data'}{'AY'} = $currentY;
249
250
0
return 1;
251
}
252
253
sub _encode_melco_delta {
254
0
0
my ($x, $y) = @_;
255
0
0
if($x < 0) { $x += 256; }
0
256
0
0
if($y < 0) { $y += 256; }
0
257
258
0
my $delta_record = sprintf('%02x%02x', $x, $y);
259
0
return $delta_record;
260
}
261
262
sub _decode_melco_delta {
263
0
0
my ($record) = @_;
264
0
my $x = hex(substr($record, 0, 2));
265
0
my $y = hex(substr($record, 2, 2));
266
267
# 127 is the max stitch length, 128 is a special value
268
# for encoding jumps and color changes
269
0
0
0
if($x == 128 or $y == 128) {
270
0
return (0, 0);
271
}
272
273
0
0
if($x > 127) { $x = $x - 256; }
0
274
0
0
if($y > 127) { $y = $y - 256; }
0
275
276
0
return ($x, $y);
277
}
278
279
# parse a Tajima DST file
280
sub _read_tajima_file {
281
0
0
my ($self, $fh) = @_;
282
283
0
$self->{'data'} = {};
284
0
my $field;
285
my $stitch;
286
287
0
my @x_incr = ( 0, 0, 81,-81, 0, 0, 0, 0,
288
3, -3, 27,-27, 0, 0, 0, 0,
289
1, -1, 9, -9, 0, 0, 0, 0
290
);
291
0
my @y_incr = ( 0, 0, 0, 0,-81, 81, 0, 0,
292
0, 0, 0, 0,-27, 27, -3, 3,
293
0, 0, 0, 0, -9, 9, -1, 1
294
);
295
296
# keep track of the actual color changes we see, to verify that
297
# it matches what's in the header. some programs incorrectly put
298
# the number of colors in the header, which will be one too large
299
0
my $actual_color_changes = 0;
300
301
# i don't think the order of these header elements
302
# can change, but i'll be flexible.
303
0
while($fh->read($field, 2)) {
304
# read the next character, which should be a colon
305
# that separates the field name from the value. some
306
# file generators forget the colon sometimes, so if
307
# we don't get a colon back, we assume it's part of the data
308
0
$fh->read(my $separator, 1);
309
0
0
unless($separator eq ':') {
310
0
$fh->seek(1,-1);
311
}
312
313
0
0
if($field eq 'LA') {
0
0
0
0
0
0
314
0
$fh->read(my $label, 16);
315
0
($self->{'data'}{'label'} = $label) =~ s/\s*$//;
316
} elsif($field eq 'ST') {
317
0
$fh->read($self->{'data'}{'stitches'}, 7);
318
0
$self->{'data'}{'stitches'} = int($self->{'data'}{'stitches'});
319
} elsif($field eq 'CO') {
320
0
my $color_changes;
321
0
$fh->read($color_changes, 3);
322
0
$self->{'data'}{'color_changes'} = int($color_changes);
323
} elsif($field =~ /^([-+][XY])$/) {
324
0
$fh->read(my $val, 5);
325
0
$self->{'data'}{"$1"} = int($val);
326
} elsif($field =~ /^([AM][XY])$/) {
327
0
my $field_name = $1;
328
0
$fh->read(my $val, 6);
329
0
$val =~ s/ //g;
330
0
0
if($val =~ /^[\+\-]?\s*\d+$/) {
331
0
$self->{'data'}{"$field_name"} = int($val);
332
} else {
333
0
$self->{'data'}{"$field_name"} = 0;
334
}
335
} elsif($field eq 'PD') {
336
0
$fh->read($self->{'data'}{'PD'}, 9);
337
} elsif(unpack('H6', $field) eq '2020') {
338
0
last;
339
} else {
340
0
carp("Invalid header field: $field"); return 0;
0
341
}
342
343
# eat the CR that follows each field (except the last one, in which
344
# case we're eating a 0x20)
345
0
$fh->read(my $junk, 1);
346
}
347
348
0
$self->{'data'}{'x_size'} = $self->{'data'}{'+X'} + $self->{'data'}{'-X'};
349
0
$self->{'data'}{'y_size'} = $self->{'data'}{'+Y'} + $self->{'data'}{'-Y'};
350
351
# skip to the end of the header
352
0
$fh->seek(512, 0);
353
354
# the file spec for Tajima DST indicates that bits 0 and 1 of a
355
# stitch should always be '1', but since they don't mean anything,
356
# and some file generators don't follow the spec very carefully,
357
# we just require them to be consistent throughout the file.
358
# we store the values in the first stitch that we find, then
359
# compare subsequent stitches to the first value we saw.
360
0
my $stitch_bit_0;
361
my $stitch_bit_1;
362
363
364
0
while($fh->read($stitch, 3)) {
365
0
my $v = Bit::Vector->new(24);
366
0
$v->from_Hex(unpack('H6', $stitch));
367
368
# just check for consistency to detect corrupt files, these bits are meaningless
369
0
0
if(defined($stitch_bit_0)) {
370
0
0
0
unless($v->bit_test(1) == $stitch_bit_1 and $v->bit_test(0) == $stitch_bit_0) {
371
0
carp("Possibly corrupt data file: ", unpack('H6', $stitch));
372
}
373
} else {
374
0
$stitch_bit_0 = $v->bit_test(0);
375
0
$stitch_bit_1 = $v->bit_test(1);
376
}
377
378
# bit 6 is off for jumps and normal stitches
379
0
0
if(!$v->bit_test(6)) {
0
380
0
my ($x, $y) = (0, 0);
381
# first two bits are not used. 6 and 7 are record type flags
382
0
foreach my $index(2..5, 8..23) {
383
0
0
$x += $x_incr[$index] if($v->bit_test($index));
384
0
0
$y += $y_incr[$index] if($v->bit_test($index));
385
}
386
387
# bit 7 will be off for normal stitches, on for jumps
388
0
push(@{$self->{'data'}{'pattern'}}, [ $v->bit_test(7), $x, $y ]);
0
389
390
} elsif(!$v->bit_test(7)) {
391
0
carp("Invalid operation code");
392
0
return 0;
393
} else {
394
0
0
if($v->to_Hex() eq '0000C3') {
0
395
0
push(@{$self->{'data'}{'pattern'}}, [ $COLOR_CHANGE ]);
0
396
0
$actual_color_changes++;
397
} elsif($v->to_Hex() eq '0000F3') {
398
# this is the 'stop' code. sometimes there is trailing data, so
399
# stop reading now.
400
0
last;
401
} else {
402
0
carp("Invalid operation code");
403
0
return 0;
404
}
405
}
406
}
407
408
# trust the data more than the header
409
0
0
if($actual_color_changes != $self->{'data'}{'color_changes'}) {
410
# TODO some kind of logging ("Tajima file header lists incorrect number of color changes: $self->{'data'}{'color_changes'}, should be $actual_color_changes");
411
0
$self->{'data'}{'color_changes'} = $actual_color_changes;
412
}
413
414
0
return 1;
415
}
416
417
=item I
418
419
$emb->write_file();
420
$emb->write_file( $filename );
421
$emb->write_file( $filename, $format );
422
423
Output the contents of the object's pattern to the specified
424
file, using the specified file format. If the filename
425
is omitted, the default filename will be the last
426
file that was successfully read using I.
427
See FILE FORMATS for supported formats. Default is Tajima DST.
428
Returns 0 on failure, 1 on success.
429
430
=cut
431
sub write_file {
432
0
0
1
my ($self, $file, $type) = @_;
433
434
0
0
unless(defined($self->{'data'}{'pattern'})) {
435
0
carp("You do not have a pattern to write");
436
0
return 0;
437
}
438
439
0
0
unless(defined($file)) {
440
0
0
if(defined($self->{'filename'})) {
441
0
$file = $self->{'filename'};
442
} else {
443
0
carp("No filename supplied");
444
0
return 0;
445
}
446
}
447
0
0
0
my $fh = IO::File->new($file, "w") or carp("Unable to write to $file") and return 0;
448
449
# for windows
450
0
binmode($fh);
451
452
0
0
if(defined($type)) {
453
0
$type = lc($type);
454
} else {
455
0
$type = 'tajima';
456
}
457
458
0
0
0
if($type eq 'tajima' or $type eq 'dst') {
0
0
459
0
return _write_tajima_file($self, $fh);
460
} elsif($type eq 'melco' or $type eq 'exp') {
461
0
return _write_melco_file($self, $fh);
462
} else {
463
0
carp("Request to write unknown file type!");
464
0
return 0;
465
}
466
}
467
468
# output a Melco EXP file
469
sub _write_melco_file {
470
0
0
my ($self, $fh) = @_;
471
472
0
foreach my $entry (@{$self->{'data'}{'pattern'}}) {
0
473
0
0
if($entry->[0] == $NORMAL) {
0
474
0
print $fh pack('H4', _encode_melco_delta($entry->[1], $entry->[2]));
475
} elsif($entry->[0] == $JUMP) {
476
0
print $fh pack('H4', '8004'); # this can be either 8002 or 8004
477
0
print $fh pack('H4', _encode_melco_delta($entry->[1], $entry->[2]));
478
} else { # color change
479
# i don't think the extra zero records are required, but most generators
480
# seem to put them in there.
481
0
print $fh pack('H8', '80010000');
482
}
483
}
484
}
485
486
# output a Tajima DST file
487
sub _write_tajima_file {
488
0
0
my ($self, $fh) = @_;
489
490
# header
491
0
printf $fh "LA:%-16s\r", $self->{'data'}{'label'};
492
0
printf $fh "ST:%07d\r", $self->{'data'}{'stitches'};
493
0
printf $fh "CO:%03d\r", $self->{'data'}{'color_changes'};
494
495
0
for('+X', '-X', '+Y', '-Y') { printf $fh "$_:%05d\r", $self->{'data'}{$_}; }
0
496
497
0
foreach my $key ('AX', 'AY', 'MX', 'MY') {
498
0
0
if($self->{'data'}{$key} < 0) { printf $fh "$key:-%5s\r", abs($self->{'data'}{$key}); }
0
499
0
else { printf $fh "$key:+%5s\r", $self->{'data'}{$key}; }
500
}
501
502
0
printf $fh "PD:%9s", $self->{'data'}{'PD'};
503
504
# pad out the rest of the header (512 bytes total)
505
0
printf $fh ' 'x386;
506
507
# data
508
0
foreach my $entry (@{$self->{'data'}{'pattern'}}) {
0
509
0
0
0
if($entry->[0] == $NORMAL or $entry->[0] == $JUMP) {
510
0
print $fh pack('B24', _get_tajima_move_record(@{$entry}));
0
511
} else { # color change
512
0
print $fh pack('H6', '0000C3');
513
}
514
}
515
516
# this is the 'stop' code
517
0
print $fh pack('H6', '0000F3');
518
519
0
$fh->close();
520
521
0
return 1;
522
}
523
524
sub _get_tajima_move_record {
525
0
0
my ($jump,$x,$y) = @_;
526
0
my ($b0, $b1, $b2);
527
528
0
my %x = _get_tajima_components($x);
529
0
my %y = _get_tajima_components($y);
530
531
# byte 0
532
0
0
$b0.=($y{ 1}?'1':'0');
533
0
0
$b0.=($y{ -1}?'1':'0');
534
0
0
$b0.=($y{ 9}?'1':'0');
535
0
0
$b0.=($y{ -9}?'1':'0');
536
0
0
$b0.=($x{ -9}?'1':'0');
537
0
0
$b0.=($x{ 9}?'1':'0');
538
0
0
$b0.=($x{ -1}?'1':'0');
539
0
0
$b0.=($x{ 1}?'1':'0');
540
541
# byte 1
542
0
0
$b1.=($y{ 3}?'1':'0');
543
0
0
$b1.=($y{ -3}?'1':'0');
544
0
0
$b1.=($y{ 27}?'1':'0');
545
0
0
$b1.=($y{-27}?'1':'0');
546
0
0
$b1.=($x{-27}?'1':'0');
547
0
0
$b1.=($x{ 27}?'1':'0');
548
0
0
$b1.=($x{ -3}?'1':'0');
549
0
0
$b1.=($x{ 3}?'1':'0');
550
551
# byte 2
552
0
0
$b2.=($jump?'1':'0');
553
0
$b2.='0';
554
0
0
$b2.=($y{ 81}?'1':'0');
555
0
0
$b2.=($y{-81}?'1':'0');
556
0
0
$b2.=($x{-81}?'1':'0');
557
0
0
$b2.=($x{ 81}?'1':'0');
558
0
$b2.='1';
559
0
$b2.='1';
560
561
# debug
562
# print "x: $x => "; foreach (keys %x) { print "$_ "; } print "\n";
563
# print "y: $y => "; foreach (keys %y) { print "$_ "; } print "\n";
564
# print "$b0 $b1 $b2\n";
565
566
0
return($b0.$b1.$b2);
567
}
568
569
sub _get_tajima_components {
570
0
0
my ($n) = @_;
571
0
my ($s,%c);
572
573
0
for my $p (reverse(0..4)) {
574
0
0
if($n<0) { $n*=-1; $s=!$s; }
0
0
575
0
my $m = 0;
576
0
for my $q (0..$p-1) { $m+=3**$q; }
0
577
0
0
if($n>=3**$p-$m) { $n-=3**$p; $c{($s?-1:1)*3**$p}=1; }
0
0
0
578
}
579
0
return(%c);
580
}
581
582
=item I
583
584
$emb->draw_logo( $gd_image_object, @colors );
585
586
Write an image of the stored pattern to the supplied
587
GD::Image object. You must supply the correct number of
588
colors for the pattern. Color arguments are those returned by
589
GD::Image::colorAllocate. Returns 0 on failure, 1 on success.
590
591
=cut
592
sub draw_logo {
593
0
0
1
my ($self, $im, @colors) = @_;
594
595
0
0
unless(defined($self->{'data'}{'pattern'})) {
596
0
carp("You do not have a pattern to display");
597
0
return 0;
598
}
599
600
0
0
unless(scalar(@colors) == $self->{'data'}{'color_changes'} + 1) {
601
0
carp($self->{'data'}{'color_changes'} + 1, " colors required, ", scalar(@colors), " colors supplied");
602
0
return 0;
603
}
604
605
0
my ($x, $y);
606
607
0
0
if($self->{'ignore_header_coordinates'}) {
608
0
($x, $y) = ( int($self->{'data'}{'x_size'}/2), int($self->{'data'}{'y_size'}/2));
609
} else {
610
0
($x, $y) = ($self->{'data'}{'+X'}, $self->{'data'}{'y_size'} - $self->{'data'}{'+Y'});
611
}
612
613
0
my ($new_x, $new_y);
614
615
0
foreach my $stitch (@{$self->{'data'}{'pattern'}}) {
0
616
0
0
if($stitch->[0] == $NORMAL) {
0
0
617
0
$new_x = $x + $stitch->[1];
618
0
$new_y = $y - $stitch->[2];
619
0
$im->line($x, $y, $new_x, $new_y, $colors[0]);
620
0
$x = $new_x; $y = $new_y;
0
621
} elsif($stitch->[0] == $JUMP) {
622
0
$x = $x + $stitch->[1];
623
0
$y = $y - $stitch->[2];
624
} elsif($stitch->[0] == $COLOR_CHANGE) {
625
0
shift @colors;
626
}
627
}
628
0
return 1;
629
}
630
631
=item I
632
633
my $ignoring = $emb->ignore_header_coordinates;
634
$emb->ignore_header_coordinates( 1 );
635
636
Get or set whether to ignore the starting coordinates
637
in the file header, and assume that the pattern begins
638
in the center. Some programs that generate Tajima DST
639
files put incorrect values into the header that cause
640
the image to be off center. Enabling this will correct
641
those images, but will display images with correct
642
(but offcenter) starting points offset. This MUST be
643
called before calling read_file.
644
645
=cut
646
sub ignore_header_coordinates {
647
0
0
1
my ($self, $ignore) = @_;
648
649
0
0
if(defined($ignore)) {
650
0
$self->{'ignore_header_coordinates'} = $ignore;
651
}
652
653
0
return $self->{'ignore_header_coordinates'};
654
}
655
656
=item I
657
658
my $label = $emb->label();
659
$emb->label( $new_label );
660
661
Get or set the label that will be inserted into the file headers,
662
if the output format supports it.
663
664
=cut
665
sub label {
666
0
0
1
my ($self, $label) = @_;
667
668
0
0
if(defined($label)) {
669
0
$self->{'label'} = $label;
670
}
671
0
return $self->{'label'};
672
}
673
674
=item I
675
676
my ($x, $y) = $emb->size();
677
678
Returns the X and Y size of the pattern.
679
680
=cut
681
sub size {
682
0
0
1
my ($self) = @_;
683
0
return ($self->{'data'}{'x_size'}, $self->{'data'}{'y_size'});
684
}
685
686
=item I
687
688
my $changes = $emb->get_color_changes();
689
690
Return the number of colors changes in the pattern.
691
692
=cut
693
sub get_color_changes {
694
0
0
1
my ($self) = @_;
695
0
return $self->{'data'}{'color_changes'};
696
}
697
698
=item I
699
700
my $colors = $emb->get_color_count();
701
702
Returns the number of colors in the pattern.
703
704
=cut
705
sub get_color_count {
706
0
0
1
my ($self) = @_;
707
0
return ($self->{'data'}{'color_changes'} + 1);
708
}
709
710
=item I
711
712
my $count = $emb->get_stitch_count();
713
714
Return the total number of stitches in the pattern.
715
716
=cut
717
sub get_stitch_count {
718
0
0
1
my ($self) = @_;
719
0
return $self->{'data'}{'stitches'};
720
}
721
722
=item I
723
724
my ($x, $y) = $emb->get_end_point();
725
726
Returns the position of the last point in the pattern,
727
relative to the starting point.
728
729
=cut
730
sub get_end_point {
731
0
0
1
my ($self) = @_;
732
0
return ($self->{'data'}{'AX'}, $self->{'data'}{'AY'});
733
}
734
735
=item I
736
737
my ($plus_x, $minus_x, $plus_y, $minus_y) = $emb->get_abs_size();
738
739
Returns the distance from the starting point to
740
the edges of the pattern, in the order +X, -X, +Y, -Y.
741
742
=cut
743
sub get_abs_size {
744
0
0
1
my ($self) = @_;
745
0
return ($self->{'data'}{'+X'}, $self->{'data'}{'-X'},
746
$self->{'data'}{'+Y'}, $self->{'data'}{'-Y'});
747
}
748
749
750
1;
751
__END__