File Coverage

blib/lib/Imager.pm
Criterion Covered Total %
statement 1683 2250 74.8
branch 980 1410 69.5
condition 196 350 56.0
subroutine 142 160 88.7
pod 1 105 0.9
total 3002 4275 70.2


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