File Coverage

blib/lib/Image/Embroidery.pm
Criterion Covered Total %
statement 24 304 7.8
branch 0 160 0.0
condition 0 34 0.0
subroutine 8 28 28.5
pod 12 12 100.0
total 44 538 8.1


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__