File Coverage

/root/.cpan/build/Imager-1.017-0/blib/lib/Imager.pm
Criterion Covered Total %
statement 1686 2240 75.2
branch 978 1398 69.9
condition 191 338 56.5
subroutine 141 159 88.6
pod 1 105 0.9
total 2997 4240 70.6


line stmt bran cond sub pod time code
1             package Imager;
2 58     58   2051302 use 5.006;
  58         530  
3              
4 58     58   266 use strict;
  58         90  
  58         1305  
5 58     58   302 use Scalar::Util;
  58         105  
  58         2535  
6 58     58   21479 use Imager::Color;
  58         137  
  58         1876  
7 58     58   22621 use Imager::Color::Float;
  58         148  
  58         1647  
8 58     58   23757 use Imager::Font;
  58         128  
  58         1617  
9 58     58   20923 use Imager::TrimColorList;
  58         128  
  58         1771  
10 58     58   355 use warnings::register qw(tagcodes channelmask);
  58         91  
  58         23471  
11              
12             our $ERRSTR;
13              
14             our @EXPORT_OK = qw(
15             init
16             init_log
17             DSO_open
18             DSO_close
19             DSO_funclist
20             DSO_call
21              
22             load_plugin
23             unload_plugin
24              
25             i_list_formats
26              
27             i_color_new
28             i_color_set
29             i_color_info
30              
31             i_img_info
32              
33             i_img_setmask
34             i_img_getmask
35              
36             i_line
37             i_line_aa
38             i_box
39             i_box_filled
40             i_arc
41             i_circle_aa
42              
43             i_bezier_multi
44             i_poly_aa
45             i_poly_aa_cfill
46              
47             i_copyto
48             i_rubthru
49             i_scaleaxis
50             i_scale_nn
51             i_haar
52             i_count_colors
53              
54             i_gaussian
55             i_conv
56              
57             i_convert
58             i_map
59              
60             i_img_diff
61              
62             i_tt_set_aa
63             i_tt_cp
64             i_tt_text
65             i_tt_bbox
66              
67             i_readpnm_wiol
68             i_writeppm_wiol
69              
70             i_readraw_wiol
71             i_writeraw_wiol
72              
73             i_contrast
74             i_hardinvert
75             i_noise
76             i_bumpmap
77             i_postlevels
78             i_mosaic
79             i_watermark
80              
81             malloc_state
82              
83             list_formats
84              
85             i_gifquant
86              
87             newfont
88             newcolor
89             newcolour
90             NC
91             NF
92             NCF
93             );
94              
95             our @EXPORT=qw(
96             );
97              
98             our %EXPORT_TAGS=
99             (handy => [qw(
100             newfont
101             newcolor
102             NF
103             NC
104             NCF
105             )],
106             all => [@EXPORT_OK],
107             default => [qw(
108             load_plugin
109             unload_plugin
110             )]);
111              
112             # registered file readers
113             my %readers;
114              
115             # registered file writers
116             my %writers;
117              
118             # modules we attempted to autoload
119             my %attempted_to_load;
120              
121             # errors from loading files
122             my %file_load_errors;
123              
124             # what happened when we tried to load
125             my %reader_load_errors;
126             my %writer_load_errors;
127              
128             # library keys that are image file formats
129             my %file_formats = map { $_ => 1 } qw/tiff pnm gif png jpeg raw bmp tga/;
130              
131             # image pixel combine types
132             my @combine_types =
133             qw/none normal multiply dissolve add subtract diff lighten darken
134             hue saturation value color/;
135             my %combine_types;
136             @combine_types{@combine_types} = 0 .. $#combine_types;
137             $combine_types{mult} = $combine_types{multiply};
138             $combine_types{'sub'} = $combine_types{subtract};
139             $combine_types{sat} = $combine_types{saturation};
140              
141             # this will be used to store global defaults at some point
142             my %defaults;
143              
144             our $VERSION;
145              
146             BEGIN {
147 58     58   377 require Exporter;
148 58         2981 my $ex_version = eval $Exporter::VERSION;
149 58 50       357 if ($ex_version < 5.57) {
150 0         0 our @ISA = qw(Exporter);
151             }
152 58         103 $VERSION = '1.017';
153 58         212 require XSLoader;
154 58         157678 XSLoader::load(Imager => $VERSION);
155             }
156              
157             my %formats_low;
158             my %format_classes =
159             (
160             png => "Imager::File::PNG",
161             gif => "Imager::File::GIF",
162             tiff => "Imager::File::TIFF",
163             jpeg => "Imager::File::JPEG",
164             w32 => "Imager::Font::W32",
165             ft2 => "Imager::Font::FT2",
166             t1 => "Imager::Font::T1",
167             );
168              
169             our %formats;
170              
171             tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes;
172              
173             our %filters;
174              
175             our $DEBUG;
176             our %OPCODES;
177             our $FORMATGUESS;
178             our $warn_obsolete;
179              
180             BEGIN {
181 58     58   1423 for(i_list_formats()) { $formats_low{$_}++; }
  290         625  
182              
183 58         693 %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
184              
185 58         123 $DEBUG=0;
186              
187             # the members of the subhashes under %filters are:
188             # callseq - a list of the parameters to the underlying filter in the
189             # order they are passed
190             # callsub - a code ref that takes a named parameter list and calls the
191             # underlying filter
192             # defaults - a hash of default values
193             # names - defines names for value of given parameters so if the names
194             # field is foo=> { bar=>1 }, and the user supplies "bar" as the
195             # foo parameter, the filter will receive 1 for the foo
196             # parameter
197             $filters{contrast}={
198             callseq => ['image','intensity'],
199 1         3 callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
  1         1464  
200 58         436 };
201              
202             $filters{noise} ={
203             callseq => ['image', 'amount', 'subtype'],
204             defaults => { amount=>3,subtype=>0 },
205 1         6 callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
  1         2018  
206 58         339 };
207              
208             $filters{hardinvert} ={
209             callseq => ['image'],
210             defaults => { },
211 3         8 callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
  3         1061  
212 58         255 };
213              
214             $filters{hardinvertall} =
215             {
216             callseq => ['image'],
217             defaults => { },
218 2         7 callsub => sub { my %hsh=@_; i_hardinvertall($hsh{image}); }
  2         177  
219 58         275 };
220              
221             $filters{autolevels_skew} ={
222             callseq => ['image','lsat','usat','skew'],
223             defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
224 1         4 callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
  1         2931  
225 58         376 };
226              
227             $filters{autolevels} ={
228             callseq => ['image','lsat','usat'],
229             defaults => { lsat=>0.1,usat=>0.1 },
230 3         9 callsub => sub { my %hsh=@_; i_autolevels_mono($hsh{image},$hsh{lsat},$hsh{usat}); }
  3         1775  
231 58         319 };
232              
233             $filters{turbnoise} ={
234             callseq => ['image'],
235             defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
236 1         4 callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
  1         60383  
237 58         382 };
238              
239             $filters{radnoise} ={
240             callseq => ['image'],
241             defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
242 1         8 callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
  1         63260  
243 58         397 };
244              
245             $filters{conv} =
246             {
247             callseq => ['image', 'coef'],
248             defaults => { },
249             callsub =>
250             sub {
251 46         123 my %hsh=@_;
252             i_conv($hsh{image},$hsh{coef})
253 46 100       454484 or die Imager->_error_as_msg() . "\n";
254             }
255 58         376 };
256              
257             $filters{gradgen} =
258             {
259             callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
260             defaults => { dist => 0 },
261             callsub =>
262             sub {
263 1         6 my %hsh=@_;
264 1         3 my @colors = @{$hsh{colors}};
  1         5  
265             $_ = _color($_)
266 1         6 for @colors;
267 1         3364 i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
268             }
269 58         362 };
270              
271             $filters{nearest_color} =
272             {
273             callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
274             defaults => { },
275             callsub =>
276             sub {
277 1         9 my %hsh=@_;
278             # make sure the segments are specified with colors
279 1         2 my @colors;
280 1         2 for my $color (@{$hsh{colors}}) {
  1         3  
281 3 50       5 my $new_color = _color($color)
282             or die $Imager::ERRSTR."\n";
283 3         6 push @colors, $new_color;
284             }
285              
286             i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
287             $hsh{dist})
288 1 50       3198 or die Imager->_error_as_msg() . "\n";
289             },
290 58         526 };
291             $filters{gaussian} = {
292             callseq => [ 'image', 'stddev' ],
293             defaults => { },
294 2         6 callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
  2         95643  
295 58         305 };
296             $filters{gaussian2} = {
297             callseq => [ 'image', 'stddevX', 'stddevY' ],
298             defaults => { },
299 5         14 callsub => sub { my %hsh = @_; i_gaussian2($hsh{image}, $hsh{stddevX}, $hsh{stddevY}); },
  5         139740  
300 58         353 };
301             $filters{mosaic} =
302             {
303             callseq => [ qw(image size) ],
304             defaults => { size => 20 },
305 1         3 callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
  1         1648  
306 58         292 };
307             $filters{bumpmap} =
308             {
309             callseq => [ qw(image bump elevation lightx lighty st) ],
310             defaults => { elevation=>0, st=> 2 },
311             callsub => sub {
312 1         6 my %hsh = @_;
313             i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
314 1         5224 $hsh{lightx}, $hsh{lighty}, $hsh{st});
315             },
316 58         331 };
317             $filters{bumpmap_complex} =
318             {
319             callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
320             defaults => {
321             channel => 0,
322             tx => 0,
323             ty => 0,
324             Lx => 0.2,
325             Ly => 0.4,
326             Lz => -1.0,
327             cd => 1.0,
328             cs => 40,
329             n => 1.3,
330             Ia => [0,0,0],
331             Il => [255,255,255],
332             Is => [255,255,255],
333             },
334             callsub => sub {
335 1         6 my %hsh = @_;
336 1         3 for my $cname (qw/Ia Il Is/) {
337 3         8 my $old = $hsh{$cname};
338 3 50       6 my $new_color = _color($old)
339             or die $Imager::ERRSTR, "\n";
340 3         10 $hsh{$cname} = $new_color;
341             }
342             i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
343             $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
344             $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
345 1         8023 $hsh{Is});
346             },
347 58         704 };
348             $filters{postlevels} =
349             {
350             callseq => [ qw(image levels) ],
351             defaults => { levels => 10 },
352 1         11 callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
  1         1713  
353 58         336 };
354             $filters{watermark} =
355             {
356             callseq => [ qw(image wmark tx ty pixdiff) ],
357             defaults => { pixdiff=>10, tx=>0, ty=>0 },
358             callsub =>
359             sub {
360 1         4 my %hsh = @_;
361             i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
362 1         2046 $hsh{pixdiff});
363             },
364 58         339 };
365             $filters{fountain} =
366             {
367             callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
368             names => {
369             ftype => { linear => 0,
370             bilinear => 1,
371             radial => 2,
372             radial_square => 3,
373             revolution => 4,
374             conical => 5 },
375             repeat => { none => 0,
376             sawtooth => 1,
377             triangle => 2,
378             saw_both => 3,
379             tri_both => 4,
380             },
381             super_sample => {
382             none => 0,
383             grid => 1,
384             random => 2,
385             circle => 3,
386             },
387             combine => {
388             none => 0,
389             normal => 1,
390             multiply => 2, mult => 2,
391             dissolve => 3,
392             add => 4,
393             subtract => 5, 'sub' => 5,
394             diff => 6,
395             lighten => 7,
396             darken => 8,
397             hue => 9,
398             sat => 10,
399             value => 11,
400             color => 12,
401             },
402             },
403             defaults => { ftype => 0, repeat => 0, combine => 0,
404             super_sample => 0, ssample_param => 4,
405             segments=>[
406             [ 0, 0.5, 1,
407             [0,0,0],
408             [255, 255, 255],
409             0, 0,
410             ],
411             ],
412             },
413             callsub =>
414             sub {
415 10         39 my %hsh = @_;
416              
417             # make sure the segments are specified with colors
418 10         11 my @segments;
419 10         14 for my $segment (@{$hsh{segments}}) {
  10         18  
420 13         28 my @new_segment = @$segment;
421            
422 13   100     30 $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
423 12         27 push @segments, \@new_segment;
424             }
425              
426             i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
427             $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
428 9 50       122906 $hsh{ssample_param}, \@segments)
429             or die Imager->_error_as_msg() . "\n";
430             },
431 58         1723 };
432             $filters{unsharpmask} =
433             {
434             callseq => [ qw(image stddev scale) ],
435             defaults => { stddev=>2.0, scale=>1.0 },
436             callsub =>
437             sub {
438 1         4 my %hsh = @_;
439 1         21021 i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
440             },
441 58         325 };
442              
443 58         206 $FORMATGUESS=\&def_guess_type;
444              
445 58         1184716 $warn_obsolete = 1;
446             }
447              
448             #
449             # Non methods
450             #
451              
452             # initialize Imager
453             # NOTE: this might be moved to an import override later on
454              
455             sub import {
456 98     98   941 my $i = 1;
457 98         429 while ($i < @_) {
458 34 50       120 if ($_[$i] eq '-log-stderr') {
459 0         0 init_log(undef, 4);
460 0         0 splice(@_, $i, 1);
461             }
462             else {
463 34         78 ++$i;
464             }
465             }
466 98         27249 goto &Exporter::import;
467             }
468              
469             sub init_log {
470 7     7 0 638 Imager->open_log(log => $_[0], level => $_[1]);
471             }
472              
473              
474             sub init {
475 8     8 0 683 my %parms=(loglevel=>1,@_);
476              
477 8 50       34 if (exists $parms{'warn_obsolete'}) {
478 0         0 $warn_obsolete = $parms{'warn_obsolete'};
479             }
480              
481 8 50       29 if ($parms{'log'}) {
482             Imager->open_log(log => $parms{log}, level => $parms{loglevel})
483 8 50       47 or return;
484             }
485              
486 8 50       31 if (exists $parms{'t1log'}) {
487 0 0       0 if ($formats{t1}) {
488 0 0       0 if (Imager::Font::T1::i_init_t1($parms{'t1log'})) {
489 0         0 Imager->_set_error(Imager->_error_as_msg);
490 0         0 return;
491             }
492             }
493             }
494              
495 8         26 return 1;
496             }
497              
498             {
499             my $is_logging = 0;
500              
501             sub open_log {
502 34     34 0 1685 my $class = shift;
503 34         163 my (%opts) = ( loglevel => 1, @_ );
504              
505 34         6824 $is_logging = i_init_log($opts{log}, $opts{loglevel});
506 34 50       201 unless ($is_logging) {
507 0         0 Imager->_set_error(Imager->_error_as_msg());
508 0         0 return;
509             }
510              
511 34         253 Imager->log("Imager $VERSION starting\n", 1);
512              
513 34         190 return $is_logging;
514             }
515              
516             sub close_log {
517 18     18 0 32430 i_init_log(undef, -1);
518 18         407 $is_logging = 0;
519             }
520              
521             sub log {
522 35     35 0 110 my ($class, $message, $level) = @_;
523              
524 35 100       109 defined $level or $level = 1;
525              
526 35         1215 i_log_entry($message, $level);
527             }
528              
529             sub is_logging {
530 0     0 0 0 return $is_logging;
531             }
532             }
533              
534             END {
535 58 50   58   93125 if ($DEBUG) {
536 0         0 print "shutdown code\n";
537             # for(keys %instances) { $instances{$_}->DESTROY(); }
538 0         0 malloc_state(); # how do decide if this should be used? -- store something from the import
539 0         0 print "Imager exiting\n";
540             }
541             }
542              
543             # Load a filter plugin
544              
545             our %DSOs;
546              
547             sub load_plugin {
548 0     0 0 0 my ($filename)=@_;
549 0         0 my $i;
550              
551 0 0       0 if ($^O eq 'android') {
552 0         0 require File::Spec;
553 0         0 $filename = File::Spec->rel2abs($filename);
554             }
555              
556 0         0 my ($DSO_handle,$str)=DSO_open($filename);
557 0 0       0 if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
  0         0  
  0         0  
558 0         0 my %funcs=DSO_funclist($DSO_handle);
559 0 0       0 if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
  0         0  
  0         0  
  0         0  
  0         0  
560 0         0 $i=0;
561 0 0       0 for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
  0         0  
  0         0  
  0         0  
  0         0  
562              
563 0         0 $DSOs{$filename}=[$DSO_handle,\%funcs];
564              
565 0         0 for(keys %funcs) {
566 0         0 my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
567 0 0       0 $DEBUG && print "eval string:\n",$evstr,"\n";
568 0         0 eval $evstr;
569 0 0       0 print $@ if $@;
570             }
571 0         0 return 1;
572             }
573              
574             # Unload a plugin
575              
576             sub unload_plugin {
577 0     0 0 0 my ($filename)=@_;
578              
579 0 0       0 if ($^O eq 'android') {
580 0         0 require File::Spec;
581 0         0 $filename = File::Spec->rel2abs($filename);
582             }
583              
584 0 0       0 if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
  0         0  
  0         0  
585 0         0 my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
  0         0  
586 0         0 for(keys %{$funcref}) {
  0         0  
587 0         0 delete $filters{$_};
588 0 0       0 $DEBUG && print "unloading: $_\n";
589             }
590 0         0 my $rc=DSO_close($DSO_handle);
591 0 0       0 if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
  0         0  
  0         0  
592 0         0 return 1;
593             }
594              
595             # take the results of i_error() and make a message out of it
596             sub _error_as_msg {
597 178     178   191916 return join(": ", map $_->[0], i_errors());
598             }
599              
600             # this function tries to DWIM for color parameters
601             # color objects are used as is
602             # simple scalars are simply treated as single parameters to Imager::Color->new
603             # hashrefs are treated as named argument lists to Imager::Color->new
604             # arrayrefs are treated as list arguments to Imager::Color->new iff any
605             # parameter is > 1
606             # other arrayrefs are treated as list arguments to Imager::Color::Float
607              
608             sub _color {
609 1023     1023   1396 my $arg = shift;
610             # perl 5.6.0 seems to do weird things to $arg if we don't make an
611             # explicitly stringified copy
612             # I vaguely remember a bug on this on p5p, but couldn't find it
613             # through bugs.perl.org (I had trouble getting it to find any bugs)
614 1023         2266 my $copy = $arg . "";
615 1023         1189 my $result;
616              
617 1023 100       1625 if (ref $arg) {
618 659 100 100     2042 if (UNIVERSAL::isa($arg, "Imager::Color")
619             || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
620 520         690 $result = $arg;
621             }
622             else {
623 139 100       624 if ($copy =~ /^HASH\(/) {
    50          
624 3         20 $result = Imager::Color->new(%$arg);
625             }
626             elsif ($copy =~ /^ARRAY\(/) {
627 136         446 $result = Imager::Color->new(@$arg);
628             }
629             else {
630 0         0 $Imager::ERRSTR = "Not a color";
631             }
632             }
633             }
634             else {
635             # assume Imager::Color::new knows how to handle it
636 364         1049 $result = Imager::Color->new($arg);
637             }
638              
639 1023         2763 return $result;
640             }
641              
642             sub _combine {
643 123     123   379 my ($self, $combine, $default) = @_;
644              
645 123 100 100     442 if (!defined $combine && ref $self) {
646 55         100 $combine = $self->{combine};
647             }
648 123 100       279 defined $combine or $combine = $defaults{combine};
649 123 100       259 defined $combine or $combine = $default;
650              
651 123 100       304 if (exists $combine_types{$combine}) {
652 85         150 $combine = $combine_types{$combine};
653             }
654            
655 123         287 return $combine;
656             }
657              
658             sub _valid_image {
659 8601     8601   12069 my ($self, $method) = @_;
660              
661 8601 50       14219 ref $self
662             or return Imager->_set_error("$method needs an image object");
663              
664 8601 100 66     38399 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
665              
666 68 50       162 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
667 68 50       218 $msg = "$method: $msg" if $method;
668 68         191 $self->_set_error($msg);
669              
670 68         549 return;
671             }
672              
673             # returns first defined parameter
674             sub _first {
675 76     76   135 for (@_) {
676 162 100       316 return $_ if defined $_;
677             }
678 1         2 return undef;
679             }
680              
681             #
682             # Methods to be called on objects.
683             #
684              
685             # Create a new Imager object takes very few parameters.
686             # usually you call this method and then call open from
687             # the resulting object
688              
689             sub new {
690 1272     1272 0 214311 my $class = shift;
691 1272         1931 my $self ={};
692 1272         2759 my %hsh=@_;
693 1272         1941 bless $self,$class;
694 1272         2380 $self->{IMG}=undef; # Just to indicate what exists
695 1272         1750 $self->{ERRSTR}=undef; #
696 1272         1792 $self->{DEBUG}=$DEBUG;
697 1272 50       2445 $self->{DEBUG} and print "Initialized Imager\n";
698 1272 100 100     12711 if (defined $hsh{file} ||
    100 66        
    50 66        
      33        
      66        
      66        
      66        
699             defined $hsh{fh} ||
700             defined $hsh{fd} ||
701             defined $hsh{callback} ||
702             defined $hsh{readcb} ||
703             defined $hsh{data} ||
704             defined $hsh{io}) {
705             # allow $img = Imager->new(file => $filename)
706 14         30 my %extras;
707            
708             # type is already used as a parameter to new(), rename it for the
709             # call to read()
710 14 100       35 if ($hsh{filetype}) {
711 6         16 $extras{type} = $hsh{filetype};
712             }
713 14 100       66 unless ($self->read(%hsh, %extras)) {
714 5         25 $Imager::ERRSTR = $self->{ERRSTR};
715 5         26 return;
716             }
717             }
718             elsif (defined $hsh{xsize} || defined $hsh{ysize}) {
719 554 100       1676 unless ($self->img_set(%hsh)) {
720 25         44 $Imager::ERRSTR = $self->{ERRSTR};
721 25         78 return;
722             }
723             }
724             elsif (%hsh) {
725 0         0 Imager->_set_error("new: supply xsize and ysize or a file access parameter or no parameters");
726 0         0 return;
727             }
728              
729 1242         3202 return $self;
730             }
731              
732             # Copy an entire image with no changes
733             # - if an image has magic the copy of it will not be magical
734              
735             sub copy {
736 217     217 0 23876 my $self = shift;
737              
738 217 100       443 $self->_valid_image("copy")
739             or return;
740              
741 216 100       550 unless (defined wantarray) {
742 1         4 my @caller = caller;
743 1         15 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
744 1         50 return;
745             }
746              
747 215         529 my $newcopy=Imager->new();
748 215         109009 $newcopy->{IMG} = i_copy($self->{IMG});
749 215         985 return $newcopy;
750             }
751              
752             # Paste a region
753              
754             sub paste {
755 29     29 0 553 my $self = shift;
756              
757 29 100       62 $self->_valid_image("paste")
758             or return;
759              
760 28         165 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
761 28   100     115 my $src = $input{img} || $input{src};
762 28 100       58 unless($src) {
763 1         4 $self->_set_error("no source image");
764 1         5 return;
765             }
766 27 100       59 unless ($src->_valid_image("paste")) {
767 1         4 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
768 1         4 return;
769             }
770 26 100       72 $input{left}=0 if $input{left} <= 0;
771 26 100       62 $input{top}=0 if $input{top} <= 0;
772              
773 26         2027 my($r,$b)=i_img_info($src->{IMG});
774 26         107 my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
775 26         45 my ($src_right, $src_bottom);
776 26 100       82 if ($input{src_coords}) {
777 1         3 ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
  1         4  
778             }
779             else {
780 25 100       127 if (defined $input{src_maxx}) {
    100          
781 2         5 $src_right = $input{src_maxx};
782             }
783             elsif (defined $input{width}) {
784 1 50       5 if ($input{width} <= 0) {
785 0         0 $self->_set_error("paste: width must me positive");
786 0         0 return;
787             }
788 1         3 $src_right = $src_left + $input{width};
789             }
790             else {
791 22         39 $src_right = $r;
792             }
793 25 100       70 if (defined $input{src_maxy}) {
    100          
794 3         8 $src_bottom = $input{src_maxy};
795             }
796             elsif (defined $input{height}) {
797 1 50       4 if ($input{height} < 0) {
798 0         0 $self->_set_error("paste: height must be positive");
799 0         0 return;
800             }
801 1         2 $src_bottom = $src_top + $input{height};
802             }
803             else {
804 21         33 $src_bottom = $b;
805             }
806             }
807              
808 26 50       103 $src_right > $r and $src_right = $r;
809 26 50       55 $src_bottom > $b and $src_bottom = $b;
810              
811 26 50 33     104 if ($src_right <= $src_left
812             || $src_bottom < $src_top) {
813 0         0 $self->_set_error("nothing to paste");
814 0         0 return;
815             }
816              
817             i_copyto($self->{IMG}, $src->{IMG},
818             $src_left, $src_top, $src_right, $src_bottom,
819 26         5082 $input{left}, $input{top});
820              
821 26         199 return $self; # What should go here??
822             }
823              
824             # Crop an image - i.e. return a new image that is smaller
825              
826             sub crop {
827 47     47 0 5450 my $self=shift;
828              
829 47 100       86 $self->_valid_image("crop")
830             or return;
831            
832 46 100       90 unless (defined wantarray) {
833 1         4 my @caller = caller;
834 1         12 warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
835 1         117 return;
836             }
837              
838 45         123 my %hsh=@_;
839              
840             my ($w, $h, $l, $r, $b, $t) =
841 45         131 @hsh{qw(width height left right bottom top)};
842              
843             # work through the various possibilities
844 45 100       97 if (defined $l) {
    100          
    100          
845 33 100       74 if (defined $w) {
    100          
846 1         2 $r = $l + $w;
847             }
848             elsif (!defined $r) {
849 1         3 $r = $self->getwidth;
850             }
851             }
852             elsif (defined $r) {
853 3 100       13 if (defined $w) {
854 2         5 $l = $r - $w;
855             }
856             else {
857 1         4 $l = 0;
858             }
859             }
860             elsif (defined $w) {
861 1         4 $l = int(0.5+($self->getwidth()-$w)/2);
862 1         2 $r = $l + $w;
863             }
864             else {
865 8         10 $l = 0;
866 8         15 $r = $self->getwidth;
867             }
868 45 100       93 if (defined $t) {
    100          
    100          
869 35 100       77 if (defined $h) {
    100          
870 4         6 $b = $t + $h;
871             }
872             elsif (!defined $b) {
873 1         2 $b = $self->getheight;
874             }
875             }
876             elsif (defined $b) {
877 3 100       5 if (defined $h) {
878 2         3 $t = $b - $h;
879             }
880             else {
881 1         2 $t = 0;
882             }
883             }
884             elsif (defined $h) {
885 1         2 $t=int(0.5+($self->getheight()-$h)/2);
886 1         2 $b=$t+$h;
887             }
888             else {
889 6         7 $t = 0;
890 6         11 $b = $self->getheight;
891             }
892              
893 45 50       81 ($l,$r)=($r,$l) if $l>$r;
894 45 50       65 ($t,$b)=($b,$t) if $t>$b;
895              
896 45 100       71 $l < 0 and $l = 0;
897 45 100       83 $r > $self->getwidth and $r = $self->getwidth;
898 45 100       71 $t < 0 and $t = 0;
899 45 100       72 $b > $self->getheight and $b = $self->getheight;
900              
901 45 100 100     126 if ($l == $r || $t == $b) {
902 2         11 $self->_set_error("resulting image would have no content");
903 2         7 return;
904             }
905 43 100 100     107 if( $r < $l or $b < $t ) {
906 2         6 $self->_set_error("attempting to crop outside of the image");
907 2         13 return;
908             }
909 41         90 my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
910              
911 41         7662 i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
912 41         183 return $dst;
913             }
914              
915             my $empty_trim_colors = Imager::TrimColorList->new();
916              
917             sub _trim_rect {
918 12     12   23 my ($self, $name, %hsh) = @_;
919              
920 12 50       21 $self->_valid_image($name)
921             or return;
922              
923 12         22 my $auto = delete $hsh{auto};
924 12   66     33 my $colors = delete $hsh{colors} || $empty_trim_colors;
925 12   50     31 my $alpha = delete $hsh{alpha} || 0;
926 12         19 my $tolerance = delete $hsh{tolerance};
927 12 50       20 defined $tolerance or $tolerance = 0.01;
928              
929 12 50       25 if (keys %hsh) {
930 0         0 $self->_set_error("$name: unexpected arguments:".join(", ", sort keys %hsh));
931 0         0 return;
932             }
933              
934 12 100       22 if ($auto) {
935 5 50       12 if ($colors != $empty_trim_colors) {
936 0         0 $self->_set_error("$name: only one of auto and colors can be supplied");
937 0         0 return;
938             }
939 5 50       12 if ($tolerance < 0) {
940 0         0 $self->_set_error("$name: tolerance must be non-negative");
941 0         0 return;
942             }
943              
944 5         16 $colors = Imager::TrimColorList->auto
945             (
946             auto => $auto,
947             tolerance => $tolerance,
948             name => $name,
949             image => $self,
950             );
951 5 50       15 unless ($colors) {
952 0         0 $self->_set_error(Imager->errstr);
953 0         0 return;
954             }
955             }
956              
957 12 50       23 unless (ref $colors) {
958 0         0 $self->_set_error("$name: colors must be an arrayref or an Imager::TrimColorList object");
959 0         0 return;
960             }
961 12 100       29 unless (UNIVERSAL::isa($colors, "Imager::TrimColorList")) {
962 5 50       13 unless (Scalar::Util::reftype($colors) eq "ARRAY") {
963 0         0 $self->_set_error("$name: colors must be an arrayref or an Imager::TrimColorList object");
964 0         0 return;
965             }
966 5         19 $colors = Imager::TrimColorList->new(@$colors);
967             }
968              
969 12         300 return i_trim_rect($self->{IMG}, $alpha, $colors);
970             }
971              
972             sub trim_rect {
973 8     8 0 49 my ($self, %hsh) = @_;
974              
975 8         24 return $self->_trim_rect("trim_rect", %hsh);
976             }
977              
978             sub trim {
979 4     4 0 2470 my ($self, %hsh) = @_;
980              
981 4 50       17 my ($left, $top, $right, $bottom) = $self->_trim_rect("trim", %hsh)
982             or return;
983              
984 4 50       12 if ($left == $self->getwidth) {
985             # the whole image would be trimmed, but we don't support zero
986             # width or height images.
987 0         0 return $self->crop(width => 1, height => 1);
988             }
989             else {
990 4         17 my ($w, $h) = i_img_info($self->{IMG});
991 4         16 return $self->crop(left => $left, right => $w - $right,
992             top => $top, bottom => $h - $bottom);
993             }
994             }
995              
996             sub _sametype {
997 41     41   95 my ($self, %opts) = @_;
998              
999 41 50       67 $self->_valid_image
1000             or return;
1001              
1002 41   33     85 my $x = $opts{xsize} || $self->getwidth;
1003 41   33     71 my $y = $opts{ysize} || $self->getheight;
1004 41   33     93 my $channels = $opts{channels} || $self->getchannels;
1005            
1006 41         91 my $out = Imager->new;
1007 41 50       71 if ($channels == $self->getchannels) {
1008 41         3659 $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
1009             }
1010             else {
1011 0         0 $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
1012             }
1013 41 50       127 unless ($out->{IMG}) {
1014 0         0 $self->{ERRSTR} = $self->_error_as_msg;
1015 0         0 return;
1016             }
1017            
1018 41         97 return $out;
1019             }
1020              
1021             # Sets an image to a certain size and channel number
1022             # if there was previously data in the image it is discarded
1023              
1024             my %model_channels =
1025             (
1026             gray => 1,
1027             graya => 2,
1028             rgb => 3,
1029             rgba => 4,
1030             );
1031              
1032             sub img_set {
1033 554     554 0 731 my $self=shift;
1034              
1035 554         1895 my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
1036              
1037 554         826 undef($self->{IMG});
1038              
1039 554 100       1135 if ($hsh{model}) {
1040 4 50       10 if (my $channels = $model_channels{$hsh{model}}) {
1041 4         5 $hsh{channels} = $channels;
1042             }
1043             else {
1044 0         0 $self->_set_error("new: unknown value for model '$hsh{model}'");
1045 0         0 return;
1046             }
1047             }
1048              
1049 554 100 100     2486 if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
    100          
    100          
1050             $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
1051 25   50     2105 $hsh{maxcolors} || 256);
1052             }
1053             elsif ($hsh{bits} eq 'double') {
1054 70         8514 $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
1055             }
1056             elsif ($hsh{bits} == 16) {
1057 22         2510 $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
1058             }
1059             else {
1060             $self->{IMG}= i_img_8_new($hsh{'xsize'}, $hsh{'ysize'},
1061 437         41947 $hsh{'channels'});
1062             }
1063              
1064 554 100       2022 unless ($self->{IMG}) {
1065 25         87 $self->_set_error(Imager->_error_as_msg());
1066 25         91 return;
1067             }
1068              
1069 529         1709 $self;
1070             }
1071              
1072             # created a masked version of the current image
1073             sub masked {
1074 10     10 0 513 my $self = shift;
1075              
1076 10 100       22 $self->_valid_image("masked")
1077             or return;
1078              
1079 9         43 my %opts = (left => 0,
1080             top => 0,
1081             right => $self->getwidth,
1082             bottom => $self->getheight,
1083             @_);
1084 9 100       23 my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
1085              
1086 9         22 my $result = Imager->new;
1087             $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
1088             $opts{top}, $opts{right} - $opts{left},
1089 9         676 $opts{bottom} - $opts{top});
1090 9 100       32 unless ($result->{IMG}) {
1091 1         5 $self->_set_error(Imager->_error_as_msg);
1092 1         3 return;
1093             }
1094              
1095             # keep references to the mask and base images so they don't
1096             # disappear on us
1097 8         20 $result->{DEPENDS} = [ $self->{IMG}, $mask ];
1098              
1099 8         31 return $result;
1100             }
1101              
1102             # convert an RGB image into a paletted image
1103             sub to_paletted {
1104 14     14 0 797 my $self = shift;
1105 14         21 my $opts;
1106 14 100 66     102 if (@_ != 1 && !ref $_[0]) {
1107 13         42 $opts = { @_ };
1108             }
1109             else {
1110 1         13 $opts = shift;
1111             }
1112              
1113 14 100       42 unless (defined wantarray) {
1114 1         4 my @caller = caller;
1115 1         11 warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
1116 1         49 return;
1117             }
1118              
1119 13 100       33 $self->_valid_image("to_paletted")
1120             or return;
1121              
1122 12         35 my $result = Imager->new;
1123 12 100       92861 unless ($result->{IMG} = i_img_to_pal($self->{IMG}, $opts)) {
1124 2         10 $self->_set_error(Imager->_error_as_msg);
1125 2         9 return;
1126             }
1127              
1128 10         73 return $result;
1129             }
1130              
1131             sub make_palette {
1132 7     7 0 913 my ($class, $quant, @images) = @_;
1133              
1134 7 100       16 unless (@images) {
1135 1         5 Imager->_set_error("make_palette: supply at least one image");
1136 1         3 return;
1137             }
1138 6         7 my $index = 1;
1139 6         13 for my $img (@images) {
1140 7 100       16 unless ($img->{IMG}) {
1141 1         6 Imager->_set_error("make_palette: image $index is empty");
1142 1         2 return;
1143             }
1144 6         8 ++$index;
1145             }
1146              
1147 5         6328 my @cols = i_img_make_palette($quant, map $_->{IMG}, @images);
1148 5 100       19 unless (@cols) {
1149 1         6 Imager->_set_error(Imager->_error_as_msg);
1150 1         4 return;
1151             }
1152 4         48 return @cols;
1153             }
1154              
1155             # convert a paletted (or any image) to an 8-bit/channel RGB image
1156             sub to_rgb8 {
1157 3     3 0 267 my $self = shift;
1158              
1159 3 100       11 unless (defined wantarray) {
1160 1         5 my @caller = caller;
1161 1         13 warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
1162 1         46 return;
1163             }
1164              
1165 2 100       6 $self->_valid_image("to_rgb8")
1166             or return;
1167              
1168 1         4 my $result = Imager->new;
1169 1 50       1049 unless ($result->{IMG} = i_img_to_rgb($self->{IMG})) {
1170 0         0 $self->_set_error(Imager->_error_as_msg());
1171 0         0 return;
1172             }
1173              
1174 1         5 return $result;
1175             }
1176              
1177             # convert a paletted (or any image) to a 16-bit/channel RGB image
1178             sub to_rgb16 {
1179 8     8 0 839 my $self = shift;
1180              
1181 8 50       24 unless (defined wantarray) {
1182 0         0 my @caller = caller;
1183 0         0 warn "to_rgb16() called in void context - to_rgb16() returns the converted image at $caller[1] line $caller[2]\n";
1184 0         0 return;
1185             }
1186              
1187 8 100       22 $self->_valid_image("to_rgb16")
1188             or return;
1189              
1190 7         26 my $result = Imager->new;
1191 7 50       5447 unless ($result->{IMG} = i_img_to_rgb16($self->{IMG})) {
1192 0         0 $self->_set_error(Imager->_error_as_msg());
1193 0         0 return;
1194             }
1195              
1196 7         42 return $result;
1197             }
1198              
1199             # convert a paletted (or any image) to an double/channel RGB image
1200             sub to_rgb_double {
1201 3     3 0 269 my $self = shift;
1202              
1203 3 50       11 unless (defined wantarray) {
1204 0         0 my @caller = caller;
1205 0         0 warn "to_rgb16() called in void context - to_rgb_double() returns the converted image at $caller[1] line $caller[2]\n";
1206 0         0 return;
1207             }
1208              
1209 3 100       11 $self->_valid_image("to_rgb_double")
1210             or return;
1211              
1212 2         10 my $result = Imager->new;
1213 2 50       1400 unless ($result->{IMG} = i_img_to_drgb($self->{IMG})) {
1214 0         0 $self->_set_error(Imager->_error_as_msg());
1215 0         0 return;
1216             }
1217              
1218 2         8 return $result;
1219             }
1220              
1221             sub addcolors {
1222 24     24 0 1039 my $self = shift;
1223 24         77 my %opts = (colors=>[], @_);
1224              
1225 24 100       91 $self->_valid_image("addcolors")
1226             or return -1;
1227              
1228 23 50       36 my @colors = @{$opts{colors}}
  23         69  
1229             or return undef;
1230              
1231 23         45 for my $color (@colors) {
1232 49         81 $color = _color($color);
1233 49 100       110 unless ($color) {
1234 1         3 $self->_set_error($Imager::ERRSTR);
1235 1         4 return;
1236             }
1237             }
1238              
1239 22         2108 return i_addcolors($self->{IMG}, @colors);
1240             }
1241              
1242             sub setcolors {
1243 12     12 0 553 my $self = shift;
1244 12         42 my %opts = (start=>0, colors=>[], @_);
1245              
1246 12 100       26 $self->_valid_image("setcolors")
1247             or return;
1248              
1249 11 100       45 my @colors = @{$opts{colors}}
  11         34  
1250             or return undef;
1251              
1252 10         19 for my $color (@colors) {
1253 14         26 $color = _color($color);
1254 14 100       30 unless ($color) {
1255 1         3 $self->_set_error($Imager::ERRSTR);
1256 1         7 return;
1257             }
1258             }
1259              
1260 9         686 return i_setcolors($self->{IMG}, $opts{start}, @colors);
1261             }
1262              
1263             sub getcolors {
1264 15     15 0 3065 my $self = shift;
1265 15         32 my %opts = @_;
1266              
1267 15 100       49 $self->_valid_image("getcolors")
1268             or return;
1269              
1270 14 100 66     68 if (!exists $opts{start} && !exists $opts{count}) {
    50          
    0          
1271             # get them all
1272 9         20 $opts{start} = 0;
1273 9         22 $opts{count} = $self->colorcount;
1274             }
1275             elsif (!exists $opts{count}) {
1276 5         11 $opts{count} = 1;
1277             }
1278             elsif (!exists $opts{start}) {
1279 0         0 $opts{start} = 0;
1280             }
1281              
1282 14         4386 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1283             }
1284              
1285             sub colorcount {
1286 15     15 0 1040 my ($self) = @_;
1287              
1288 15 100       31 $self->_valid_image("colorcount")
1289             or return -1;
1290              
1291 14         80 return i_colorcount($self->{IMG});
1292             }
1293              
1294             sub maxcolors {
1295 3     3 0 8 my $self = shift;
1296              
1297 3 100       10 $self->_valid_image("maxcolors")
1298             or return -1;
1299              
1300 2         14 i_maxcolors($self->{IMG});
1301             }
1302              
1303             sub findcolor {
1304 9     9 0 501 my $self = shift;
1305 9         22 my %opts = @_;
1306              
1307 9 100       20 $self->_valid_image("findcolor")
1308             or return;
1309              
1310 8 50       25 unless ($opts{color}) {
1311 0         0 $self->_set_error("findcolor: no color parameter");
1312 0         0 return;
1313             }
1314              
1315             my $color = _color($opts{color})
1316 8 50       18 or return;
1317              
1318 8         104 return i_findcolor($self->{IMG}, $color);
1319             }
1320              
1321             sub bits {
1322 53     53 0 1242 my $self = shift;
1323              
1324 53 100       125 $self->_valid_image("bits")
1325             or return;
1326              
1327 52         249 my $bits = i_img_bits($self->{IMG});
1328 52 100 66     212 if ($bits && $bits == length(pack("d", 1)) * 8) {
1329 12         21 $bits = 'double';
1330             }
1331 52         182 return $bits;
1332             }
1333              
1334             sub type {
1335 57     57 0 17118 my $self = shift;
1336              
1337 57 100       123 $self->_valid_image("type")
1338             or return;
1339              
1340 56 100       435 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1341             }
1342              
1343             sub virtual {
1344 2     2 0 4 my $self = shift;
1345              
1346 2 100       5 $self->_valid_image("virtual")
1347             or return;
1348              
1349 1         7 return i_img_virtual($self->{IMG});
1350             }
1351              
1352             sub is_bilevel {
1353 25     25 0 49 my ($self) = @_;
1354              
1355 25 100       46 $self->_valid_image("is_bilevel")
1356             or return;
1357              
1358 24         157 return i_img_is_monochrome($self->{IMG});
1359             }
1360              
1361             sub tags {
1362 86     86 0 1707 my ($self, %opts) = @_;
1363              
1364 86 100       150 $self->_valid_image("tags")
1365             or return;
1366              
1367 85 50       161 if (defined $opts{name}) {
    0          
1368 85         90 my @result;
1369 85         117 my $start = 0;
1370 85         83 my $found;
1371 85         369 while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
1372 85         261 push @result, (i_tags_get($self->{IMG}, $found))[1];
1373 85         231 $start = $found+1;
1374             }
1375 85 100       392 return wantarray ? @result : $result[0];
1376             }
1377             elsif (defined $opts{code}) {
1378 0         0 my @result;
1379 0         0 my $start = 0;
1380 0         0 my $found;
1381 0         0 while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
1382 0         0 push @result, (i_tags_get($self->{IMG}, $found))[1];
1383 0         0 $start = $found+1;
1384             }
1385 0         0 return @result;
1386             }
1387             else {
1388 0 0       0 if (wantarray) {
1389 0         0 return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
  0         0  
1390             }
1391             else {
1392 0         0 return i_tags_count($self->{IMG});
1393             }
1394             }
1395             }
1396              
1397             sub addtag {
1398 23     23 0 1403 my $self = shift;
1399 23         58 my %opts = @_;
1400              
1401 23 100       51 $self->_valid_image("addtag")
1402             or return;
1403              
1404 22 100       68 if ($opts{name}) {
    50          
1405 20 50       53 if (defined $opts{value}) {
    0          
1406 20 100       116 if ($opts{value} =~ /^\d+$/) {
1407             # add as a number
1408 17         1041 return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
1409             }
1410             else {
1411 3         387 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
1412             }
1413             }
1414             elsif (defined $opts{data}) {
1415             # force addition as a string
1416 0         0 return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
1417             }
1418             else {
1419 0         0 $self->{ERRSTR} = "No value supplied";
1420 0         0 return undef;
1421             }
1422             }
1423             elsif ($opts{code}) {
1424 2         129 warnings::warnif("Imager::tagcodes", "addtag: code parameter is deprecated");
1425 2 50       51 if (defined $opts{value}) {
    0          
1426 2 50       11 if ($opts{value} =~ /^\d+$/) {
1427             # add as a number
1428 2         87 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1429             }
1430             else {
1431 0         0 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1432             }
1433             }
1434             elsif (defined $opts{data}) {
1435             # force addition as a string
1436 0         0 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1437             }
1438             else {
1439 0         0 $self->{ERRSTR} = "No value supplied";
1440 0         0 return undef;
1441             }
1442             }
1443             else {
1444 0         0 return undef;
1445             }
1446             }
1447              
1448             sub deltag {
1449 21     21 0 36 my $self = shift;
1450 21         53 my %opts = @_;
1451              
1452 21 100       46 $self->_valid_image("deltag")
1453             or return 0;
1454              
1455 20 50       77 if (defined $opts{'index'}) {
    50          
    0          
1456 0         0 return i_tags_delete($self->{IMG}, $opts{'index'});
1457             }
1458             elsif (defined $opts{name}) {
1459 20         231 return i_tags_delbyname($self->{IMG}, $opts{name});
1460             }
1461             elsif (defined $opts{code}) {
1462 0         0 warnings::warnif("Imager::tagcodes", "deltag: code parameter is deprecated");
1463 0         0 return i_tags_delbycode($self->{IMG}, $opts{code});
1464             }
1465             else {
1466 0         0 $self->{ERRSTR} = "Need to supply index, name, or code parameter";
1467 0         0 return 0;
1468             }
1469             }
1470              
1471             sub settag {
1472 23     23 0 1072 my ($self, %opts) = @_;
1473              
1474 23 100       55 $self->_valid_image("settag")
1475             or return;
1476              
1477 22 100       58 if ($opts{name}) {
    50          
1478 20         75 $self->deltag(name=>$opts{name});
1479 20         73 return $self->addtag(name=>$opts{name}, value=>$opts{value});
1480             }
1481             elsif (defined $opts{code}) {
1482 2         201 warnings::warnif("Imager::tagcodes", "settag: code parameter is deprecated");
1483 2         70 i_tags_delbycode($self->{IMG}, $opts{code});
1484 2 50       6 if (defined $opts{value}) {
    0          
1485 2 50       9 if ($opts{value} =~ /^\d+$/) {
1486             # add as a number
1487 2         108 return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
1488             }
1489             else {
1490 0         0 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
1491             }
1492             }
1493             elsif (defined $opts{data}) {
1494             # force addition as a string
1495 0         0 return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
1496             }
1497             else {
1498 0         0 $self->{ERRSTR} = "No value supplied";
1499 0         0 return undef;
1500             }
1501             }
1502             else {
1503 0         0 return undef;
1504             }
1505             }
1506              
1507              
1508             sub _get_reader_io {
1509 226     226   368 my ($self, $input) = @_;
1510              
1511 226 50 33     749 if ($input->{io}) {
    100          
    100          
    100          
    100          
    50          
1512 0         0 return $input->{io}, undef;
1513             }
1514             elsif ($input->{fd}) {
1515 4         326 return io_new_fd($input->{fd});
1516             }
1517             elsif ($input->{fh}) {
1518 11 50       38 unless (Scalar::Util::openhandle($input->{fh})) {
1519 0         0 $self->_set_error("Handle in fh option not opened");
1520 0         0 return;
1521             }
1522 11         35 return Imager::IO->new_fh($input->{fh});
1523             }
1524             elsif ($input->{file}) {
1525 140         158 my $file;
1526 140 50       4788 unless (open $file, "<", $input->{file}) {
1527 0         0 $self->_set_error("Could not open $input->{file}: $!");
1528 0         0 return;
1529             }
1530 140         451 binmode $file;
1531 140         11561 return (io_new_fd(fileno($file)), $file);
1532             }
1533             elsif ($input->{data}) {
1534 63         5448 return io_new_buffer($input->{data});
1535             }
1536             elsif ($input->{callback} || $input->{readcb}) {
1537 8 50       14 if (!$input->{seekcb}) {
1538 0         0 $self->_set_error("Need a seekcb parameter");
1539             }
1540 8 50       12 if ($input->{maxbuffer}) {
1541             return io_new_cb($input->{writecb},
1542             $input->{callback} || $input->{readcb},
1543             $input->{seekcb}, $input->{closecb},
1544 0   0     0 $input->{maxbuffer});
1545             }
1546             else {
1547             return io_new_cb($input->{writecb},
1548             $input->{callback} || $input->{readcb},
1549 8   33     1018 $input->{seekcb}, $input->{closecb});
1550             }
1551             }
1552             else {
1553 0         0 $self->_set_error("file/fd/fh/data/callback parameter missing");
1554 0         0 return;
1555             }
1556             }
1557              
1558             sub _get_writer_io {
1559 168     168   304 my ($self, $input) = @_;
1560              
1561 168 100       368 my $buffered = exists $input->{buffered} ? $input->{buffered} : 1;
1562              
1563 168         270 my $io;
1564             my @extras;
1565 168 100 66     654 if ($input->{io}) {
    50          
    100          
    100          
    100          
    50          
1566 19         25 $io = $input->{io};
1567             }
1568             elsif ($input->{fd}) {
1569 0         0 $io = io_new_fd($input->{fd});
1570             }
1571             elsif ($input->{fh}) {
1572 6 50       22 unless (Scalar::Util::openhandle($input->{fh})) {
1573 0         0 $self->_set_error("Handle in fh option not opened");
1574 0         0 return;
1575             }
1576 6         28 $io = Imager::IO->new_fh($input->{fh});
1577             }
1578             elsif ($input->{file}) {
1579 113         158 my $fh;
1580 113 50       9740 unless (open $fh, "+>", $input->{file}) {
1581 0         0 $self->_set_error("Could not open file $input->{file}: $!");
1582 0         0 return;
1583             }
1584 113 50       599 binmode($fh) or die;
1585 113         9035 $io = io_new_fd(fileno($fh));
1586 113         476 push @extras, $fh;
1587             }
1588             elsif ($input->{data}) {
1589 20         2190 $io = io_new_bufchain();
1590             }
1591             elsif ($input->{callback} || $input->{writecb}) {
1592 10 100 66     33 if ($input->{maxbuffer} && $input->{maxbuffer} == 1) {
1593 4         8 $buffered = 0;
1594             }
1595             $io = io_new_cb($input->{callback} || $input->{writecb},
1596             $input->{readcb},
1597 10   66     1301 $input->{seekcb}, $input->{closecb});
1598             }
1599             else {
1600 0         0 $self->_set_error("file/fd/fh/data/callback parameter missing");
1601 0         0 return;
1602             }
1603              
1604 168 100       431 unless ($buffered) {
1605 5         20 $io->set_buffered(0);
1606             }
1607              
1608 168         597 return ($io, @extras);
1609             }
1610              
1611             sub _test_format {
1612 152     152   15284 my ($io) = @_;
1613              
1614 152         7221 return i_test_format_probe($io, -1);
1615             }
1616              
1617             sub add_file_magic {
1618 1     1 0 545 my ($class, %opts) = @_;
1619              
1620 1         4 my $name = delete $opts{name};
1621 1         3 my $bits = delete $opts{bits};
1622 1         3 my $mask = delete $opts{mask};
1623              
1624 1 50       8 unless (i_add_file_magic($name, $bits, $mask)) {
1625 0         0 Imager->_set_error(Imager->_error_as_msg);
1626 0         0 return;
1627             }
1628              
1629 1         5 1;
1630             }
1631              
1632             # Read an image from file
1633              
1634             sub read {
1635 221     221 0 15616 my $self = shift;
1636 221         614 my %input=@_;
1637              
1638 221 100       471 if (defined($self->{IMG})) {
1639             # let IIM_DESTROY do the destruction, since the image may be
1640             # referenced from elsewhere
1641             #i_img_destroy($self->{IMG});
1642 22         5988 undef($self->{IMG});
1643             }
1644              
1645 221 50       599 my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
1646              
1647 221         619 my $type = $input{'type'};
1648 221 100       387 unless ($type) {
1649 116         242 $type = _test_format($IO);
1650             }
1651              
1652 221 100 100     1660 if ($input{file} && !$type) {
1653             # guess the type
1654 1         7 $type = $FORMATGUESS->($input{file});
1655             }
1656              
1657 221 100       410 unless ($type) {
1658 2         3 my $msg = "type parameter missing and it couldn't be determined from the file contents";
1659 2 100       7 $input{file} and $msg .= " or file name";
1660 2         5 $self->_set_error($msg);
1661 2         211 return undef;
1662             }
1663              
1664 219         500 _reader_autoload($type);
1665              
1666 219 0 33     422 if ($readers{$type} && $readers{$type}{single}) {
1667 0         0 return $readers{$type}{single}->($self, $IO, %input);
1668             }
1669              
1670 219 100       409 unless ($formats_low{$type}) {
1671 6         43 my $read_types = join ', ', sort Imager->read_types();
1672 6         52 $self->_set_error("format '$type' not supported - formats $read_types available for reading - $reader_load_errors{$type}");
1673 6         466 return;
1674             }
1675              
1676 213         264 my $allow_incomplete = $input{allow_incomplete};
1677 213 100       376 defined $allow_incomplete or $allow_incomplete = 0;
1678              
1679 213 100       411 if ( $type eq 'pnm' ) {
1680 75         41892 $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
1681 75 100       2671 if ( !defined($self->{IMG}) ) {
1682 20         42 $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
1683 20         1749 return undef;
1684             }
1685 55 50       112 $self->{DEBUG} && print "loading a pnm file\n";
1686 55         5014 return $self;
1687             }
1688              
1689 138 100       220 if ( $type eq 'bmp' ) {
1690 98         48175 $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
1691 98 100       1367 if ( !defined($self->{IMG}) ) {
1692 46         110 $self->{ERRSTR}=$self->_error_as_msg();
1693 46         4707 return undef;
1694             }
1695 52 50       95 $self->{DEBUG} && print "loading a bmp file\n";
1696             }
1697              
1698 92 100       164 if ( $type eq 'tga' ) {
1699 22         33277 $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
1700 22 100       2914 if ( !defined($self->{IMG}) ) {
1701 4         14 $self->{ERRSTR}=$self->_error_as_msg();
1702 4         393 return undef;
1703             }
1704 18 50       43 $self->{DEBUG} && print "loading a tga file\n";
1705             }
1706              
1707 88 100       148 if ( $type eq 'raw' ) {
1708 18 50 33     58 unless ( $input{xsize} && $input{ysize} ) {
1709 0         0 $self->_set_error('missing xsize or ysize parameter for raw');
1710 0         0 return undef;
1711             }
1712              
1713 18         58 my $interleave = _first($input{raw_interleave}, $input{interleave});
1714 18 100       42 unless (defined $interleave) {
1715 1         4 my @caller = caller;
1716 1         15 warn "read(type => 'raw') $caller[2] line $caller[1]: supply interleave or raw_interleave for future compatibility\n";
1717 1         8 $interleave = 1;
1718             }
1719 18         51 my $data_ch = _first($input{raw_datachannels}, $input{datachannels}, 3);
1720 18         49 my $store_ch = _first($input{raw_storechannels}, $input{storechannels}, 3);
1721              
1722             $self->{IMG} = i_readraw_wiol( $IO,
1723             $input{xsize},
1724             $input{ysize},
1725 18         5356 $data_ch,
1726             $store_ch,
1727             $interleave);
1728 18 100       400 if ( !defined($self->{IMG}) ) {
1729 4         12 $self->{ERRSTR}=$self->_error_as_msg();
1730 4         314 return undef;
1731             }
1732 14 50       36 $self->{DEBUG} && print "loading a raw file\n";
1733             }
1734              
1735 84         8357 return $self;
1736             }
1737              
1738             sub register_reader {
1739 3     3 0 13 my ($class, %opts) = @_;
1740              
1741             defined $opts{type}
1742 3 50       8 or die "register_reader called with no type parameter\n";
1743              
1744 3         5 my $type = $opts{type};
1745              
1746             defined $opts{single} || defined $opts{multiple}
1747 3 50 33     8 or die "register_reader called with no single or multiple parameter\n";
1748              
1749 3         6 $readers{$type} = { };
1750 3 50       8 if ($opts{single}) {
1751 3         7 $readers{$type}{single} = $opts{single};
1752             }
1753 3 100       6 if ($opts{multiple}) {
1754 2         4 $readers{$type}{multiple} = $opts{multiple};
1755             }
1756              
1757 3         6 return 1;
1758             }
1759              
1760             sub register_writer {
1761 3     3 0 8 my ($class, %opts) = @_;
1762              
1763             defined $opts{type}
1764 3 50       6 or die "register_writer called with no type parameter\n";
1765              
1766 3         4 my $type = $opts{type};
1767              
1768             defined $opts{single} || defined $opts{multiple}
1769 3 50 33     8 or die "register_writer called with no single or multiple parameter\n";
1770              
1771 3         4 $writers{$type} = { };
1772 3 50       5 if ($opts{single}) {
1773 3         6 $writers{$type}{single} = $opts{single};
1774             }
1775 3 100       7 if ($opts{multiple}) {
1776 2         3 $writers{$type}{multiple} = $opts{multiple};
1777             }
1778              
1779 3         10 return 1;
1780             }
1781              
1782             sub read_types {
1783             my %types =
1784             (
1785 96         192 map { $_ => 1 }
1786             keys %readers,
1787 16     16 0 159 grep($file_formats{$_}, keys %formats),
1788             qw(ico sgi), # formats not handled directly, but supplied with Imager
1789             );
1790              
1791 16         136 return keys %types;
1792             }
1793              
1794             sub write_types {
1795             my %types =
1796             (
1797 96         169 map { $_ => 1 }
1798             keys %writers,
1799 16     16 0 70 grep($file_formats{$_}, keys %formats),
1800             qw(ico sgi), # formats not handled directly, but supplied with Imager
1801             );
1802              
1803 16         121 return keys %types;
1804             }
1805              
1806             sub _load_file {
1807 105     105   156 my ($file, $error) = @_;
1808              
1809 105 100       207 if ($attempted_to_load{$file}) {
1810 22 50       40 if ($file_load_errors{$file}) {
1811 22         33 $$error = $file_load_errors{$file};
1812 22         46 return 0;
1813             }
1814             else {
1815 0         0 return 1;
1816             }
1817             }
1818             else {
1819 83         195 local $SIG{__DIE__};
1820 83         122 my $loaded = eval {
1821 83         320 local @INC = @INC;
1822 83 100       188 pop @INC if $INC[-1] eq '.';
1823 83         182 ++$attempted_to_load{$file};
1824 83         9584 require $file;
1825 0         0 return 1;
1826             };
1827 83 50       445 if ($loaded) {
1828 0         0 return 1;
1829             }
1830             else {
1831 83   50     182 my $work = $@ || "Unknown error";
1832 83         129 chomp $work;
1833 83         188 $work =~ s/\n?Compilation failed in require at .*Imager\.pm line .*\z//m;
1834 83         116 $work =~ s/\n/\\n/g;
1835 83         5963 $work =~ s/\s*\.?\z/ loading $file/;
1836 83         238 $file_load_errors{$file} = $work;
1837 83         163 $$error = $work;
1838 83         305 return 0;
1839             }
1840             }
1841             }
1842              
1843             # probes for an Imager::File::whatever module
1844             sub _reader_autoload {
1845 222     222   333 my $type = shift;
1846              
1847 222 100 66     594 return if $formats_low{$type} || $readers{$type};
1848              
1849 8 50       63 return unless $type =~ /^\w+$/;
1850              
1851 8         34 my $file = "Imager/File/\U$type\E.pm";
1852              
1853 8         12 my $error;
1854 8         36 my $loaded = _load_file($file, \$error);
1855 8 100 66     64 if (!$loaded && $error =~ /^Can't locate /) {
1856 7         34 my $filer = "Imager/File/\U$type\EReader.pm";
1857 7         17 $loaded = _load_file($filer, \$error);
1858 7 50       36 if ($error =~ /^Can't locate /) {
1859 7         23 $error = "Can't locate $file or $filer";
1860             }
1861             }
1862 8 50       22 unless ($loaded) {
1863 8         19 $reader_load_errors{$type} = $error;
1864             }
1865             }
1866              
1867             # probes for an Imager::File::whatever module
1868             sub _writer_autoload {
1869 176     176   253 my $type = shift;
1870              
1871 176 100 66     564 return if $formats_low{$type} || $writers{$type};
1872              
1873 8 50       49 return unless $type =~ /^\w+$/;
1874              
1875 8         28 my $file = "Imager/File/\U$type\E.pm";
1876              
1877 8         12 my $error;
1878 8         80 my $loaded = _load_file($file, \$error);
1879 8 100 66     71 if (!$loaded && $error =~ /^Can't locate /) {
1880 7         56 my $filew = "Imager/File/\U$type\EWriter.pm";
1881 7         19 $loaded = _load_file($filew, \$error);
1882 7 50       38 if ($error =~ /^Can't locate /) {
1883 7         24 $error = "Can't locate $file or $filew";
1884             }
1885             }
1886 8 50       19 unless ($loaded) {
1887 8         20 $writer_load_errors{$type} = $error;
1888             }
1889             }
1890              
1891             sub _fix_gif_positions {
1892 0     0   0 my ($opts, $opt, $msg, @imgs) = @_;
1893              
1894 0         0 my $positions = $opts->{'gif_positions'};
1895 0         0 my $index = 0;
1896 0         0 for my $pos (@$positions) {
1897 0         0 my ($x, $y) = @$pos;
1898 0         0 my $img = $imgs[$index++];
1899 0         0 $img->settag(name=>'gif_left', value=>$x);
1900 0 0       0 $img->settag(name=>'gif_top', value=>$y) if defined $y;
1901             }
1902 0         0 $$msg .= "replaced with the gif_left and gif_top tags";
1903             }
1904              
1905             my %obsolete_opts =
1906             (
1907             gif_each_palette=>'gif_local_map',
1908             interlace => 'gif_interlace',
1909             gif_delays => 'gif_delay',
1910             gif_positions => \&_fix_gif_positions,
1911             gif_loop_count => 'gif_loop',
1912             );
1913              
1914             # options that should be converted to colors
1915             my %color_opts = map { $_ => 1 } qw/i_background/;
1916              
1917             sub _set_opts {
1918 344     344   742 my ($self, $opts, $prefix, @imgs) = @_;
1919              
1920 344         1051 for my $opt (keys %$opts) {
1921 3320         3799 my $tagname = $opt;
1922 3320 50       4565 if ($obsolete_opts{$opt}) {
1923 0         0 my $new = $obsolete_opts{$opt};
1924 0         0 my $msg = "Obsolete option $opt ";
1925 0 0       0 if (ref $new) {
1926 0         0 $new->($opts, $opt, \$msg, @imgs);
1927             }
1928             else {
1929 0         0 $msg .= "replaced with the $new tag ";
1930 0         0 $tagname = $new;
1931             }
1932 0         0 $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
1933 0 0 0     0 warn $msg if $warn_obsolete && $^W;
1934             }
1935 3320 100       10911 next unless $tagname =~ /^\Q$prefix/;
1936 19         43 my $value = $opts->{$opt};
1937 19 100       52 if ($color_opts{$opt}) {
1938 3         9 $value = _color($value);
1939 3 50       11 unless ($value) {
1940 0         0 $self->_set_error($Imager::ERRSTR);
1941 0         0 return;
1942             }
1943             }
1944 19 100       47 if (ref $value) {
1945 3 50       13 if (UNIVERSAL::isa($value, "Imager::Color")) {
    0          
1946 3         21 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1947 3         8 for my $img (@imgs) {
1948 3         11 $img->settag(name=>$tagname, value=>$tag);
1949             }
1950             }
1951             elsif (ref($value) eq 'ARRAY') {
1952 0         0 for my $i (0..$#$value) {
1953 0         0 my $val = $value->[$i];
1954 0 0       0 if (ref $val) {
1955 0 0       0 if (UNIVERSAL::isa($val, "Imager::Color")) {
1956 0         0 my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
1957 0 0       0 $i < @imgs and
1958             $imgs[$i]->settag(name=>$tagname, value=>$tag);
1959             }
1960             else {
1961 0         0 $self->_set_error("Unknown reference type " . ref($value) .
1962             " supplied in array for $opt");
1963 0         0 return;
1964             }
1965             }
1966             else {
1967 0 0       0 $i < @imgs
1968             and $imgs[$i]->settag(name=>$tagname, value=>$val);
1969             }
1970             }
1971             }
1972             else {
1973 0         0 $self->_set_error("Unknown reference type " . ref($value) .
1974             " supplied for $opt");
1975 0         0 return;
1976             }
1977             }
1978             else {
1979             # set it as a tag for every image
1980 16         41 for my $img (@imgs) {
1981 16         61 $img->settag(name=>$tagname, value=>$value);
1982             }
1983             }
1984             }
1985              
1986 344         953 return 1;
1987             }
1988              
1989             # Write an image to file
1990             sub write {
1991 175     175 0 22120 my $self = shift;
1992 175         1393 my %input=(jpegquality=>75,
1993             gifquant=>'mc',
1994             lmdither=>6.0,
1995             lmfixed=>[],
1996             idstring=>"",
1997             compress=>1,
1998             wierdpack=>0,
1999             fax_fine=>1, @_);
2000 175         289 my $rc;
2001              
2002 175 100       419 $self->_valid_image("write")
2003             or return;
2004              
2005 174 50       614 $self->_set_opts(\%input, "i_", $self)
2006             or return undef;
2007              
2008 174         318 my $type = $input{'type'};
2009 174 50 66     575 if (!$type and $input{file}) {
2010 99         287 $type = $FORMATGUESS->($input{file});
2011             }
2012 174 50       362 unless ($type) {
2013 0         0 $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
2014 0         0 return undef;
2015             }
2016              
2017 174         494 _writer_autoload($type);
2018              
2019 174         266 my ($IO, $fh);
2020 174 50 33     595 if ($writers{$type} && $writers{$type}{single}) {
2021 0 0       0 ($IO, $fh) = $self->_get_writer_io(\%input)
2022             or return undef;
2023              
2024 0 0       0 $writers{$type}{single}->($self, $IO, %input, type => $type)
2025             or return undef;
2026             }
2027             else {
2028 174 100       390 if (!$formats_low{$type}) {
2029 6         22 my $write_types = join ', ', sort Imager->write_types();
2030 6         36 $self->_set_error("format '$type' not supported - formats $write_types available for writing - $writer_load_errors{$type}");
2031 6         38 return undef;
2032             }
2033            
2034 168 50       469 ($IO, $fh) = $self->_get_writer_io(\%input, $type)
2035             or return undef;
2036            
2037 168 100       1300 if ( $type eq 'pnm' ) {
    100          
    100          
    50          
2038 121 50       344 $self->_set_opts(\%input, "pnm_", $self)
2039             or return undef;
2040 121 100       31481 if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
2041 5         735 $self->{ERRSTR} = $self->_error_as_msg();
2042 5         41 return undef;
2043             }
2044 116 50       678 $self->{DEBUG} && print "writing a pnm file\n";
2045             }
2046             elsif ( $type eq 'raw' ) {
2047 10 50       24 $self->_set_opts(\%input, "raw_", $self)
2048             or return undef;
2049 10 100       1694 if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
2050 4         412 $self->{ERRSTR} = $self->_error_as_msg();
2051 4         106 return undef;
2052             }
2053 6 50       207 $self->{DEBUG} && print "writing a raw file\n";
2054             }
2055             elsif ( $type eq 'bmp' ) {
2056 21 50       49 $self->_set_opts(\%input, "bmp_", $self)
2057             or return undef;
2058 21 100       4534 if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
2059 12         6341 $self->{ERRSTR} = $self->_error_as_msg;
2060 12         192 return undef;
2061             }
2062 9 50       2159 $self->{DEBUG} && print "writing a bmp file\n";
2063             }
2064             elsif ( $type eq 'tga' ) {
2065 16 50       47 $self->_set_opts(\%input, "tga_", $self)
2066             or return undef;
2067            
2068 16 100       26631 if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
2069 4         229 $self->{ERRSTR}=$self->_error_as_msg();
2070 4         506 return undef;
2071             }
2072 12 50       14228 $self->{DEBUG} && print "writing a tga file\n";
2073             }
2074             }
2075              
2076 143 100       729 if (exists $input{'data'}) {
2077 17         3415 my $data = io_slurp($IO);
2078 17 50       74 if (!$data) {
2079 0         0 $self->{ERRSTR}='Could not slurp from buffer';
2080 0         0 return undef;
2081             }
2082 17         29 ${$input{data}} = $data;
  17         50  
2083             }
2084 143         14828 return $self;
2085             }
2086              
2087             sub write_multi {
2088 5     5 0 37 my ($class, $opts, @images) = @_;
2089              
2090 5         9 my $type = $opts->{type};
2091              
2092 5 50 66     20 if (!$type && $opts->{'file'}) {
2093 2         7 $type = $FORMATGUESS->($opts->{'file'});
2094             }
2095 5 50       11 unless ($type) {
2096 0         0 $class->_set_error('type parameter missing and not possible to guess from extension');
2097 0         0 return;
2098             }
2099             # translate to ImgRaw
2100 5         7 my $index = 1;
2101 5         15 for my $img (@images) {
2102 8 100 66     92 unless (ref $img && Scalar::Util::blessed($img) && $img->isa("Imager")) {
      100        
2103 2         9 $class->_set_error("write_multi: image $index is not an Imager image object");
2104 2         8 return;
2105             }
2106 6 100       20 unless ($img->_valid_image("write_multi")) {
2107 1         6 $class->_set_error($img->errstr . " (image $index)");
2108 1         6 return;
2109             }
2110 5         17 ++$index;
2111             }
2112 2 50       7 $class->_set_opts($opts, "i_", @images)
2113             or return;
2114 2         10 my @work = map $_->{IMG}, @images;
2115              
2116 2         6 _writer_autoload($type);
2117              
2118 2         71 my ($IO, $file);
2119 2 50 33     14 if ($writers{$type} && $writers{$type}{multiple}) {
2120 0 0       0 ($IO, $file) = $class->_get_writer_io($opts, $type)
2121             or return undef;
2122              
2123 0 0       0 $writers{$type}{multiple}->($class, $IO, $opts, @images)
2124             or return undef;
2125             }
2126             else {
2127 2 50       8 if (!$formats{$type}) {
2128 2         6 my $write_types = join ', ', sort Imager->write_types();
2129 2         13 $class->_set_error("format '$type' not supported - formats $write_types available for writing");
2130 2         74 return undef;
2131             }
2132            
2133 0 0       0 ($IO, $file) = $class->_get_writer_io($opts, $type)
2134             or return undef;
2135            
2136 0         0 if (0) { # eventually PNM in here, now that TIFF/GIF are elsewhere
2137             }
2138             else {
2139 0 0       0 if (@images == 1) {
2140 0 0       0 unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
2141 0         0 return 1;
2142             }
2143             }
2144             else {
2145 0         0 $ERRSTR = "Sorry, write_multi doesn't support $type yet";
2146 0         0 return 0;
2147             }
2148             }
2149             }
2150              
2151 0 0       0 if (exists $opts->{'data'}) {
2152 0         0 my $data = io_slurp($IO);
2153 0 0       0 if (!$data) {
2154 0         0 Imager->_set_error('Could not slurp from buffer');
2155 0         0 return undef;
2156             }
2157 0         0 ${$opts->{data}} = $data;
  0         0  
2158             }
2159 0         0 return 1;
2160             }
2161              
2162             # read multiple images from a file
2163             sub read_multi {
2164 5     5 0 39 my ($class, %opts) = @_;
2165              
2166 5 50       24 my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
2167             or return;
2168              
2169 5         20 my $type = $opts{'type'};
2170 5 50       15 unless ($type) {
2171 5         14 $type = _test_format($IO);
2172             }
2173              
2174 5 100 100     48 if ($opts{file} && !$type) {
2175             # guess the type
2176 1         12 $type = $FORMATGUESS->($opts{file});
2177             }
2178              
2179 5 100       13 unless ($type) {
2180 2         8 my $msg = "type parameter missing and it couldn't be determined from the file contents";
2181 2 100       8 $opts{file} and $msg .= " or file name";
2182 2         9 Imager->_set_error($msg);
2183 2         209 return;
2184             }
2185              
2186 3         10 _reader_autoload($type);
2187              
2188 3 0 33     9 if ($readers{$type} && $readers{$type}{multiple}) {
2189 0         0 return $readers{$type}{multiple}->($IO, %opts);
2190             }
2191              
2192 3 100       15 unless ($formats{$type}) {
2193 2         8 my $read_types = join ', ', sort Imager->read_types();
2194 2         12 Imager->_set_error("format '$type' not supported - formats $read_types available for reading");
2195 2         38 return;
2196             }
2197              
2198 1         4 my @imgs;
2199 1 50       4 if ($type eq 'pnm') {
2200 1   50     2151 @imgs = i_readpnm_multi_wiol($IO, $opts{allow_incomplete}||0);
2201             }
2202             else {
2203 0         0 my $img = Imager->new;
2204 0 0       0 if ($img->read(%opts, io => $IO, type => $type)) {
2205 0         0 return ( $img );
2206             }
2207 0         0 Imager->_set_error($img->errstr);
2208 0         0 return;
2209             }
2210              
2211 1 50       8 if (!@imgs) {
2212 0         0 $ERRSTR = _error_as_msg();
2213 0         0 return;
2214             }
2215             return map {
2216 1         5 bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
  3         96  
2217             } @imgs;
2218             }
2219              
2220             # Destroy an Imager object
2221              
2222             sub DESTROY {
2223 1275     1275   241444 my $self=shift;
2224             # delete $instances{$self};
2225 1275 100       4094 if (defined($self->{IMG})) {
2226             # the following is now handled by the XS DESTROY method for
2227             # Imager::ImgRaw object
2228             # Re-enabling this will break virtual images
2229             # tested for in t/t020masked.t
2230             # i_img_destroy($self->{IMG});
2231 1117         138547 undef($self->{IMG});
2232             } else {
2233             # print "Destroy Called on an empty image!\n"; # why did I put this here??
2234             }
2235             }
2236              
2237             # Perform an inplace filter of an image
2238             # that is the image will be overwritten with the data
2239              
2240             sub filter {
2241 86     86 0 1027 my $self=shift;
2242 86         297 my %input=@_;
2243 86         134 my %hsh;
2244              
2245 86 100       187 $self->_valid_image("filter")
2246             or return;
2247              
2248 85 50       203 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
  0         0  
  0         0  
2249              
2250 85 50       462 if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
  1701         2261  
2251 0         0 $self->{ERRSTR}='type parameter not matching any filter'; return undef;
  0         0  
2252             }
2253              
2254 85 100       323 if ($filters{$input{'type'}}{names}) {
2255 10         15 my $names = $filters{$input{'type'}}{names};
2256 10         23 for my $name (keys %$names) {
2257 40 100 66     104 if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
2258 12         21 $input{$name} = $names->{$name}{$input{$name}};
2259             }
2260             }
2261             }
2262 85 100       224 if (defined($filters{$input{'type'}}{defaults})) {
2263             %hsh=( image => $self->{IMG},
2264             imager => $self,
2265 84         137 %{$filters{$input{'type'}}{defaults}},
  84         386  
2266             %input );
2267             } else {
2268             %hsh=( image => $self->{IMG},
2269 1         4 imager => $self,
2270             %input );
2271             }
2272              
2273 85         137 my @cs=@{$filters{$input{'type'}}{callseq}};
  85         259  
2274              
2275 85         162 for(@cs) {
2276 290 50       510 if (!defined($hsh{$_})) {
2277 0         0 $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
  0         0  
2278             }
2279             }
2280              
2281 85         122 eval {
2282 85         283 local $SIG{__DIE__}; # we don't want this processed by confess, etc
2283 85         178 &{$filters{$input{'type'}}{callsub}}(%hsh);
  85         242  
2284             };
2285 85 100       840 if ($@) {
2286 4         12 chomp($self->{ERRSTR} = $@);
2287 4         26 return;
2288             }
2289              
2290 81         304 my @b=keys %hsh;
2291              
2292 81 50       218 $self->{DEBUG} && print "callseq is: @cs\n";
2293 81 50       162 $self->{DEBUG} && print "matching callseq is: @b\n";
2294              
2295 81         501 return $self;
2296             }
2297              
2298             sub register_filter {
2299 1     1 0 13 my $class = shift;
2300 1         6 my %hsh = ( defaults => {}, @_ );
2301              
2302             defined $hsh{type}
2303 1 50       5 or die "register_filter() with no type\n";
2304             defined $hsh{callsub}
2305 1 50       3 or die "register_filter() with no callsub\n";
2306             defined $hsh{callseq}
2307 1 50       3 or die "register_filter() with no callseq\n";
2308              
2309             exists $filters{$hsh{type}}
2310 1 50       3 and return;
2311              
2312 1         3 $filters{$hsh{type}} = \%hsh;
2313              
2314 1         2 return 1;
2315             }
2316              
2317             sub scale_calculate {
2318 61     61 0 90 my $self = shift;
2319              
2320 61         232 my %opts = ('type'=>'max', @_);
2321              
2322             # none of these should be references
2323 61         134 for my $name (qw/xpixels ypixels xscalefactor yscalefactor width height/) {
2324 361 100 100     716 if (defined $opts{$name} && ref $opts{$name}) {
2325 1         6 $self->_set_error("scale_calculate: $name parameter cannot be a reference");
2326 1         5 return;
2327             }
2328             }
2329              
2330 60         83 my ($x_scale, $y_scale);
2331 60         85 my $width = $opts{width};
2332 60         86 my $height = $opts{height};
2333 60 100       116 if (ref $self) {
2334 58 50       162 defined $width or $width = $self->getwidth;
2335 58 50       147 defined $height or $height = $self->getheight;
2336             }
2337             else {
2338 2 100 66     16 unless (defined $width && defined $height) {
2339 1         7 $self->_set_error("scale_calculate: width and height parameters must be supplied when called as a class method");
2340 1         6 return;
2341             }
2342             }
2343              
2344 59 100 100     204 if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
    100          
    100          
2345 8         11 $x_scale = $opts{'xscalefactor'};
2346 8         12 $y_scale = $opts{'yscalefactor'};
2347             }
2348             elsif ($opts{'xscalefactor'}) {
2349 3         6 $x_scale = $opts{'xscalefactor'};
2350 3   33     9 $y_scale = $opts{'scalefactor'} || $x_scale;
2351             }
2352             elsif ($opts{'yscalefactor'}) {
2353 3         6 $y_scale = $opts{'yscalefactor'};
2354 3   33     11 $x_scale = $opts{'scalefactor'} || $y_scale;
2355             }
2356             else {
2357 45   100     139 $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
2358             }
2359              
2360             # work out the scaling
2361 59 100 100     281 if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
    100 66        
    100 33        
    50 33        
2362             my ($xpix, $ypix)=( $opts{xpixels} / $width ,
2363 19         62 $opts{ypixels} / $height );
2364 19 100 66     58 if ($opts{'type'} eq 'min') {
    100          
    100          
2365 3         6 $x_scale = $y_scale = _min($xpix,$ypix);
2366             }
2367             elsif ($opts{'type'} eq 'max') {
2368 9         26 $x_scale = $y_scale = _max($xpix,$ypix);
2369             }
2370             elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
2371 6         8 $x_scale = $xpix;
2372 6         8 $y_scale = $ypix;
2373             }
2374             else {
2375 1         3 $self->_set_error('invalid value for type parameter');
2376 1         5 return;
2377             }
2378             } elsif ($opts{xpixels}) {
2379 6         20 $x_scale = $y_scale = $opts{xpixels} / $width;
2380             }
2381             elsif ($opts{ypixels}) {
2382 3         8 $x_scale = $y_scale = $opts{ypixels}/$height;
2383             }
2384             elsif ($opts{constrain} && ref $opts{constrain}
2385             && $opts{constrain}->can('constrain')) {
2386             # we've been passed an Image::Math::Constrain object or something
2387             # that looks like one
2388 0         0 my $scalefactor;
2389             (undef, undef, $scalefactor)
2390 0         0 = $opts{constrain}->constrain($self->getwidth, $self->getheight);
2391 0 0       0 unless ($scalefactor) {
2392 0         0 $self->_set_error('constrain method failed on constrain parameter');
2393 0         0 return;
2394             }
2395 0         0 $x_scale = $y_scale = $scalefactor;
2396             }
2397              
2398 58         163 my $new_width = int($x_scale * $width + 0.5);
2399 58 100       126 $new_width > 0 or $new_width = 1;
2400 58         99 my $new_height = int($y_scale * $height + 0.5);
2401 58 100       106 $new_height > 0 or $new_height = 1;
2402              
2403 58         275 return ($x_scale, $y_scale, $new_width, $new_height);
2404            
2405             }
2406              
2407             # Scale an image to requested size and return the scaled version
2408              
2409             sub scale {
2410 60     60 0 3005 my $self=shift;
2411 60         281 my %opts = (qtype=>'normal' ,@_);
2412 60         186 my $img = Imager->new();
2413 60         123 my $tmp = Imager->new();
2414              
2415 60 100       126 unless (defined wantarray) {
2416 1         4 my @caller = caller;
2417 1         14 warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
2418 1         155 return;
2419             }
2420              
2421 59 100       124 $self->_valid_image("scale")
2422             or return;
2423              
2424 58 100       193 my ($x_scale, $y_scale, $new_width, $new_height) =
2425             $self->scale_calculate(%opts)
2426             or return;
2427              
2428 56 100       197 if ($opts{qtype} eq 'normal') {
    100          
    100          
2429 17         46113 $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
2430 17 50       92 if ( !defined($tmp->{IMG}) ) {
2431 0         0 $self->{ERRSTR} = 'unable to scale image: ' . $self->_error_as_msg;
2432 0         0 return undef;
2433             }
2434 17         27612 $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
2435 17 50       86 if ( !defined($img->{IMG}) ) {
2436 0         0 $self->{ERRSTR}='unable to scale image: ' . $self->_error_as_msg;
2437 0         0 return undef;
2438             }
2439              
2440 17         118 return $img;
2441             }
2442             elsif ($opts{'qtype'} eq 'preview') {
2443 18         9463 $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
2444 18 50       82 if ( !defined($img->{IMG}) ) {
2445 0         0 $self->{ERRSTR}='unable to scale image';
2446 0         0 return undef;
2447             }
2448 18         69 return $img;
2449             }
2450             elsif ($opts{'qtype'} eq 'mixing') {
2451 20         19581 $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
2452 20 50       82 unless ($img->{IMG}) {
2453 0         0 $self->_set_error(Imager->_error_as_msg);
2454 0         0 return;
2455             }
2456 20         81 return $img;
2457             }
2458             else {
2459 1         4 $self->_set_error('invalid value for qtype parameter');
2460 1         2 return undef;
2461             }
2462             }
2463              
2464             # Scales only along the X axis
2465              
2466             sub scaleX {
2467 11     11 0 1403 my $self = shift;
2468 11         53 my %opts = ( scalefactor=>0.5, @_ );
2469              
2470 11 100       61 unless (defined wantarray) {
2471 1         4 my @caller = caller;
2472 1         9 warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
2473 1         112 return;
2474             }
2475              
2476 10 100       32 $self->_valid_image("scaleX")
2477             or return;
2478              
2479 9         34 my $img = Imager->new();
2480              
2481 9         19 my $scalefactor = $opts{scalefactor};
2482              
2483 9 100       26 if ($opts{pixels}) {
2484 3         9 $scalefactor = $opts{pixels} / $self->getwidth();
2485             }
2486              
2487 9 50       27 unless ($self->{IMG}) {
2488 0         0 $self->{ERRSTR}='empty input image';
2489 0         0 return undef;
2490             }
2491              
2492 9         26012 $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
2493              
2494 9 50       63 if ( !defined($img->{IMG}) ) {
2495 0         0 $self->{ERRSTR} = 'unable to scale image';
2496 0         0 return undef;
2497             }
2498              
2499 9         65 return $img;
2500             }
2501              
2502             # Scales only along the Y axis
2503              
2504             sub scaleY {
2505 11     11 0 1401 my $self = shift;
2506 11         57 my %opts = ( scalefactor => 0.5, @_ );
2507              
2508 11 100       39 unless (defined wantarray) {
2509 1         5 my @caller = caller;
2510 1         9 warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
2511 1         127 return;
2512             }
2513              
2514 10 100       28 $self->_valid_image("scaleY")
2515             or return;
2516              
2517 9         35 my $img = Imager->new();
2518              
2519 9         19 my $scalefactor = $opts{scalefactor};
2520              
2521 9 100       29 if ($opts{pixels}) {
2522 3         8 $scalefactor = $opts{pixels} / $self->getheight();
2523             }
2524              
2525 9 50       25 unless ($self->{IMG}) {
2526 0         0 $self->{ERRSTR} = 'empty input image';
2527 0         0 return undef;
2528             }
2529 9         41129 $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
2530              
2531 9 50       77 if ( !defined($img->{IMG}) ) {
2532 0         0 $self->{ERRSTR} = 'unable to scale image';
2533 0         0 return undef;
2534             }
2535              
2536 9         91 return $img;
2537             }
2538              
2539             # Transform returns a spatial transformation of the input image
2540             # this moves pixels to a new location in the returned image.
2541             # NOTE - should make a utility function to check transforms for
2542             # stack overruns
2543              
2544             our $I2P;
2545              
2546             sub transform {
2547 0     0 0 0 my $self=shift;
2548 0         0 my %opts=@_;
2549 0         0 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
2550              
2551             # print Dumper(\%opts);
2552             # xopcopdes
2553              
2554 0 0       0 $self->_valid_image("transform")
2555             or return;
2556              
2557 0 0 0     0 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
2558 0 0       0 if (!$I2P) {
2559             {
2560 0         0 local @INC = @INC;
  0         0  
2561 0 0       0 pop @INC if $INC[-1] eq '.';
2562 0         0 eval ("use Affix::Infix2Postfix;");
2563             }
2564              
2565 0 0       0 if ( $@ ) {
2566 0         0 $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
2567 0         0 return undef;
2568             }
2569 0         0 $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
2570             {op=>'-',trans=>'Sub'},
2571             {op=>'*',trans=>'Mult'},
2572             {op=>'/',trans=>'Div'},
2573             {op=>'-','type'=>'unary',trans=>'u-'},
2574             {op=>'**'},
2575             {op=>'func','type'=>'unary'}],
2576             'grouping'=>[qw( \( \) )],
2577             'func'=>[qw( sin cos )],
2578             'vars'=>[qw( x y )]
2579             );
2580             }
2581              
2582 0         0 @xt=$I2P->translate($opts{'xexpr'});
2583 0         0 @yt=$I2P->translate($opts{'yexpr'});
2584              
2585 0         0 $numre=$I2P->{'numre'};
2586 0         0 @pt=(0,0);
2587              
2588 0 0       0 for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
2589 0 0       0 for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
2590 0         0 @{$opts{'parm'}}=@pt;
  0         0  
2591             }
2592              
2593             # print Dumper(\%opts);
2594              
2595 0 0 0     0 if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
  0         0  
2596 0         0 $self->{ERRSTR}='transform: no xopcodes given.';
2597 0         0 return undef;
2598             }
2599              
2600 0         0 @op=@{$opts{'xopcodes'}};
  0         0  
2601 0         0 for $iop (@op) {
2602 0 0 0     0 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2603 0         0 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2604 0         0 return undef;
2605             }
2606 0 0       0 push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
  0         0  
2607             }
2608              
2609              
2610             # yopcopdes
2611              
2612 0 0 0     0 if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
  0         0  
2613 0         0 $self->{ERRSTR}='transform: no yopcodes given.';
2614 0         0 return undef;
2615             }
2616              
2617 0         0 @op=@{$opts{'yopcodes'}};
  0         0  
2618 0         0 for $iop (@op) {
2619 0 0 0     0 if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
2620 0         0 $self->{ERRSTR}="transform: illegal opcode '$_'.";
2621 0         0 return undef;
2622             }
2623 0 0       0 push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
  0         0  
2624             }
2625              
2626             #parameters
2627              
2628 0 0       0 if ( !exists $opts{'parm'}) {
2629 0         0 $self->{ERRSTR}='transform: no parameter arg given.';
2630 0         0 return undef;
2631             }
2632              
2633             # print Dumper(\@ropx);
2634             # print Dumper(\@ropy);
2635             # print Dumper(\@ropy);
2636              
2637 0         0 my $img = Imager->new();
2638 0         0 $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
2639 0 0       0 if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
  0         0  
  0         0  
2640 0         0 return $img;
2641             }
2642              
2643              
2644             sub transform2 {
2645 30     30 0 1663 my ($opts, @imgs) = @_;
2646            
2647 30         134 require "Imager/Expr.pm";
2648              
2649 30         67 $opts->{variables} = [ qw(x y) ];
2650 30         39 my ($width, $height) = @{$opts}{qw(width height)};
  30         58  
2651 30 100       63 if (@imgs) {
2652 26         28 my $index = 1;
2653 26         43 for my $img (@imgs) {
2654 28 100       50 unless ($img->_valid_image("transform2")) {
2655 1         3 Imager->_set_error($img->errstr . " (input image $index)");
2656 1         4 return;
2657             }
2658 27         43 ++$index;
2659             }
2660              
2661 25   33     78 $width ||= $imgs[0]->getwidth();
2662 25   33     69 $height ||= $imgs[0]->getheight();
2663 25         29 my $img_num = 1;
2664 25         30 for my $img (@imgs) {
2665 26         36 $opts->{constants}{"w$img_num"} = $img->getwidth();
2666 26         41 $opts->{constants}{"h$img_num"} = $img->getheight();
2667 26         38 $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
2668 26         37 $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
2669 26         43 ++$img_num;
2670             }
2671             }
2672 29 100       46 if ($width) {
2673 28         46 $opts->{constants}{w} = $width;
2674 28         48 $opts->{constants}{cx} = $width/2;
2675             }
2676             else {
2677 1         2 $Imager::ERRSTR = "No width supplied";
2678 1         2 return;
2679             }
2680 28 50       37 if ($height) {
2681 28         44 $opts->{constants}{h} = $height;
2682 28         56 $opts->{constants}{cy} = $height/2;
2683             }
2684             else {
2685 0         0 $Imager::ERRSTR = "No height supplied";
2686 0         0 return;
2687             }
2688 28         79 my $code = Imager::Expr->new($opts);
2689 28 50       54 if (!$code) {
2690 0         0 $Imager::ERRSTR = Imager::Expr::error();
2691 0         0 return;
2692             }
2693 28   100     75 my $channels = $opts->{channels} || 3;
2694 28 50 33     75 unless ($channels >= 1 && $channels <= 4) {
2695 0         0 return Imager->_set_error("channels must be an integer between 1 and 4");
2696             }
2697              
2698 28         67 my $img = Imager->new();
2699             $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
2700             $channels, $code->code(),
2701             $code->nregs(), $code->cregs(),
2702 28         94 [ map { $_->{IMG} } @imgs ]);
  26         23899  
2703 28 100       141 if (!defined $img->{IMG}) {
2704 1         9 $Imager::ERRSTR = Imager->_error_as_msg();
2705 1         4 return;
2706             }
2707              
2708 27         237 return $img;
2709             }
2710              
2711             sub rubthrough {
2712 22     22 0 141 my $self=shift;
2713 22         90 my %opts= @_;
2714              
2715 22 100       53 $self->_valid_image("rubthrough")
2716             or return;
2717              
2718 21 100 66     80 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2719 1         4 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2720 1         5 return;
2721             }
2722              
2723             %opts = (src_minx => 0,
2724             src_miny => 0,
2725             src_maxx => $opts{src}->getwidth(),
2726 20         66 src_maxy => $opts{src}->getheight(),
2727             %opts);
2728              
2729 20         42 my $tx = $opts{tx};
2730 20 100       53 defined $tx or $tx = $opts{left};
2731 20 100       46 defined $tx or $tx = 0;
2732              
2733 20         28 my $ty = $opts{ty};
2734 20 100       41 defined $ty or $ty = $opts{top};
2735 20 100       43 defined $ty or $ty = 0;
2736              
2737 20 50       4367 unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $tx, $ty,
2738             $opts{src_minx}, $opts{src_miny},
2739             $opts{src_maxx}, $opts{src_maxy})) {
2740 0         0 $self->_set_error($self->_error_as_msg());
2741 0         0 return undef;
2742             }
2743              
2744 20         158 return $self;
2745             }
2746              
2747             sub compose {
2748 58     58 0 337 my $self = shift;
2749 58         361 my %opts =
2750             (
2751             opacity => 1.0,
2752             mask_left => 0,
2753             mask_top => 0,
2754             @_
2755             );
2756              
2757 58 100       131 $self->_valid_image("compose")
2758             or return;
2759              
2760 57 50       134 unless ($opts{src}) {
2761 0         0 $self->_set_error("compose: src parameter missing");
2762 0         0 return;
2763             }
2764            
2765 57 100       115 unless ($opts{src}->_valid_image("compose")) {
2766 1         4 $self->_set_error($opts{src}->errstr . " (for src)");
2767 1         4 return;
2768             }
2769 56         119 my $src = $opts{src};
2770              
2771 56         93 my $left = $opts{left};
2772 56 50       182 defined $left or $left = $opts{tx};
2773 56 100       95 defined $left or $left = 0;
2774              
2775 56         98 my $top = $opts{top};
2776 56 50       123 defined $top or $top = $opts{ty};
2777 56 100       107 defined $top or $top = 0;
2778              
2779 56         101 my $src_left = $opts{src_left};
2780 56 100       143 defined $src_left or $src_left = $opts{src_minx};
2781 56 100       120 defined $src_left or $src_left = 0;
2782              
2783 56         104 my $src_top = $opts{src_top};
2784 56 100       140 defined $src_top or $src_top = $opts{src_miny};
2785 56 100       86 defined $src_top or $src_top = 0;
2786              
2787 56         72 my $width = $opts{width};
2788 56 50 66     179 if (!defined $width && defined $opts{src_maxx}) {
2789 0         0 $width = $opts{src_maxx} - $src_left;
2790             }
2791 56 100       177 defined $width or $width = $src->getwidth() - $src_left;
2792              
2793 56         78 my $height = $opts{height};
2794 56 50 66     204 if (!defined $height && defined $opts{src_maxy}) {
2795 0         0 $height = $opts{src_maxy} - $src_top;
2796             }
2797 56 100       135 defined $height or $height = $src->getheight() - $src_top;
2798              
2799 56         234 my $combine = $self->_combine($opts{combine}, 'normal');
2800              
2801 56 100       141 if ($opts{mask}) {
2802 31 100       64 unless ($opts{mask}->_valid_image("compose")) {
2803 1         4 $self->_set_error($opts{mask}->errstr . " (for mask)");
2804 1         4 return;
2805             }
2806              
2807 30         43 my $mask_left = $opts{mask_left};
2808 30 50       52 defined $mask_left or $mask_left = $opts{mask_minx};
2809 30 50       52 defined $mask_left or $mask_left = 0;
2810            
2811 30         43 my $mask_top = $opts{mask_top};
2812 30 50       61 defined $mask_top or $mask_top = $opts{mask_miny};
2813 30 50       67 defined $mask_top or $mask_top = 0;
2814              
2815 30 100       7189 unless (i_compose_mask($self->{IMG}, $src->{IMG}, $opts{mask}{IMG},
2816             $left, $top, $src_left, $src_top,
2817             $mask_left, $mask_top, $width, $height,
2818             $combine, $opts{opacity})) {
2819 10         46 $self->_set_error(Imager->_error_as_msg);
2820 10         72 return;
2821             }
2822             }
2823             else {
2824 25 100       3845 unless (i_compose($self->{IMG}, $src->{IMG}, $left, $top, $src_left, $src_top,
2825             $width, $height, $combine, $opts{opacity})) {
2826 10         45 $self->_set_error(Imager->_error_as_msg);
2827 10         73 return;
2828             }
2829             }
2830              
2831 35         347 return $self;
2832             }
2833              
2834             sub flip {
2835 144     144 0 683 my $self = shift;
2836 144         251 my %opts = @_;
2837              
2838 144 100       206 $self->_valid_image("flip")
2839             or return;
2840              
2841 143         342 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
2842 143         140 my $dir;
2843 143 50 33     391 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
2844 143         176 $dir = $xlate{$opts{'dir'}};
2845 143 50       12136 return $self if i_flipxy($self->{IMG}, $dir);
2846 0         0 return ();
2847             }
2848              
2849             sub rotate {
2850 41     41 0 1563 my $self = shift;
2851 41         118 my %opts = @_;
2852              
2853 41 100       144 unless (defined wantarray) {
2854 1         4 my @caller = caller;
2855 1         11 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
2856 1         22 return;
2857             }
2858              
2859 40 100       97 $self->_valid_image("rotate")
2860             or return;
2861              
2862 39 100 33     130 if (defined $opts{right}) {
    50          
2863 28         41 my $degrees = $opts{right};
2864 28 50       60 if ($degrees < 0) {
2865 0         0 $degrees += 360 * int(((-$degrees)+360)/360);
2866             }
2867 28         42 $degrees = $degrees % 360;
2868 28 100 100     99 if ($degrees == 0) {
    50 66        
2869 2         5 return $self->copy();
2870             }
2871             elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
2872 26         56 my $result = Imager->new();
2873 26 50       12175 if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
2874 26         128 return $result;
2875             }
2876             else {
2877 0         0 $self->{ERRSTR} = $self->_error_as_msg();
2878 0         0 return undef;
2879             }
2880             }
2881             else {
2882 0         0 $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
2883 0         0 return undef;
2884             }
2885             }
2886             elsif (defined $opts{radians} || defined $opts{degrees}) {
2887 11   33     65 my $amount = $opts{radians} || $opts{degrees} * 3.14159265358979 / 180;
2888              
2889 11         20 my $back = $opts{back};
2890 11         37 my $result = Imager->new;
2891 11 100       28 if ($back) {
2892 6         19 $back = _color($back);
2893 6 100       17 unless ($back) {
2894 1         5 $self->_set_error(Imager->errstr);
2895 1         4 return undef;
2896             }
2897              
2898 5         13495 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
2899             }
2900             else {
2901 5         7457 $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
2902             }
2903 10 50       61 if ($result->{IMG}) {
2904 10         253 return $result;
2905             }
2906             else {
2907 0         0 $self->{ERRSTR} = $self->_error_as_msg();
2908 0         0 return undef;
2909             }
2910             }
2911             else {
2912 0         0 $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
2913 0         0 return undef;
2914             }
2915             }
2916              
2917             sub matrix_transform {
2918 5     5 0 786 my $self = shift;
2919 5         12 my %opts = @_;
2920              
2921 5 100       14 $self->_valid_image("matrix_transform")
2922             or return;
2923              
2924 4 100       12 unless (defined wantarray) {
2925 1         4 my @caller = caller;
2926 1         9 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
2927 1         23 return;
2928             }
2929              
2930 3 50       8 if ($opts{matrix}) {
2931 3   33     13 my $xsize = $opts{xsize} || $self->getwidth;
2932 3   33     14 my $ysize = $opts{ysize} || $self->getheight;
2933              
2934 3         11 my $result = Imager->new;
2935 3 100       11 if ($opts{back}) {
2936             $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2937             $opts{matrix}, $opts{back})
2938 1 50       1127 or return undef;
2939             }
2940             else {
2941             $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
2942             $opts{matrix})
2943 2 50       1373 or return undef;
2944             }
2945              
2946 3         18 return $result;
2947             }
2948             else {
2949 0         0 $self->{ERRSTR} = "matrix parameter required";
2950 0         0 return undef;
2951             }
2952             }
2953              
2954             # blame Leolo :)
2955             *yatf = \&matrix_transform;
2956              
2957             # These two are supported for legacy code only
2958              
2959             sub i_color_new {
2960 254     254 0 27509 return Imager::Color->new(@_);
2961             }
2962              
2963             sub i_color_set {
2964 0     0 0 0 return Imager::Color::set(@_);
2965             }
2966              
2967             # Draws a box between the specified corner points.
2968             sub box {
2969 981     981 0 12258 my $self=shift;
2970 981         1295 my $raw = $self->{IMG};
2971              
2972 981 100       1566 $self->_valid_image("box")
2973             or return;
2974              
2975 980         2532 my %opts = @_;
2976              
2977 980         1265 my ($xmin, $ymin, $xmax, $ymax);
2978 980 100       1521 if (exists $opts{'box'}) {
2979 565         1038 $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]);
2980 565         926 $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]);
2981 565         813 $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]);
2982 565         797 $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]);
2983             }
2984             else {
2985 415 100       790 defined($xmin = $opts{xmin}) or $xmin = 0;
2986 415 100       1185 defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1;
2987 415 100       804 defined($ymin = $opts{ymin}) or $ymin = 0;
2988 415 100       927 defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1;
2989             }
2990              
2991 980 100       1670 if ($opts{filled}) {
    100          
2992 863         1010 my $color = $opts{'color'};
2993              
2994 863 100       1165 if (defined $color) {
2995 861 100       2438 unless (_is_color_object($color)) {
2996 145         283 $color = _color($color);
2997 145 50       395 unless ($color) {
2998 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
2999 0         0 return;
3000             }
3001             }
3002             }
3003             else {
3004 2         8 $color = i_color_new(255,255,255,255);
3005             }
3006              
3007 863 100       2002 if ($color->isa("Imager::Color")) {
3008 826         51813 i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color);
3009             }
3010             else {
3011 37         3173 i_box_filledf($raw, $xmin, $ymin,$xmax, $ymax, $color);
3012             }
3013             }
3014             elsif ($opts{fill}) {
3015 113 100       300 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3016             # assume it's a hash ref
3017 6         1379 require 'Imager/Fill.pm';
3018 6 50       15 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  6         39  
3019 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3020 0         0 return undef;
3021             }
3022             }
3023 113         25343 i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill});
3024             }
3025             else {
3026 4         7 my $color = $opts{'color'};
3027 4 100       10 if (defined $color) {
3028 3 100       39 unless (_is_color_object($color)) {
3029 2         8 $color = _color($color);
3030 2 50       10 unless ($color) {
3031 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3032 0         0 return;
3033             }
3034             }
3035             }
3036             else {
3037 1         4 $color = i_color_new(255, 255, 255, 255);
3038             }
3039 4 50       17 unless ($color) {
3040 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3041 0         0 return;
3042             }
3043 4         324 i_box($raw, $xmin, $ymin, $xmax, $ymax, $color);
3044             }
3045              
3046 980         3295 return $self;
3047             }
3048              
3049             sub arc {
3050 257     257 0 1263 my $self=shift;
3051              
3052 257 100       544 $self->_valid_image("arc")
3053             or return;
3054              
3055 256         584 my $dflcl= [ 255, 255, 255, 255];
3056 256         305 my $good = 1;
3057 256         609 my %opts=
3058             (
3059             color=>$dflcl,
3060             'r'=>_min($self->getwidth(),$self->getheight())/3,
3061             'x'=>$self->getwidth()/2,
3062             'y'=>$self->getheight()/2,
3063             'd1'=>0, 'd2'=>361,
3064             filled => 1,
3065             @_,
3066             );
3067 256 100       678 if ($opts{aa}) {
3068 133 100       292 if ($opts{fill}) {
    100          
3069 2 50       7 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3070             # assume it's a hash ref
3071 2         11 require 'Imager/Fill.pm';
3072 2 50       3 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  2         9  
3073 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3074 0         0 return;
3075             }
3076             }
3077 2 100 66     11 if ($opts{d1} == 0 && $opts{d2} == 361) {
3078             i_circle_aa_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
3079 1         432 $opts{fill}{fill});
3080             }
3081             else {
3082             i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
3083 1         748 $opts{'d2'}, $opts{fill}{fill});
3084             }
3085             }
3086             elsif ($opts{filled}) {
3087 33         72 my $color = _color($opts{'color'});
3088 33 50       79 unless ($color) {
3089 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3090 0         0 return;
3091             }
3092 33 100 100     136 if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
      66        
3093 8         3144 i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
3094             $color);
3095             }
3096             else {
3097             i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
3098 25         103655 $opts{'d1'}, $opts{'d2'}, $color);
3099             }
3100             }
3101             else {
3102 98         183 my $color = _color($opts{'color'});
3103 98 100       252 if ($opts{d2} - $opts{d1} >= 360) {
3104 25         4074 $good = i_circle_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $color);
3105             }
3106             else {
3107 73         8647 $good = i_arc_out_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'}, $opts{'d1'}, $opts{'d2'}, $color);
3108             }
3109             }
3110             }
3111             else {
3112 123 100       250 if ($opts{fill}) {
3113 10 50       35 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3114             # assume it's a hash ref
3115 10         709 require 'Imager/Fill.pm';
3116 10 100       21 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  10         71  
3117 1         4 $self->{ERRSTR} = $Imager::ERRSTR;
3118 1         6 return;
3119             }
3120             }
3121             i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
3122 9         48877 $opts{'d2'}, $opts{fill}{fill});
3123             }
3124             else {
3125 113         250 my $color = _color($opts{'color'});
3126 113 50       266 unless ($color) {
3127 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3128 0         0 return;
3129             }
3130 113 100       221 if ($opts{filled}) {
3131             i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
3132 51         268596 $opts{'d1'}, $opts{'d2'}, $color);
3133             }
3134             else {
3135 62 100 100     147 if ($opts{d1} == 0 && $opts{d2} == 361) {
3136 13         1203 $good = i_circle_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $color);
3137             }
3138             else {
3139 49         5053 $good = i_arc_out($self->{IMG}, $opts{x}, $opts{y}, $opts{r}, $opts{d1}, $opts{d2}, $color);
3140             }
3141             }
3142             }
3143             }
3144 254 50       2653 unless ($good) {
3145 0         0 $self->_set_error($self->_error_as_msg);
3146 0         0 return;
3147             }
3148              
3149 254         2099 return $self;
3150             }
3151              
3152             # Draws a line from one point to the other
3153             # the endpoint is set if the endp parameter is set which it is by default.
3154             # to turn of the endpoint being set use endp=>0 when calling line.
3155              
3156             sub line {
3157 212     212 0 2272 my $self=shift;
3158 212         359 my $dflcl=i_color_new(0,0,0,0);
3159 212         1059 my %opts=(color=>$dflcl,
3160             endp => 1,
3161             @_);
3162              
3163 212 100       476 $self->_valid_image("line")
3164             or return;
3165              
3166 211 50 33     562 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
  0         0  
  0         0  
3167 211 50 33     500 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
  0         0  
  0         0  
3168              
3169 211         321 my $color = _color($opts{'color'});
3170 211 50       327 unless ($color) {
3171 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3172 0         0 return;
3173             }
3174              
3175 211 100       369 $opts{antialias} = $opts{aa} if defined $opts{aa};
3176 211 100       300 if ($opts{antialias}) {
3177             i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3178 146         4126 $color, $opts{endp});
3179             } else {
3180             i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
3181 65         531 $color, $opts{endp});
3182             }
3183 211         11895 return $self;
3184             }
3185              
3186             # Draws a line between an ordered set of points - It more or less just transforms this
3187             # into a list of lines.
3188              
3189             sub polyline {
3190 6     6 0 869 my $self=shift;
3191 6         10 my ($pt,$ls,@points);
3192 6         16 my $dflcl=i_color_new(0,0,0,0);
3193 6         41 my %opts=(color=>$dflcl,@_);
3194              
3195 6 100       18 $self->_valid_image("polyline")
3196             or return;
3197              
3198 5 100       14 if (exists($opts{points})) { @points=@{$opts{points}}; }
  1         2  
  1         2  
3199 5 50 66     36 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
      33        
3200 4         8 @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
  269         361  
  4         16  
3201             }
3202              
3203             # print Dumper(\@points);
3204              
3205 5         18 my $color = _color($opts{'color'});
3206 5 50       16 unless ($color) {
3207 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3208 0         0 return;
3209             }
3210 5 100       13 $opts{antialias} = $opts{aa} if defined $opts{aa};
3211 5 100       16 if ($opts{antialias}) {
3212 2         5 for $pt(@points) {
3213 6 100       16 if (defined($ls)) {
3214 4         32 i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
3215             }
3216 6         9 $ls=$pt;
3217             }
3218             } else {
3219 3         8 for $pt(@points) {
3220 266 100       326 if (defined($ls)) {
3221 263         707 i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
3222             }
3223 266         283 $ls=$pt;
3224             }
3225             }
3226 5         410 return $self;
3227             }
3228              
3229             sub polygon {
3230 11     11 0 8112 my $self = shift;
3231 11         26 my ($pt,$ls,@points);
3232 11         34 my $dflcl = i_color_new(0,0,0,0);
3233 11         65 my %opts = (color=>$dflcl, @_);
3234              
3235 11 100       42 $self->_valid_image("polygon")
3236             or return;
3237              
3238 10 100       29 if (exists($opts{points})) {
3239 8         13 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
  1044         1206  
  8         23  
3240 8         34 $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
  1044         1190  
  8         18  
3241             }
3242              
3243 10 50 33     69 if (!exists $opts{'x'} or !exists $opts{'y'}) {
3244 0         0 $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
  0         0  
3245             }
3246              
3247 10         48 my $mode = _first($opts{mode}, 0);
3248              
3249 10 100       32 if ($opts{'fill'}) {
3250 4 100       20 unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
3251             # assume it's a hash ref
3252 3         641 require 'Imager/Fill.pm';
3253 3 50       8 unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
  3         26  
3254 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3255 0         0 return undef;
3256             }
3257             }
3258 4 100       7173 unless (i_poly_aa_cfill_m($self->{IMG}, $opts{'x'}, $opts{'y'},
3259             $mode, $opts{'fill'}{'fill'})) {
3260 1         5 return $self->_set_error($self->_error_as_msg);
3261             }
3262             }
3263             else {
3264 6         23 my $color = _color($opts{'color'});
3265 6 50       16 unless ($color) {
3266 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3267 0         0 return;
3268             }
3269 6 100       8729 unless (i_poly_aa_m($self->{IMG}, $opts{'x'}, $opts{'y'}, $mode, $color)) {
3270 1         6 return $self->_set_error($self->_error_as_msg);
3271             }
3272             }
3273              
3274 8         645 return $self;
3275             }
3276              
3277             sub polypolygon {
3278 6     6 0 64 my ($self, %opts) = @_;
3279              
3280 6 50       17 $self->_valid_image("polypolygon")
3281             or return;
3282              
3283 6         11 my $points = $opts{points};
3284 6 50       11 $points
3285             or return $self->_set_error("polypolygon: missing required points");
3286              
3287 6         18 my $mode = _first($opts{mode}, "evenodd");
3288              
3289 6 50       24 if ($opts{filled}) {
    0          
3290 6 50       17 my $color = _color(_first($opts{color}, [ 0, 0, 0, 0 ]))
3291             or return $self->_set_error($Imager::ERRSTR);
3292              
3293 6 50       5558 i_poly_poly_aa($self->{IMG}, $points, $mode, $color)
3294             or return $self->_set_error($self->_error_as_msg);
3295             }
3296             elsif ($opts{fill}) {
3297 0         0 my $fill = $opts{fill};
3298 0 0       0 $self->_valid_fill($fill, "polypolygon")
3299             or return;
3300              
3301             i_poly_poly_aa_cfill($self->{IMG}, $points, $mode, $fill->{fill})
3302 0 0       0 or return $self->_set_error($self->_error_as_msg);
3303             }
3304             else {
3305 0 0       0 my $color = _color(_first($opts{color}, [ 0, 0, 0, 255 ]))
3306             or return $self->_set_error($Imager::ERRSTR);
3307              
3308 0         0 my $rimg = $self->{IMG};
3309              
3310 0 0       0 if (_first($opts{aa}, 1)) {
3311 0         0 for my $poly (@$points) {
3312 0         0 my $xp = $poly->[0];
3313 0         0 my $yp = $poly->[1];
3314 0         0 for my $i (0 .. $#$xp - 1) {
3315 0         0 i_line_aa($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3316             $color, 0);
3317             }
3318 0         0 i_line_aa($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3319             $color, 0);
3320             }
3321             }
3322             else {
3323 0         0 for my $poly (@$points) {
3324 0         0 my $xp = $poly->[0];
3325 0         0 my $yp = $poly->[1];
3326 0         0 for my $i (0 .. $#$xp - 1) {
3327 0         0 i_line($rimg, $xp->[$i], $yp->[$i], $xp->[$i+1], $yp->[$i+1],
3328             $color, 0);
3329             }
3330 0         0 i_line($rimg, $xp->[$#$xp], $yp->[$#$yp], $xp->[0], $yp->[0],
3331             $color, 0);
3332             }
3333             }
3334             }
3335              
3336 6         67 return $self;
3337             }
3338              
3339             # this the multipoint bezier curve
3340             # this is here more for testing that actual usage since
3341             # this is not a good algorithm. Usually the curve would be
3342             # broken into smaller segments and each done individually.
3343              
3344             sub polybezier {
3345 0     0 0 0 my $self=shift;
3346 0         0 my ($pt,$ls,@points);
3347 0         0 my $dflcl=i_color_new(0,0,0,0);
3348 0         0 my %opts=(color=>$dflcl,@_);
3349              
3350 0 0       0 $self->_valid_image("polybezier")
3351             or return;
3352              
3353 0 0       0 if (exists $opts{points}) {
3354 0         0 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
  0         0  
  0         0  
3355 0         0 $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
  0         0  
  0         0  
3356             }
3357              
3358 0 0 0     0 unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
  0         0  
  0         0  
  0         0  
3359 0         0 $self->{ERRSTR}='Missing or invalid points.';
3360 0         0 return;
3361             }
3362              
3363 0         0 my $color = _color($opts{'color'});
3364 0 0       0 unless ($color) {
3365 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3366 0         0 return;
3367             }
3368 0         0 i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
3369 0         0 return $self;
3370             }
3371              
3372             sub flood_fill {
3373 90     90 0 530 my $self = shift;
3374 90         231 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
3375 90         358 my $rc;
3376              
3377 90 100       167 $self->_valid_image("flood_fill")
3378             or return;
3379              
3380 89 50 33     255 unless (exists $opts{'x'} && exists $opts{'y'}) {
3381 0         0 $self->{ERRSTR} = "missing seed x and y parameters";
3382 0         0 return undef;
3383             }
3384              
3385 89 100       152 if ($opts{border}) {
3386 2         9 my $border = _color($opts{border});
3387 2 50       8 unless ($border) {
3388 0         0 $self->_set_error($Imager::ERRSTR);
3389 0         0 return;
3390             }
3391 2 100       8 if ($opts{fill}) {
3392 1 50       7 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3393             # assume it's a hash ref
3394 1         8 require Imager::Fill;
3395 1 50       3 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  1         10  
3396 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3397 0         0 return;
3398             }
3399             }
3400             $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3401 1         10865 $opts{fill}{fill}, $border);
3402             }
3403             else {
3404 1         3 my $color = _color($opts{'color'});
3405 1 50       5 unless ($color) {
3406 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3407 0         0 return;
3408             }
3409 1         10327 $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
3410             $color, $border);
3411             }
3412 2 50       23 if ($rc) {
3413 2         220 return $self;
3414             }
3415             else {
3416 0         0 $self->{ERRSTR} = $self->_error_as_msg();
3417 0         0 return;
3418             }
3419             }
3420             else {
3421 87 100       121 if ($opts{fill}) {
3422 1 50       5 unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
3423             # assume it's a hash ref
3424 1         11 require 'Imager/Fill.pm';
3425 1 50       2 unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  1         12  
3426 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3427 0         0 return;
3428             }
3429             }
3430 1         10407 $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
3431             }
3432             else {
3433 86         126 my $color = _color($opts{'color'});
3434 86 50       156 unless ($color) {
3435 0         0 $self->{ERRSTR} = $Imager::ERRSTR;
3436 0         0 return;
3437             }
3438 86         12661 $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
3439             }
3440 87 50       180 if ($rc) {
3441 87         486 return $self;
3442             }
3443             else {
3444 0         0 $self->{ERRSTR} = $self->_error_as_msg();
3445 0         0 return;
3446             }
3447             }
3448             }
3449              
3450             sub setpixel {
3451 128     128 0 965 my ($self, %opts) = @_;
3452              
3453 128 100       267 $self->_valid_image("setpixel")
3454             or return;
3455              
3456 127         199 my $color = $opts{color};
3457 127 100       222 unless (defined $color) {
3458 1         3 $color = $self->{fg};
3459 1 50       5 defined $color or $color = NC(255, 255, 255);
3460             }
3461              
3462 127 100 100     487 unless (ref $color && UNIVERSAL::isa($color, "Imager::Color")) {
3463 84 100       163 unless ($color = _color($color, 'setpixel')) {
3464 1         5 $self->_set_error("setpixel: " . Imager->errstr);
3465 1         6 return;
3466             }
3467             }
3468              
3469 126 100 100     403 unless (exists $opts{'x'} && exists $opts{'y'}) {
3470 2         5 $self->_set_error('setpixel: missing x or y parameter');
3471 2         9 return;
3472             }
3473              
3474 124         155 my $x = $opts{'x'};
3475 124         196 my $y = $opts{'y'};
3476 124 100 100     337 if (ref $x || ref $y) {
3477 9 100       28 $x = ref $x ? $x : [ $x ];
3478 9 100       18 $y = ref $y ? $y : [ $y ];
3479 9 100       17 unless (@$x) {
3480 1         3 $self->_set_error("setpixel: x is a reference to an empty array");
3481 1         5 return;
3482             }
3483 8 100       14 unless (@$y) {
3484 1         3 $self->_set_error("setpixel: y is a reference to an empty array");
3485 1         7 return;
3486             }
3487              
3488             # make both the same length, replicating the last element
3489 7 100       24 if (@$x < @$y) {
    100          
3490 1         8 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3491             }
3492             elsif (@$y < @$x) {
3493 1         4 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3494             }
3495              
3496 7         9 my $set = 0;
3497 7 100       23 if ($color->isa('Imager::Color')) {
3498 5         13 for my $i (0..$#$x) {
3499 17 100       52 i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
3500             or ++$set;
3501             }
3502             }
3503             else {
3504 2         9 for my $i (0..$#$x) {
3505 8 100       28 i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
3506             or ++$set;
3507             }
3508             }
3509              
3510 7         88 return $set;
3511             }
3512             else {
3513 115 100       341 if ($color->isa('Imager::Color')) {
3514 84 100       427 i_ppix($self->{IMG}, $x, $y, $color)
3515             and return "0 but true";
3516             }
3517             else {
3518 31 100       237 i_ppixf($self->{IMG}, $x, $y, $color)
3519             and return "0 but true";
3520             }
3521              
3522 79         2827 return 1;
3523             }
3524             }
3525              
3526             sub getpixel {
3527 239     239 0 5912 my $self = shift;
3528              
3529 239         824 my %opts = ( "type"=>'8bit', @_);
3530              
3531 239 100       491 $self->_valid_image("getpixel")
3532             or return;
3533              
3534 238 100 100     880 unless (exists $opts{'x'} && exists $opts{'y'}) {
3535 2         9 $self->_set_error('getpixel: missing x or y parameter');
3536 2         7 return;
3537             }
3538              
3539 236         368 my $x = $opts{'x'};
3540 236         282 my $y = $opts{'y'};
3541 236         307 my $type = $opts{'type'};
3542 236 100 100     734 if (ref $x || ref $y) {
3543 19 100       35 $x = ref $x ? $x : [ $x ];
3544 19 100       32 $y = ref $y ? $y : [ $y ];
3545 19 100       35 unless (@$x) {
3546 1         3 $self->_set_error("getpixel: x is a reference to an empty array");
3547 1         4 return;
3548             }
3549 18 100       29 unless (@$y) {
3550 1         3 $self->_set_error("getpixel: y is a reference to an empty array");
3551 1         3 return;
3552             }
3553              
3554             # make both the same length, replicating the last element
3555 17 100       60 if (@$x < @$y) {
    100          
3556 1         5 $x = [ @$x, ($x->[-1]) x (@$y - @$x) ];
3557             }
3558             elsif (@$y < @$x) {
3559 3         10 $y = [ @$y, ($y->[-1]) x (@$x - @$y) ];
3560             }
3561              
3562 17         21 my @result;
3563 17 100 66     636 if ($type eq '8bit') {
    100          
3564 13         31 for my $i (0..$#$x) {
3565 40         1415 push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
3566             }
3567             }
3568             elsif ($type eq 'float' || $type eq 'double') {
3569 3         10 for my $i (0..$#$x) {
3570 10         347 push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
3571             }
3572             }
3573             else {
3574 1         5 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3575 1         6 return;
3576             }
3577 16 50       256 return wantarray ? @result : \@result;
3578             }
3579             else {
3580 217 100 100     491 if ($type eq '8bit') {
    100          
3581 195         8259 return i_get_pixel($self->{IMG}, $x, $y);
3582             }
3583             elsif ($type eq 'float' || $type eq 'double') {
3584 21         1002 return i_gpixf($self->{IMG}, $x, $y);
3585             }
3586             else {
3587 1         4 $self->_set_error("getpixel: type must be '8bit' or 'float'");
3588 1         4 return;
3589             }
3590             }
3591             }
3592              
3593             sub getscanline {
3594 39     39 0 3031 my $self = shift;
3595 39         132 my %opts = ( type => '8bit', x=>0, @_);
3596              
3597 39 100       74 $self->_valid_image("getscanline")
3598             or return;
3599              
3600 38 100       95 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3601              
3602 38 100       67 unless (defined $opts{'y'}) {
3603 1         4 $self->_set_error("missing y parameter");
3604 1         4 return;
3605             }
3606              
3607 37 100       105 if ($opts{type} eq '8bit') {
    100          
    100          
3608             return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3609 16         3654 $opts{'y'});
3610             }
3611             elsif ($opts{type} eq 'float') {
3612             return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3613 12         1693 $opts{'y'});
3614             }
3615             elsif ($opts{type} eq 'index') {
3616 8 50       28 unless (i_img_type($self->{IMG})) {
3617 0         0 $self->_set_error("type => index only valid on paletted images");
3618 0         0 return;
3619             }
3620             return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
3621 8         570 $opts{'y'});
3622             }
3623             else {
3624 1         3 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3625 1         4 return;
3626             }
3627             }
3628              
3629             sub setscanline {
3630 215     215 0 6799 my $self = shift;
3631 215         594 my %opts = ( x=>0, @_);
3632              
3633 215 100       410 $self->_valid_image("setscanline")
3634             or return;
3635              
3636 214 50       452 unless (defined $opts{'y'}) {
3637 0         0 $self->_set_error("missing y parameter");
3638 0         0 return;
3639             }
3640              
3641 214 100       338 if (!$opts{type}) {
3642 200 100 66     382 if (ref $opts{pixels} && @{$opts{pixels}}) {
  49         133  
3643             # try to guess the type
3644 49 100       222 if ($opts{pixels}[0]->isa('Imager::Color')) {
    50          
3645 32         83 $opts{type} = '8bit';
3646             }
3647             elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
3648 17         35 $opts{type} = 'float';
3649             }
3650             else {
3651 0         0 $self->_set_error("missing type parameter and could not guess from pixels");
3652 0         0 return;
3653             }
3654             }
3655             else {
3656             # default
3657 151         205 $opts{type} = '8bit';
3658             }
3659             }
3660              
3661 214 100       404 if ($opts{type} eq '8bit') {
    100          
    50          
3662 183 100       250 if (ref $opts{pixels}) {
3663 32         52 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
  32         2109  
3664             }
3665             else {
3666 151         875 return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3667             }
3668             }
3669             elsif ($opts{type} eq 'float') {
3670 18 100       37 if (ref $opts{pixels}) {
3671 17         33 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
  17         1150  
3672             }
3673             else {
3674 1         7 return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3675             }
3676             }
3677             elsif ($opts{type} eq 'index') {
3678 13 100       25 if (ref $opts{pixels}) {
3679 9         14 return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
  9         102  
3680             }
3681             else {
3682 4         38 return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
3683             }
3684             }
3685             else {
3686 0         0 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3687 0         0 return;
3688             }
3689             }
3690              
3691             sub getsamples {
3692 313     313 0 6145 my $self = shift;
3693 313         787 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3694              
3695 313 100       487 $self->_valid_image("getsamples")
3696             or return;
3697              
3698 312 100       707 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3699              
3700 312 50       491 unless (defined $opts{'y'}) {
3701 0         0 $self->_set_error("missing y parameter");
3702 0         0 return;
3703             }
3704            
3705 312 100       443 if ($opts{target}) {
3706 3         8 my $target = $opts{target};
3707 3         5 my $offset = $opts{offset};
3708 3 100       32 if ($opts{type} eq '8bit') {
    100          
    50          
3709             my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3710             $opts{y}, $opts{channels})
3711 1 50       73 or return;
3712 1         5 @{$target}[$offset .. $offset + @samples - 1] = @samples;
  1         5  
3713 1         7 return scalar(@samples);
3714             }
3715             elsif ($opts{type} eq 'float') {
3716             my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3717 1         75 $opts{y}, $opts{channels});
3718 1         7 @{$target}[$offset .. $offset + @samples - 1] = @samples;
  1         5  
3719 1         6 return scalar(@samples);
3720             }
3721             elsif ($opts{type} =~ /^(\d+)bit$/) {
3722 1         3 my $bits = $1;
3723              
3724 1         2 my @data;
3725             my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3726             $opts{y}, $bits, $target,
3727 1         73 $offset, $opts{channels});
3728 1 50       16 unless (defined $count) {
3729 0         0 $self->_set_error(Imager->_error_as_msg);
3730 0         0 return;
3731             }
3732              
3733 1         7 return $count;
3734             }
3735             else {
3736 0         0 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3737 0         0 return;
3738             }
3739             }
3740             else {
3741 309 100       458 if ($opts{type} eq '8bit') {
    50          
    0          
3742             return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3743 297         18206 $opts{y}, $opts{channels});
3744             }
3745             elsif ($opts{type} eq 'float') {
3746             return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3747 12         889 $opts{y}, $opts{channels});
3748             }
3749             elsif ($opts{type} =~ /^(\d+)bit$/) {
3750 0         0 my $bits = $1;
3751              
3752 0         0 my @data;
3753             i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3754             $opts{y}, $bits, \@data, 0, $opts{channels})
3755 0 0       0 or return;
3756 0         0 return @data;
3757             }
3758             else {
3759 0         0 $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
3760 0         0 return;
3761             }
3762             }
3763             }
3764              
3765             sub setsamples {
3766 15     15 0 88 my $self = shift;
3767              
3768 15 100       29 $self->_valid_image("setsamples")
3769             or return;
3770              
3771 14         51 my %opts = ( x => 0, offset => 0 );
3772 14         18 my $data_index;
3773             # avoid duplicating the data parameter, it may be a large scalar
3774 14         21 my $i = 0;
3775 14         28 while ($i < @_ -1) {
3776 48 100       72 if ($_[$i] eq 'data') {
3777 13         16 $data_index = $i+1;
3778             }
3779             else {
3780 35         53 $opts{$_[$i]} = $_[$i+1];
3781             }
3782              
3783 48         75 $i += 2;
3784             }
3785              
3786 14 100       25 unless(defined $data_index) {
3787 1         3 $self->_set_error('setsamples: data parameter missing');
3788 1         3 return;
3789             }
3790 13 100       24 unless (defined $_[$data_index]) {
3791 1         3 $self->_set_error('setsamples: data parameter not defined');
3792 1         8 return;
3793             }
3794              
3795 12         15 my $type = $opts{type};
3796 12 100       24 defined $type or $type = '8bit';
3797              
3798             my $width = defined $opts{width} ? $opts{width}
3799 12 50       31 : $self->getwidth() - $opts{x};
3800              
3801 12         17 my $count;
3802 12 100       36 if ($type eq '8bit') {
    100          
    100          
3803             $count = i_psamp($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3804 5         31 $_[$data_index], $opts{offset}, $width);
3805             }
3806             elsif ($type eq 'float') {
3807             $count = i_psampf($self->{IMG}, $opts{x}, $opts{y}, $opts{channels},
3808 5         50 $_[$data_index], $opts{offset}, $width);
3809             }
3810             elsif ($type =~ /^([0-9]+)bit$/) {
3811 1         4 my $bits = $1;
3812              
3813 1 50       4 unless (ref $_[$data_index]) {
3814 0         0 $self->_set_error("setsamples: data must be an array ref for type not 8bit or float");
3815 0         0 return;
3816             }
3817              
3818             $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
3819             $opts{channels}, $_[$data_index], $opts{offset},
3820 1         68 $width);
3821             }
3822             else {
3823 1         3 $self->_set_error('setsamples: type parameter invalid');
3824 1         4 return;
3825             }
3826              
3827 11 100       29 unless (defined $count) {
3828 4         10 $self->_set_error(Imager->_error_as_msg);
3829 4         21 return;
3830             }
3831              
3832 7         29 return $count;
3833             }
3834              
3835             # make an identity matrix of the given size
3836             sub _identity {
3837 2     2   5 my ($size) = @_;
3838              
3839 2         7 my $matrix = [ map { [ (0) x $size ] } 1..$size ];
  8         18  
3840 2         10 for my $c (0 .. ($size-1)) {
3841 8         12 $matrix->[$c][$c] = 1;
3842             }
3843 2         4 return $matrix;
3844             }
3845              
3846             # general function to convert an image
3847             sub convert {
3848 18     18 0 118 my ($self, %opts) = @_;
3849 18         33 my $matrix;
3850              
3851 18 100       38 $self->_valid_image("convert")
3852             or return;
3853              
3854 17 100       45 unless (defined wantarray) {
3855 1         5 my @caller = caller;
3856 1         11 warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
3857 1         117 return;
3858             }
3859              
3860             # the user can either specify a matrix or preset
3861             # the matrix overrides the preset
3862 16 100       47 if (!exists($opts{matrix})) {
3863 14 50       31 unless (exists($opts{preset})) {
3864 0         0 $self->{ERRSTR} = "convert() needs a matrix or preset";
3865 0         0 return;
3866             }
3867             else {
3868 14 100 100     171 if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
    100 33        
    50 33        
    50 66        
    100          
    50          
    100          
    50          
3869             # convert to greyscale, keeping the alpha channel if any
3870 3 50       8 if ($self->getchannels == 3) {
    0          
3871 3         8 $matrix = [ [ 0.222, 0.707, 0.071 ] ];
3872             }
3873             elsif ($self->getchannels == 4) {
3874             # preserve the alpha channel
3875 0         0 $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
3876             [ 0, 0, 0, 1 ] ];
3877             }
3878             else {
3879             # an identity
3880 0         0 $matrix = _identity($self->getchannels);
3881             }
3882             }
3883             elsif ($opts{preset} eq 'noalpha') {
3884             # strip the alpha channel
3885 1 50 33     3 if ($self->getchannels == 2 or $self->getchannels == 4) {
3886 1         4 $matrix = _identity($self->getchannels);
3887 1         3 pop(@$matrix); # lose the alpha entry
3888             }
3889             else {
3890 0         0 $matrix = _identity($self->getchannels);
3891             }
3892             }
3893             elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
3894             # extract channel 0
3895 0         0 $matrix = [ [ 1 ] ];
3896             }
3897             elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
3898 0         0 $matrix = [ [ 0, 1 ] ];
3899             }
3900             elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
3901 3         10 $matrix = [ [ 0, 0, 1 ] ];
3902             }
3903             elsif ($opts{preset} eq 'alpha') {
3904 0 0 0     0 if ($self->getchannels == 2 or $self->getchannels == 4) {
3905 0         0 $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
3906             }
3907             else {
3908             # the alpha is just 1
3909 0         0 $matrix = [ [ (0) x $self->getchannels, 1 ] ];
3910             }
3911             }
3912             elsif ($opts{preset} eq 'rgb') {
3913 6 50       15 if ($self->getchannels == 1) {
    0          
3914 6         25 $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
3915             }
3916             elsif ($self->getchannels == 2) {
3917             # preserve the alpha channel
3918 0         0 $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
3919             }
3920             else {
3921 0         0 $matrix = _identity($self->getchannels);
3922             }
3923             }
3924             elsif ($opts{preset} eq 'addalpha') {
3925 1 50       3 if ($self->getchannels == 1) {
    50          
3926 0         0 $matrix = _identity(2);
3927             }
3928             elsif ($self->getchannels == 3) {
3929 1         3 $matrix = _identity(4);
3930             }
3931             else {
3932 0         0 $matrix = _identity($self->getchannels);
3933             }
3934             }
3935             else {
3936 0         0 $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
3937 0         0 return undef;
3938             }
3939             }
3940             }
3941             else {
3942 2         3 $matrix = $opts{matrix};
3943             }
3944              
3945 16         43 my $new = Imager->new;
3946 16         7071 $new->{IMG} = i_convert($self->{IMG}, $matrix);
3947 16 100       74 unless ($new->{IMG}) {
3948             # most likely a bad matrix
3949 1         29 i_push_error(0, "convert");
3950 1         7 $self->{ERRSTR} = _error_as_msg();
3951 1         6 return undef;
3952             }
3953 15         73 return $new;
3954             }
3955              
3956             # combine channels from multiple input images, a class method
3957             sub combine {
3958 14     14 0 2784 my ($class, %opts) = @_;
3959              
3960 14         26 my $src = delete $opts{src};
3961 14 100       35 unless ($src) {
3962 1         5 $class->_set_error("src parameter missing");
3963 1         6 return;
3964             }
3965 13         21 my @imgs;
3966 13         14 my $index = 0;
3967 13         24 for my $img (@$src) {
3968 21 100       23 unless (eval { $img->isa("Imager") }) {
  21         83  
3969 1         5 $class->_set_error("src must contain image objects");
3970 1         4 return;
3971             }
3972 20 100       38 unless ($img->_valid_image("combine")) {
3973 1         4 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
3974 1         4 return;
3975             }
3976 19         43 push @imgs, $img->{IMG};
3977             }
3978 11         12 my $result;
3979 11 100       24 if (my $channels = delete $opts{channels}) {
3980 4         751 $result = i_combine(\@imgs, $channels);
3981             }
3982             else {
3983 7         4323 $result = i_combine(\@imgs);
3984             }
3985 11 100       39 unless ($result) {
3986 4         10 $class->_set_error($class->_error_as_msg);
3987 4         20 return;
3988             }
3989              
3990 7         23 my $img = $class->new;
3991 7         12 $img->{IMG} = $result;
3992              
3993 7         24 return $img;
3994             }
3995              
3996              
3997             # general function to map an image through lookup tables
3998              
3999             sub map {
4000 6     6 0 108 my ($self, %opts) = @_;
4001 6         15 my @chlist = qw( red green blue alpha );
4002              
4003 6 100       12 $self->_valid_image("map")
4004             or return;
4005              
4006 5 100       12 if (!exists($opts{'maps'})) {
4007             # make maps from channel maps
4008 1         1 my $chnum;
4009 1         3 for $chnum (0..$#chlist) {
4010 4 100       10 if (exists $opts{$chlist[$chnum]}) {
    50          
4011 3         7 $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
4012             } elsif (exists $opts{'all'}) {
4013 0         0 $opts{'maps'}[$chnum] = $opts{'all'};
4014             }
4015             }
4016             }
4017 5 50 33     18 if ($opts{'maps'} and $self->{IMG}) {
4018 5         2484 i_map($self->{IMG}, $opts{'maps'} );
4019             }
4020 5         34 return $self;
4021             }
4022              
4023             sub difference {
4024 7     7 0 538 my ($self, %opts) = @_;
4025              
4026 7 100       13 $self->_valid_image("difference")
4027             or return;
4028              
4029 6 100       17 defined $opts{mindist} or $opts{mindist} = 0;
4030              
4031             defined $opts{other}
4032 6 50       12 or return $self->_set_error("No 'other' parameter supplied");
4033 6 100       9 unless ($opts{other}->_valid_image("difference")) {
4034 1         3 $self->_set_error($opts{other}->errstr . " (other image)");
4035 1         6 return;
4036             }
4037              
4038 5         9 my $result = Imager->new;
4039             $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
4040             $opts{mindist})
4041 5 50       2317 or return $self->_set_error($self->_error_as_msg());
4042              
4043 5         32 return $result;
4044             }
4045              
4046             sub rgb_difference {
4047 1     1 0 8 my ($self, %opts) = @_;
4048              
4049 1 50       3 $self->_valid_image("rgb_difference")
4050             or return;
4051              
4052             defined $opts{other}
4053 1 50       5 or return $self->_set_error("No 'other' parameter supplied");
4054 1 50       3 unless ($opts{other}->_valid_image("rgb_difference")) {
4055 0         0 $self->_set_error($opts{other}->errstr . " (other image)");
4056 0         0 return;
4057             }
4058              
4059 1         3 my $result = Imager->new;
4060             $result->{IMG} = i_rgbdiff_image($self->{IMG}, $opts{other}{IMG})
4061 1 50       181 or return $self->_set_error($self->_error_as_msg());
4062              
4063 1         5 return $result;
4064             }
4065              
4066             # destructive border - image is shrunk by one pixel all around
4067              
4068             sub border {
4069 0     0 0 0 my ($self,%opts)=@_;
4070 0         0 my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
4071 0         0 $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
4072             }
4073              
4074              
4075             # Get the width of an image
4076              
4077             sub getwidth {
4078 2042     2042 0 34777 my $self = shift;
4079              
4080 2042 100       2961 $self->_valid_image("getwidth")
4081             or return;
4082              
4083 2041         6696 return i_img_get_width($self->{IMG});
4084             }
4085              
4086             # Get the height of an image
4087              
4088             sub getheight {
4089 1739     1739 0 2925 my $self = shift;
4090              
4091 1739 100       2280 $self->_valid_image("getheight")
4092             or return;
4093              
4094 1738         5834 return i_img_get_height($self->{IMG});
4095             }
4096              
4097             # Get number of channels in an image
4098              
4099             sub getchannels {
4100 649     649 0 2686 my $self = shift;
4101              
4102 649 100       915 $self->_valid_image("getchannels")
4103             or return;
4104              
4105 648         2022 return i_img_getchannels($self->{IMG});
4106             }
4107              
4108             my @model_names = qw(unknown gray graya rgb rgba);
4109              
4110             sub colormodel {
4111 7     7 0 1020 my ($self, %opts) = @_;
4112              
4113 7 100       17 $self->_valid_image("colormodel")
4114             or return;
4115              
4116 6         20 my $model = i_img_color_model($self->{IMG});
4117              
4118 6 100       41 return $opts{numeric} ? $model : $model_names[$model];
4119             }
4120              
4121             sub colorchannels {
4122 6     6 0 464 my ($self) = @_;
4123              
4124 6 100       15 $self->_valid_image("colorchannels")
4125             or return;
4126              
4127 5         24 return i_img_color_channels($self->{IMG});
4128             }
4129              
4130             sub alphachannel {
4131 6     6 0 15 my ($self) = @_;
4132              
4133 6 100       14 $self->_valid_image("alphachannel")
4134             or return;
4135              
4136 5         29 return scalar(i_img_alpha_channel($self->{IMG}));
4137             }
4138              
4139             # Get channel mask
4140              
4141             sub getmask {
4142 2     2 0 7 my $self = shift;
4143              
4144 2 100       6 $self->_valid_image("getmask")
4145             or return;
4146              
4147 1         5 return i_img_getmask($self->{IMG});
4148             }
4149              
4150             # Set channel mask
4151              
4152             sub setmask {
4153 28     28 0 1410 my $self = shift;
4154 28         73 my %opts = @_;
4155              
4156 28         1652 warnings::warnif("Imager::channelmask", "setmask: image channel masks are deprecated");
4157              
4158 28 100       120 $self->_valid_image("setmask")
4159             or return;
4160              
4161 27 50       60 unless (defined $opts{mask}) {
4162 0         0 $self->_set_error("mask parameter required");
4163 0         0 return;
4164             }
4165              
4166 27         90 i_img_setmask( $self->{IMG} , $opts{mask} );
4167              
4168 27         119 1;
4169             }
4170              
4171             # Get number of colors in an image
4172              
4173             sub getcolorcount {
4174 10     10 0 40 my $self=shift;
4175 10         25 my %opts=('maxcolors'=>2**30,@_);
4176              
4177 10 100       31 $self->_valid_image("getcolorcount")
4178             or return;
4179              
4180 9         62769 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
4181 9 100       108 return ($rc==-1? undef : $rc);
4182             }
4183              
4184             # Returns a reference to a hash. The keys are colour named (packed) and the
4185             # values are the number of pixels in this colour.
4186             sub getcolorusagehash {
4187 4     4 0 939 my $self = shift;
4188              
4189 4 100       10 $self->_valid_image("getcolorusagehash")
4190             or return;
4191              
4192 3         9 my %opts = ( maxcolors => 2**30, @_ );
4193 3         5 my $max_colors = $opts{maxcolors};
4194 3 50 33     11 unless (defined $max_colors && $max_colors > 0) {
4195 0         0 $self->_set_error('maxcolors must be a positive integer');
4196 0         0 return;
4197             }
4198              
4199 3         8 my $channels= $self->getchannels;
4200             # We don't want to look at the alpha channel, because some gifs using it
4201             # doesn't define it for every colour (but only for some)
4202 3 50 33     11 $channels -= 1 if $channels == 2 or $channels == 4;
4203 3         4 my %color_use;
4204 3         7 my $height = $self->getheight;
4205 3         7 for my $y (0 .. $height - 1) {
4206 126         400 my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
4207 126         386 while (length $colors) {
4208 6300         8324 $color_use{ substr($colors, 0, $channels, '') }++;
4209             }
4210 126 100       269 keys %color_use > $max_colors
4211             and return;
4212             }
4213 2         10 return \%color_use;
4214             }
4215              
4216             # This will return a ordered array of the colour usage. Kind of the sorted
4217             # version of the values of the hash returned by getcolorusagehash.
4218             # You might want to add safety checks and change the names, etc...
4219             sub getcolorusage {
4220 6     6 0 1827 my $self = shift;
4221              
4222 6 100       13 $self->_valid_image("getcolorusage")
4223             or return;
4224              
4225 5         13 my %opts = ( maxcolors => 2**30, @_ );
4226 5         7 my $max_colors = $opts{maxcolors};
4227 5 50 33     18 unless (defined $max_colors && $max_colors > 0) {
4228 0         0 $self->_set_error('maxcolors must be a positive integer');
4229 0         0 return;
4230             }
4231              
4232 5         5302 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
4233             }
4234              
4235             # draw string to an image
4236              
4237             sub string {
4238 1     1 0 4 my $self = shift;
4239              
4240 1 50       3 $self->_valid_image("string")
4241             or return;
4242              
4243 0         0 my %input=('x'=>0, 'y'=>0, @_);
4244 0 0       0 defined($input{string}) or $input{string} = $input{text};
4245              
4246 0 0       0 unless(defined $input{string}) {
4247 0         0 $self->{ERRSTR}="missing required parameter 'string'";
4248 0         0 return;
4249             }
4250              
4251 0 0       0 unless($input{font}) {
4252 0         0 $self->{ERRSTR}="missing required parameter 'font'";
4253 0         0 return;
4254             }
4255              
4256 0 0       0 unless ($input{font}->draw(image=>$self, %input)) {
4257 0         0 return;
4258             }
4259              
4260 0         0 return $self;
4261             }
4262              
4263             sub align_string {
4264 1     1 0 2 my $self = shift;
4265              
4266 1         2 my $img;
4267 1 50       4 if (ref $self) {
4268 1 50       2 $self->_valid_image("align_string")
4269             or return;
4270              
4271 0         0 $img = $self;
4272             }
4273             else {
4274 0         0 $img = undef;
4275             }
4276              
4277 0         0 my %input=('x'=>0, 'y'=>0, @_);
4278             defined $input{string}
4279 0 0       0 or $input{string} = $input{text};
4280              
4281 0 0       0 unless(exists $input{string}) {
4282 0         0 $self->_set_error("missing required parameter 'string'");
4283 0         0 return;
4284             }
4285              
4286 0 0       0 unless($input{font}) {
4287 0         0 $self->_set_error("missing required parameter 'font'");
4288 0         0 return;
4289             }
4290              
4291 0         0 my @result;
4292 0 0       0 unless (@result = $input{font}->align(image=>$img, %input)) {
4293 0         0 return;
4294             }
4295              
4296 0 0       0 return wantarray ? @result : $result[0];
4297             }
4298              
4299             my @file_limit_names = qw/width height bytes/;
4300              
4301             sub set_file_limits {
4302 25     25 0 516 shift;
4303              
4304 25         90 my %opts = @_;
4305 25         76 my %values;
4306            
4307 25 100       69 if ($opts{reset}) {
4308 23         98 @values{@file_limit_names} = (0) x @file_limit_names;
4309             }
4310             else {
4311 2         38 @values{@file_limit_names} = i_get_image_file_limits();
4312             }
4313              
4314 25         69 for my $key (keys %values) {
4315 75 100       163 defined $opts{$key} and $values{$key} = $opts{$key};
4316             }
4317              
4318 25         234 i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
4319             }
4320              
4321             sub get_file_limits {
4322 5     5 0 79192 i_get_image_file_limits();
4323             }
4324              
4325             my @check_args = qw(width height channels sample_size);
4326              
4327             sub check_file_limits {
4328 11     11 0 34 my $class = shift;
4329              
4330 11         98 my %opts =
4331             (
4332             channels => 3,
4333             sample_size => 1,
4334             @_,
4335             );
4336              
4337 11 100 100     87 if ($opts{sample_size} && $opts{sample_size} eq 'float') {
4338 1         8 $opts{sample_size} = length(pack("d", 0));
4339             }
4340              
4341 11         34 for my $name (@check_args) {
4342 38 100       120 unless (defined $opts{$name}) {
4343 1         6 $class->_set_error("check_file_limits: $name must be defined");
4344 1         5 return;
4345             }
4346 37 100       96 unless ($opts{$name} == int($opts{$name})) {
4347 1         8 $class->_set_error("check_file_limits: $name must be a positive integer");
4348 1         6 return;
4349             }
4350             }
4351              
4352 9         189 my $result = i_int_check_image_file_limits(@opts{@check_args});
4353 9 100       37 unless ($result) {
4354 6         56 $class->_set_error($class->_error_as_msg());
4355             }
4356              
4357 9         122 return $result;
4358             }
4359              
4360             # Shortcuts that can be exported
4361              
4362 277     277 0 98658 sub newcolor { Imager::Color->new(@_); }
4363 0     0 0 0 sub newfont { Imager::Font->new(@_); }
4364             sub NCF {
4365 33     33 0 12312 require Imager::Color::Float;
4366 33         120 return Imager::Color::Float->new(@_);
4367             }
4368              
4369             *NC=*newcolour=*newcolor;
4370             *NF=*newfont;
4371              
4372             *open=\&read;
4373             *circle=\&arc;
4374              
4375              
4376             #### Utility routines
4377              
4378             sub errstr {
4379 331 100   331 1 9238 ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
4380             }
4381              
4382             sub _set_error {
4383 203     203   388 my ($self, $msg) = @_;
4384              
4385 203 100       398 if (ref $self) {
4386 169         285 $self->{ERRSTR} = $msg;
4387             }
4388             else {
4389 34         64 $ERRSTR = $msg;
4390             }
4391 203         446 return;
4392             }
4393              
4394             # Default guess for the type of an image from extension
4395              
4396             my @simple_types = qw(png tga gif raw ico cur xpm mng jng ilbm pcx psd eps webp xwd xpm dng ras qoi jxl);
4397              
4398             my %ext_types =
4399             (
4400             ( map { $_ => $_ } @simple_types ),
4401             tiff => "tiff",
4402             tif => "tiff",
4403             pbm => "pnm",
4404             pgm => "pnm",
4405             ppm => "pnm",
4406             pnm => "pnm", # technically wrong, but historically it works in Imager
4407             jpeg => "jpeg",
4408             jpg => "jpeg",
4409             bmp => "bmp",
4410             dib => "bmp",
4411             rgb => "sgi",
4412             bw => "sgi",
4413             sgi => "sgi",
4414             fit => "fits",
4415             fits => "fits",
4416             rle => "utah",
4417             avifs => "avif", # AVIF image sequence
4418             avif => "avif",
4419             );
4420              
4421             sub def_guess_type {
4422 121     121 0 8729 my $name=lc(shift);
4423              
4424 121 50       848 my ($ext) = $name =~ /\.([^.]+)$/
4425             or return;
4426              
4427 121         332 my $type = $ext_types{$ext};
4428 121 100       250 unless ($type) {
4429 2         5 $type = $ext_types{lc $ext};
4430             }
4431              
4432 121 50 66     373 if (!defined $type && $ext =~ /\A[a-zA-Z0-9_]{2,}\z/) {
4433             # maybe a reasonable assumption
4434 0         0 $type = lc $ext;
4435             }
4436              
4437 121         257 return $type;
4438             }
4439              
4440             sub add_type_extensions {
4441 1     1 0 556 my ($class, $type, @exts) = @_;
4442              
4443 1         7 for my $ext (@exts) {
4444 1 50       9 exists $ext_types{lc $ext} or $ext_types{lc $ext} = lc $type;
4445             }
4446 1         3 1;
4447             }
4448              
4449             sub combines {
4450 1     1 0 10 return @combine_types;
4451             }
4452              
4453             # get the minimum of a list
4454              
4455             sub _min {
4456 1389     1389   1461 my $mx=shift;
4457 1389 50       1874 for(@_) { if ($_<$mx) { $mx=$_; }}
  1389         2291  
  0         0  
4458 1389         1843 return $mx;
4459             }
4460              
4461             # get the maximum of a list
4462              
4463             sub _max {
4464 1139     1139   1491 my $mx=shift;
4465 1139 100       1298 for(@_) { if ($_>$mx) { $mx=$_; }}
  1139         1551  
  1120         1241  
4466 1139         1204 return $mx;
4467             }
4468              
4469             # string stuff for iptc headers
4470              
4471             sub _clean {
4472 0     0   0 my($str)=$_[0];
4473 0         0 $str = substr($str,3);
4474 0         0 $str =~ s/[\n\r]//g;
4475 0         0 $str =~ s/\s+/ /g;
4476 0         0 $str =~ s/^\s//;
4477 0         0 $str =~ s/\s$//;
4478 0         0 return $str;
4479             }
4480              
4481             # A little hack to parse iptc headers.
4482              
4483             sub parseiptc {
4484 0     0 0 0 my $self=shift;
4485 0         0 my(@sar,$item,@ar);
4486 0         0 my($caption,$photogr,$headln,$credit);
4487              
4488 0         0 my $str=$self->{IPTCRAW};
4489              
4490 0 0       0 defined $str
4491             or return;
4492              
4493 0         0 @ar=split(/8BIM/,$str);
4494              
4495 0         0 my $i=0;
4496 0         0 foreach (@ar) {
4497 0 0       0 if (/^\004\004/) {
4498 0         0 @sar=split(/\034\002/);
4499 0         0 foreach $item (@sar) {
4500 0 0       0 if ($item =~ m/^x/) {
4501 0         0 $caption = _clean($item);
4502 0         0 $i++;
4503             }
4504 0 0       0 if ($item =~ m/^P/) {
4505 0         0 $photogr = _clean($item);
4506 0         0 $i++;
4507             }
4508 0 0       0 if ($item =~ m/^i/) {
4509 0         0 $headln = _clean($item);
4510 0         0 $i++;
4511             }
4512 0 0       0 if ($item =~ m/^n/) {
4513 0         0 $credit = _clean($item);
4514 0         0 $i++;
4515             }
4516             }
4517             }
4518             }
4519 0         0 return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
4520             }
4521              
4522             sub Inline {
4523             # Inline added a new argument at the beginning
4524 0     0 0 0 my $lang = $_[-1];
4525              
4526 0 0 0     0 $lang eq 'C' || $lang eq 'CPP'
4527             or die "Only C or C++ (CPP) language supported";
4528              
4529 0         0 require Imager::ExtUtils;
4530 0         0 return Imager::ExtUtils->inline_config;
4531             }
4532              
4533             # threads shouldn't try to close raw Imager objects
4534 0     0   0 sub Imager::ImgRaw::CLONE_SKIP { 1 }
4535              
4536             sub preload {
4537             # this serves two purposes:
4538             # - a class method to load the file support modules included with Imager
4539             # (or were included, once the library dependent modules are split out)
4540             # - something for Module::ScanDeps to analyze
4541             # https://rt.cpan.org/Ticket/Display.html?id=6566
4542 1     1 0 72 local $@;
4543 1         5 local @INC = @INC;
4544 1 50       5 pop @INC if $INC[-1] eq '.';
4545 1         3 eval { require Imager::File::GIF };
  1         133  
4546 1         3 eval { require Imager::File::JPEG };
  1         90  
4547 1         3 eval { require Imager::File::PNG };
  1         88  
4548 1         4 eval { require Imager::File::SGI };
  1         331  
4549 1         4 eval { require Imager::File::TIFF };
  1         98  
4550 1         3 eval { require Imager::File::ICO };
  1         314  
4551 1         3 eval { require Imager::Font::W32 };
  1         111  
4552 1         5 eval { require Imager::Font::FT2 };
  1         89  
4553 1         4 eval { require Imager::Font::T1 };
  1         87  
4554 1         8 eval { require Imager::Color::Table };
  1         376  
4555              
4556 1         7 1;
4557             }
4558              
4559             package Imager::IO;
4560 58     58   27632 use IO::Seekable;
  58         346168  
  58         11794  
4561              
4562             sub new_fh {
4563 19     19   5634 my ($class, $fh) = @_;
4564              
4565 19 100       47 if (tied(*$fh)) {
4566             return $class->new_cb
4567             (
4568             sub {
4569 2     2   1671 local $\;
4570              
4571 2         9 return print $fh $_[0];
4572             },
4573             sub {
4574 2     2   439 my $tmp;
4575 2         9 my $count = CORE::read $fh, $tmp, $_[1];
4576 2 50       30 defined $count
4577             or return undef;
4578 2 100       10 $count
4579             or return "";
4580 1         3 return $tmp;
4581             },
4582             sub {
4583 2 50 33 2   31 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4584 2 50       9 unless (CORE::seek $fh, $_[0], $_[1]) {
4585 0         0 return -1;
4586             }
4587             }
4588              
4589 2         27 return tell $fh;
4590             },
4591             undef,
4592 1         128 );
4593             }
4594             else {
4595 18         1888 return $class->_new_perlio($fh);
4596             }
4597             }
4598              
4599             # backward compatibility for %formats
4600             package Imager::FORMATS;
4601 58     58   420 use strict;
  58         152  
  58         1393  
4602 58     58   292 use constant IX_FORMATS => 0;
  58         99  
  58         5287  
4603 58     58   337 use constant IX_LIST => 1;
  58         124  
  58         2929  
4604 58     58   329 use constant IX_INDEX => 2;
  58         103  
  58         2573  
4605 58     58   319 use constant IX_CLASSES => 3;
  58         135  
  58         40563  
4606              
4607             sub TIEHASH {
4608 58     58   149 my ($class, $formats, $classes) = @_;
4609              
4610 58         245 return bless [ $formats, [ ], 0, $classes ], $class;
4611             }
4612              
4613             sub _check {
4614 75     75   129 my ($self, $key) = @_;
4615              
4616 75         300 (my $file = $self->[IX_CLASSES]{$key} . ".pm") =~ s(::)(/)g;
4617 75         117 my $value;
4618             my $error;
4619 75         145 my $loaded = Imager::_load_file($file, \$error);
4620 75 50       139 if ($loaded) {
4621 0         0 $value = 1;
4622             }
4623             else {
4624 75 50       207 if ($error =~ /^Can't locate /) {
4625 75         142 $error = "Can't locate $file";
4626             }
4627 75         155 $reader_load_errors{$key} = $writer_load_errors{$key} = $error;
4628 75         128 $value = undef;
4629             }
4630 75         164 $self->[IX_FORMATS]{$key} = $value;
4631              
4632 75         204 return $value;
4633             }
4634              
4635             sub FETCH {
4636 19     19   384 my ($self, $key) = @_;
4637              
4638 19 100       122 exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key};
4639              
4640 9 100       39 $self->[IX_CLASSES]{$key} or return undef;
4641              
4642 5         18 return $self->_check($key);
4643             }
4644              
4645             sub STORE {
4646 0     0   0 die "%Imager::formats is not user monifiable";
4647             }
4648              
4649             sub DELETE {
4650 0     0   0 die "%Imager::formats is not user monifiable";
4651             }
4652              
4653             sub CLEAR {
4654 0     0   0 die "%Imager::formats is not user monifiable";
4655             }
4656              
4657             sub EXISTS {
4658 0     0   0 my ($self, $key) = @_;
4659              
4660 0 0       0 if (exists $self->[IX_FORMATS]{$key}) {
4661 0 0       0 my $value = $self->[IX_FORMATS]{$key}
4662             or return;
4663 0         0 return 1;
4664             }
4665              
4666 0 0       0 $self->_check($key) or return 1==0;
4667              
4668 0         0 return 1==1;
4669             }
4670              
4671             sub FIRSTKEY {
4672 33     33   103 my ($self) = @_;
4673              
4674 33 100       51 unless (@{$self->[IX_LIST]}) {
  33         134  
4675             # full populate it
4676 10         34 @{$self->[IX_LIST]} = grep $self->[IX_FORMATS]{$_},
4677 10         21 keys %{$self->[IX_FORMATS]};
  10         76  
4678              
4679 10         20 for my $key (keys %{$self->[IX_CLASSES]}) {
  10         69  
4680 70 50       127 $self->[IX_FORMATS]{$key} and next;
4681             $self->_check($key)
4682 70 50       141 and push @{$self->[IX_LIST]}, $key;
  0         0  
4683             }
4684             }
4685              
4686 33 50       52 @{$self->[IX_LIST]} or return;
  33         92  
4687 33         91 $self->[IX_INDEX] = 1;
4688 33         132 return $self->[IX_LIST][0];
4689             }
4690              
4691             sub NEXTKEY {
4692 165     165   218 my ($self) = @_;
4693              
4694 165 100       174 $self->[IX_INDEX] < @{$self->[IX_LIST]}
  165         377  
4695             or return;
4696              
4697 132         286 return $self->[IX_LIST][$self->[IX_INDEX]++];
4698             }
4699              
4700             sub SCALAR {
4701 0     0     my ($self) = @_;
4702              
4703 0           return scalar @{$self->[IX_LIST]};
  0            
4704             }
4705              
4706             1;
4707             __END__