Almost-minimal filesystem based blog.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4160 lines
100 KiB

  1. package Imager;
  2. use strict;
  3. use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR $fontstate %OPCODES $I2P $FORMATGUESS $warn_obsolete);
  4. use IO::File;
  5. use Imager::Color;
  6. use Imager::Font;
  7. @EXPORT_OK = qw(
  8. init
  9. init_log
  10. DSO_open
  11. DSO_close
  12. DSO_funclist
  13. DSO_call
  14. load_plugin
  15. unload_plugin
  16. i_list_formats
  17. i_has_format
  18. i_color_new
  19. i_color_set
  20. i_color_info
  21. i_img_empty
  22. i_img_empty_ch
  23. i_img_exorcise
  24. i_img_destroy
  25. i_img_info
  26. i_img_setmask
  27. i_img_getmask
  28. i_line
  29. i_line_aa
  30. i_box
  31. i_box_filled
  32. i_arc
  33. i_circle_aa
  34. i_bezier_multi
  35. i_poly_aa
  36. i_poly_aa_cfill
  37. i_copyto
  38. i_rubthru
  39. i_scaleaxis
  40. i_scale_nn
  41. i_haar
  42. i_count_colors
  43. i_gaussian
  44. i_conv
  45. i_convert
  46. i_map
  47. i_img_diff
  48. i_init_fonts
  49. i_t1_new
  50. i_t1_destroy
  51. i_t1_set_aa
  52. i_t1_cp
  53. i_t1_text
  54. i_t1_bbox
  55. i_tt_set_aa
  56. i_tt_cp
  57. i_tt_text
  58. i_tt_bbox
  59. i_readjpeg_wiol
  60. i_writejpeg_wiol
  61. i_readtiff_wiol
  62. i_writetiff_wiol
  63. i_writetiff_wiol_faxable
  64. i_readpng_wiol
  65. i_writepng_wiol
  66. i_readgif
  67. i_readgif_wiol
  68. i_readgif_callback
  69. i_writegif
  70. i_writegifmc
  71. i_writegif_gen
  72. i_writegif_callback
  73. i_readpnm_wiol
  74. i_writeppm_wiol
  75. i_readraw_wiol
  76. i_writeraw_wiol
  77. i_contrast
  78. i_hardinvert
  79. i_noise
  80. i_bumpmap
  81. i_postlevels
  82. i_mosaic
  83. i_watermark
  84. malloc_state
  85. list_formats
  86. i_gifquant
  87. newfont
  88. newcolor
  89. newcolour
  90. NC
  91. NF
  92. );
  93. @EXPORT=qw(
  94. init_log
  95. i_list_formats
  96. i_has_format
  97. malloc_state
  98. i_color_new
  99. i_img_empty
  100. i_img_empty_ch
  101. );
  102. %EXPORT_TAGS=
  103. (handy => [qw(
  104. newfont
  105. newcolor
  106. NF
  107. NC
  108. )],
  109. all => [@EXPORT_OK],
  110. default => [qw(
  111. load_plugin
  112. unload_plugin
  113. )]);
  114. # registered file readers
  115. my %readers;
  116. # registered file writers
  117. my %writers;
  118. # modules we attempted to autoload
  119. my %attempted_to_load;
  120. BEGIN {
  121. require Exporter;
  122. @ISA = qw(Exporter);
  123. $VERSION = '0.60';
  124. eval {
  125. require XSLoader;
  126. XSLoader::load(Imager => $VERSION);
  127. 1;
  128. } or do {
  129. require DynaLoader;
  130. push @ISA, 'DynaLoader';
  131. bootstrap Imager $VERSION;
  132. }
  133. }
  134. BEGIN {
  135. i_init_fonts(); # Initialize font engines
  136. Imager::Font::__init();
  137. for(i_list_formats()) { $formats{$_}++; }
  138. if ($formats{'t1'}) {
  139. i_t1_set_aa(1);
  140. }
  141. if (!$formats{'t1'} and !$formats{'tt'}
  142. && !$formats{'ft2'} && !$formats{'w32'}) {
  143. $fontstate='no font support';
  144. }
  145. %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]);
  146. $DEBUG=0;
  147. # the members of the subhashes under %filters are:
  148. # callseq - a list of the parameters to the underlying filter in the
  149. # order they are passed
  150. # callsub - a code ref that takes a named parameter list and calls the
  151. # underlying filter
  152. # defaults - a hash of default values
  153. # names - defines names for value of given parameters so if the names
  154. # field is foo=> { bar=>1 }, and the user supplies "bar" as the
  155. # foo parameter, the filter will receive 1 for the foo
  156. # parameter
  157. $filters{contrast}={
  158. callseq => ['image','intensity'],
  159. callsub => sub { my %hsh=@_; i_contrast($hsh{image},$hsh{intensity}); }
  160. };
  161. $filters{noise} ={
  162. callseq => ['image', 'amount', 'subtype'],
  163. defaults => { amount=>3,subtype=>0 },
  164. callsub => sub { my %hsh=@_; i_noise($hsh{image},$hsh{amount},$hsh{subtype}); }
  165. };
  166. $filters{hardinvert} ={
  167. callseq => ['image'],
  168. defaults => { },
  169. callsub => sub { my %hsh=@_; i_hardinvert($hsh{image}); }
  170. };
  171. $filters{autolevels} ={
  172. callseq => ['image','lsat','usat','skew'],
  173. defaults => { lsat=>0.1,usat=>0.1,skew=>0.0 },
  174. callsub => sub { my %hsh=@_; i_autolevels($hsh{image},$hsh{lsat},$hsh{usat},$hsh{skew}); }
  175. };
  176. $filters{turbnoise} ={
  177. callseq => ['image'],
  178. defaults => { xo=>0.0,yo=>0.0,scale=>10.0 },
  179. callsub => sub { my %hsh=@_; i_turbnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{scale}); }
  180. };
  181. $filters{radnoise} ={
  182. callseq => ['image'],
  183. defaults => { xo=>100,yo=>100,ascale=>17.0,rscale=>0.02 },
  184. callsub => sub { my %hsh=@_; i_radnoise($hsh{image},$hsh{xo},$hsh{yo},$hsh{rscale},$hsh{ascale}); }
  185. };
  186. $filters{conv} ={
  187. callseq => ['image', 'coef'],
  188. defaults => { },
  189. callsub => sub { my %hsh=@_; i_conv($hsh{image},$hsh{coef}); }
  190. };
  191. $filters{gradgen} =
  192. {
  193. callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
  194. defaults => { dist => 0 },
  195. callsub =>
  196. sub {
  197. my %hsh=@_;
  198. my @colors = @{$hsh{colors}};
  199. $_ = _color($_)
  200. for @colors;
  201. i_gradgen($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors, $hsh{dist});
  202. }
  203. };
  204. $filters{nearest_color} =
  205. {
  206. callseq => ['image', 'xo', 'yo', 'colors', 'dist'],
  207. defaults => { },
  208. callsub =>
  209. sub {
  210. my %hsh=@_;
  211. # make sure the segments are specified with colors
  212. my @colors;
  213. for my $color (@{$hsh{colors}}) {
  214. my $new_color = _color($color)
  215. or die $Imager::ERRSTR."\n";
  216. push @colors, $new_color;
  217. }
  218. i_nearest_color($hsh{image}, $hsh{xo}, $hsh{yo}, \@colors,
  219. $hsh{dist})
  220. or die Imager->_error_as_msg() . "\n";
  221. },
  222. };
  223. $filters{gaussian} = {
  224. callseq => [ 'image', 'stddev' ],
  225. defaults => { },
  226. callsub => sub { my %hsh = @_; i_gaussian($hsh{image}, $hsh{stddev}); },
  227. };
  228. $filters{mosaic} =
  229. {
  230. callseq => [ qw(image size) ],
  231. defaults => { size => 20 },
  232. callsub => sub { my %hsh = @_; i_mosaic($hsh{image}, $hsh{size}) },
  233. };
  234. $filters{bumpmap} =
  235. {
  236. callseq => [ qw(image bump elevation lightx lighty st) ],
  237. defaults => { elevation=>0, st=> 2 },
  238. callsub => sub {
  239. my %hsh = @_;
  240. i_bumpmap($hsh{image}, $hsh{bump}{IMG}, $hsh{elevation},
  241. $hsh{lightx}, $hsh{lighty}, $hsh{st});
  242. },
  243. };
  244. $filters{bumpmap_complex} =
  245. {
  246. callseq => [ qw(image bump channel tx ty Lx Ly Lz cd cs n Ia Il Is) ],
  247. defaults => {
  248. channel => 0,
  249. tx => 0,
  250. ty => 0,
  251. Lx => 0.2,
  252. Ly => 0.4,
  253. Lz => -1.0,
  254. cd => 1.0,
  255. cs => 40,
  256. n => 1.3,
  257. Ia => Imager::Color->new(rgb=>[0,0,0]),
  258. Il => Imager::Color->new(rgb=>[255,255,255]),
  259. Is => Imager::Color->new(rgb=>[255,255,255]),
  260. },
  261. callsub => sub {
  262. my %hsh = @_;
  263. i_bumpmap_complex($hsh{image}, $hsh{bump}{IMG}, $hsh{channel},
  264. $hsh{tx}, $hsh{ty}, $hsh{Lx}, $hsh{Ly}, $hsh{Lz},
  265. $hsh{cd}, $hsh{cs}, $hsh{n}, $hsh{Ia}, $hsh{Il},
  266. $hsh{Is});
  267. },
  268. };
  269. $filters{postlevels} =
  270. {
  271. callseq => [ qw(image levels) ],
  272. defaults => { levels => 10 },
  273. callsub => sub { my %hsh = @_; i_postlevels($hsh{image}, $hsh{levels}); },
  274. };
  275. $filters{watermark} =
  276. {
  277. callseq => [ qw(image wmark tx ty pixdiff) ],
  278. defaults => { pixdiff=>10, tx=>0, ty=>0 },
  279. callsub =>
  280. sub {
  281. my %hsh = @_;
  282. i_watermark($hsh{image}, $hsh{wmark}{IMG}, $hsh{tx}, $hsh{ty},
  283. $hsh{pixdiff});
  284. },
  285. };
  286. $filters{fountain} =
  287. {
  288. callseq => [ qw(image xa ya xb yb ftype repeat combine super_sample ssample_param segments) ],
  289. names => {
  290. ftype => { linear => 0,
  291. bilinear => 1,
  292. radial => 2,
  293. radial_square => 3,
  294. revolution => 4,
  295. conical => 5 },
  296. repeat => { none => 0,
  297. sawtooth => 1,
  298. triangle => 2,
  299. saw_both => 3,
  300. tri_both => 4,
  301. },
  302. super_sample => {
  303. none => 0,
  304. grid => 1,
  305. random => 2,
  306. circle => 3,
  307. },
  308. combine => {
  309. none => 0,
  310. normal => 1,
  311. multiply => 2, mult => 2,
  312. dissolve => 3,
  313. add => 4,
  314. subtract => 5, 'sub' => 5,
  315. diff => 6,
  316. lighten => 7,
  317. darken => 8,
  318. hue => 9,
  319. sat => 10,
  320. value => 11,
  321. color => 12,
  322. },
  323. },
  324. defaults => { ftype => 0, repeat => 0, combine => 0,
  325. super_sample => 0, ssample_param => 4,
  326. segments=>[
  327. [ 0, 0.5, 1,
  328. Imager::Color->new(0,0,0),
  329. Imager::Color->new(255, 255, 255),
  330. 0, 0,
  331. ],
  332. ],
  333. },
  334. callsub =>
  335. sub {
  336. my %hsh = @_;
  337. # make sure the segments are specified with colors
  338. my @segments;
  339. for my $segment (@{$hsh{segments}}) {
  340. my @new_segment = @$segment;
  341. $_ = _color($_) or die $Imager::ERRSTR."\n" for @new_segment[3,4];
  342. push @segments, \@new_segment;
  343. }
  344. i_fountain($hsh{image}, $hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb},
  345. $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample},
  346. $hsh{ssample_param}, \@segments)
  347. or die Imager->_error_as_msg() . "\n";
  348. },
  349. };
  350. $filters{unsharpmask} =
  351. {
  352. callseq => [ qw(image stddev scale) ],
  353. defaults => { stddev=>2.0, scale=>1.0 },
  354. callsub =>
  355. sub {
  356. my %hsh = @_;
  357. i_unsharp_mask($hsh{image}, $hsh{stddev}, $hsh{scale});
  358. },
  359. };
  360. $FORMATGUESS=\&def_guess_type;
  361. $warn_obsolete = 1;
  362. }
  363. #
  364. # Non methods
  365. #
  366. # initlize Imager
  367. # NOTE: this might be moved to an import override later on
  368. #sub import {
  369. # my $pack = shift;
  370. # (look through @_ for special tags, process, and remove them);
  371. # use Data::Dumper;
  372. # print Dumper($pack);
  373. # print Dumper(@_);
  374. #}
  375. sub init_log {
  376. i_init_log($_[0],$_[1]);
  377. i_log_entry("Imager $VERSION starting\n", 1);
  378. }
  379. sub init {
  380. my %parms=(loglevel=>1,@_);
  381. if ($parms{'log'}) {
  382. init_log($parms{'log'},$parms{'loglevel'});
  383. }
  384. if (exists $parms{'warn_obsolete'}) {
  385. $warn_obsolete = $parms{'warn_obsolete'};
  386. }
  387. # if ($parms{T1LIB_CONFIG}) { $ENV{T1LIB_CONFIG}=$parms{T1LIB_CONFIG}; }
  388. # if ( $ENV{T1LIB_CONFIG} and ( $fontstate eq 'missing conf' )) {
  389. # i_init_fonts();
  390. # $fontstate='ok';
  391. # }
  392. if (exists $parms{'t1log'}) {
  393. i_init_fonts($parms{'t1log'});
  394. }
  395. }
  396. END {
  397. if ($DEBUG) {
  398. print "shutdown code\n";
  399. # for(keys %instances) { $instances{$_}->DESTROY(); }
  400. malloc_state(); # how do decide if this should be used? -- store something from the import
  401. print "Imager exiting\n";
  402. }
  403. }
  404. # Load a filter plugin
  405. sub load_plugin {
  406. my ($filename)=@_;
  407. my $i;
  408. my ($DSO_handle,$str)=DSO_open($filename);
  409. if (!defined($DSO_handle)) { $Imager::ERRSTR="Couldn't load plugin '$filename'\n"; return undef; }
  410. my %funcs=DSO_funclist($DSO_handle);
  411. if ($DEBUG) { print "loading module $filename\n"; $i=0; for(keys %funcs) { printf(" %2d: %s\n",$i++,$_); } }
  412. $i=0;
  413. for(keys %funcs) { if ($filters{$_}) { $ERRSTR="filter '$_' already exists\n"; DSO_close($DSO_handle); return undef; } }
  414. $DSOs{$filename}=[$DSO_handle,\%funcs];
  415. for(keys %funcs) {
  416. my $evstr="\$filters{'".$_."'}={".$funcs{$_}.'};';
  417. $DEBUG && print "eval string:\n",$evstr,"\n";
  418. eval $evstr;
  419. print $@ if $@;
  420. }
  421. return 1;
  422. }
  423. # Unload a plugin
  424. sub unload_plugin {
  425. my ($filename)=@_;
  426. if (!$DSOs{$filename}) { $ERRSTR="plugin '$filename' not loaded."; return undef; }
  427. my ($DSO_handle,$funcref)=@{$DSOs{$filename}};
  428. for(keys %{$funcref}) {
  429. delete $filters{$_};
  430. $DEBUG && print "unloading: $_\n";
  431. }
  432. my $rc=DSO_close($DSO_handle);
  433. if (!defined($rc)) { $ERRSTR="unable to unload plugin '$filename'."; return undef; }
  434. return 1;
  435. }
  436. # take the results of i_error() and make a message out of it
  437. sub _error_as_msg {
  438. return join(": ", map $_->[0], i_errors());
  439. }
  440. # this function tries to DWIM for color parameters
  441. # color objects are used as is
  442. # simple scalars are simply treated as single parameters to Imager::Color->new
  443. # hashrefs are treated as named argument lists to Imager::Color->new
  444. # arrayrefs are treated as list arguments to Imager::Color->new iff any
  445. # parameter is > 1
  446. # other arrayrefs are treated as list arguments to Imager::Color::Float
  447. sub _color {
  448. my $arg = shift;
  449. # perl 5.6.0 seems to do weird things to $arg if we don't make an
  450. # explicitly stringified copy
  451. # I vaguely remember a bug on this on p5p, but couldn't find it
  452. # through bugs.perl.org (I had trouble getting it to find any bugs)
  453. my $copy = $arg . "";
  454. my $result;
  455. if (ref $arg) {
  456. if (UNIVERSAL::isa($arg, "Imager::Color")
  457. || UNIVERSAL::isa($arg, "Imager::Color::Float")) {
  458. $result = $arg;
  459. }
  460. else {
  461. if ($copy =~ /^HASH\(/) {
  462. $result = Imager::Color->new(%$arg);
  463. }
  464. elsif ($copy =~ /^ARRAY\(/) {
  465. $result = Imager::Color->new(@$arg);
  466. }
  467. else {
  468. $Imager::ERRSTR = "Not a color";
  469. }
  470. }
  471. }
  472. else {
  473. # assume Imager::Color::new knows how to handle it
  474. $result = Imager::Color->new($arg);
  475. }
  476. return $result;
  477. }
  478. sub _valid_image {
  479. my ($self) = @_;
  480. $self->{IMG} and return 1;
  481. $self->_set_error('empty input image');
  482. return;
  483. }
  484. #
  485. # Methods to be called on objects.
  486. #
  487. # Create a new Imager object takes very few parameters.
  488. # usually you call this method and then call open from
  489. # the resulting object
  490. sub new {
  491. my $class = shift;
  492. my $self ={};
  493. my %hsh=@_;
  494. bless $self,$class;
  495. $self->{IMG}=undef; # Just to indicate what exists
  496. $self->{ERRSTR}=undef; #
  497. $self->{DEBUG}=$DEBUG;
  498. $self->{DEBUG} && print "Initialized Imager\n";
  499. if (defined $hsh{xsize} && defined $hsh{ysize}) {
  500. unless ($self->img_set(%hsh)) {
  501. $Imager::ERRSTR = $self->{ERRSTR};
  502. return;
  503. }
  504. }
  505. return $self;
  506. }
  507. # Copy an entire image with no changes
  508. # - if an image has magic the copy of it will not be magical
  509. sub copy {
  510. my $self = shift;
  511. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  512. unless (defined wantarray) {
  513. my @caller = caller;
  514. warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
  515. return;
  516. }
  517. my $newcopy=Imager->new();
  518. $newcopy->{IMG} = i_copy($self->{IMG});
  519. return $newcopy;
  520. }
  521. # Paste a region
  522. sub paste {
  523. my $self = shift;
  524. unless ($self->{IMG}) {
  525. $self->_set_error('empty input image');
  526. return;
  527. }
  528. my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
  529. my $src = $input{img} || $input{src};
  530. unless($src) {
  531. $self->_set_error("no source image");
  532. return;
  533. }
  534. $input{left}=0 if $input{left} <= 0;
  535. $input{top}=0 if $input{top} <= 0;
  536. my($r,$b)=i_img_info($src->{IMG});
  537. my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
  538. my ($src_right, $src_bottom);
  539. if ($input{src_coords}) {
  540. ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
  541. }
  542. else {
  543. if (defined $input{src_maxx}) {
  544. $src_right = $input{src_maxx};
  545. }
  546. elsif (defined $input{width}) {
  547. if ($input{width} <= 0) {
  548. $self->_set_error("paste: width must me positive");
  549. return;
  550. }
  551. $src_right = $src_left + $input{width};
  552. }
  553. else {
  554. $src_right = $r;
  555. }
  556. if (defined $input{src_maxy}) {
  557. $src_bottom = $input{src_maxy};
  558. }
  559. elsif (defined $input{height}) {
  560. if ($input{height} < 0) {
  561. $self->_set_error("paste: height must be positive");
  562. return;
  563. }
  564. $src_bottom = $src_top + $input{height};
  565. }
  566. else {
  567. $src_bottom = $b;
  568. }
  569. }
  570. $src_right > $r and $src_right = $r;
  571. $src_bottom > $b and $src_bottom = $b;
  572. if ($src_right <= $src_left
  573. || $src_bottom < $src_top) {
  574. $self->_set_error("nothing to paste");
  575. return;
  576. }
  577. i_copyto($self->{IMG}, $src->{IMG},
  578. $src_left, $src_top, $src_right, $src_bottom,
  579. $input{left}, $input{top});
  580. return $self; # What should go here??
  581. }
  582. # Crop an image - i.e. return a new image that is smaller
  583. sub crop {
  584. my $self=shift;
  585. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  586. unless (defined wantarray) {
  587. my @caller = caller;
  588. warn "crop() called in void context - crop() returns the cropped image at $caller[1] line $caller[2]\n";
  589. return;
  590. }
  591. my %hsh=@_;
  592. my ($w, $h, $l, $r, $b, $t) =
  593. @hsh{qw(width height left right bottom top)};
  594. # work through the various possibilities
  595. if (defined $l) {
  596. if (defined $w) {
  597. $r = $l + $w;
  598. }
  599. elsif (!defined $r) {
  600. $r = $self->getwidth;
  601. }
  602. }
  603. elsif (defined $r) {
  604. if (defined $w) {
  605. $l = $r - $w;
  606. }
  607. else {
  608. $l = 0;
  609. }
  610. }
  611. elsif (defined $w) {
  612. $l = int(0.5+($self->getwidth()-$w)/2);
  613. $r = $l + $w;
  614. }
  615. else {
  616. $l = 0;
  617. $r = $self->getwidth;
  618. }
  619. if (defined $t) {
  620. if (defined $h) {
  621. $b = $t + $h;
  622. }
  623. elsif (!defined $b) {
  624. $b = $self->getheight;
  625. }
  626. }
  627. elsif (defined $b) {
  628. if (defined $h) {
  629. $t = $b - $h;
  630. }
  631. else {
  632. $t = 0;
  633. }
  634. }
  635. elsif (defined $h) {
  636. $t=int(0.5+($self->getheight()-$h)/2);
  637. $b=$t+$h;
  638. }
  639. else {
  640. $t = 0;
  641. $b = $self->getheight;
  642. }
  643. ($l,$r)=($r,$l) if $l>$r;
  644. ($t,$b)=($b,$t) if $t>$b;
  645. $l < 0 and $l = 0;
  646. $r > $self->getwidth and $r = $self->getwidth;
  647. $t < 0 and $t = 0;
  648. $b > $self->getheight and $b = $self->getheight;
  649. if ($l == $r || $t == $b) {
  650. $self->_set_error("resulting image would have no content");
  651. return;
  652. }
  653. if( $r < $l or $b < $t ) {
  654. $self->_set_error("attempting to crop outside of the image");
  655. return;
  656. }
  657. my $dst = $self->_sametype(xsize=>$r-$l, ysize=>$b-$t);
  658. i_copyto($dst->{IMG},$self->{IMG},$l,$t,$r,$b,0,0);
  659. return $dst;
  660. }
  661. sub _sametype {
  662. my ($self, %opts) = @_;
  663. $self->{IMG} or return $self->_set_error("Not a valid image");
  664. my $x = $opts{xsize} || $self->getwidth;
  665. my $y = $opts{ysize} || $self->getheight;
  666. my $channels = $opts{channels} || $self->getchannels;
  667. my $out = Imager->new;
  668. if ($channels == $self->getchannels) {
  669. $out->{IMG} = i_sametype($self->{IMG}, $x, $y);
  670. }
  671. else {
  672. $out->{IMG} = i_sametype_chans($self->{IMG}, $x, $y, $channels);
  673. }
  674. unless ($out->{IMG}) {
  675. $self->{ERRSTR} = $self->_error_as_msg;
  676. return;
  677. }
  678. return $out;
  679. }
  680. # Sets an image to a certain size and channel number
  681. # if there was previously data in the image it is discarded
  682. sub img_set {
  683. my $self=shift;
  684. my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
  685. if (defined($self->{IMG})) {
  686. # let IIM_DESTROY destroy it, it's possible this image is
  687. # referenced from a virtual image (like masked)
  688. #i_img_destroy($self->{IMG});
  689. undef($self->{IMG});
  690. }
  691. if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
  692. $self->{IMG} = i_img_pal_new($hsh{xsize}, $hsh{ysize}, $hsh{channels},
  693. $hsh{maxcolors} || 256);
  694. }
  695. elsif ($hsh{bits} eq 'double') {
  696. $self->{IMG} = i_img_double_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
  697. }
  698. elsif ($hsh{bits} == 16) {
  699. $self->{IMG} = i_img_16_new($hsh{xsize}, $hsh{ysize}, $hsh{channels});
  700. }
  701. else {
  702. $self->{IMG}=Imager::ImgRaw::new($hsh{'xsize'}, $hsh{'ysize'},
  703. $hsh{'channels'});
  704. }
  705. unless ($self->{IMG}) {
  706. $self->{ERRSTR} = Imager->_error_as_msg();
  707. return;
  708. }
  709. $self;
  710. }
  711. # created a masked version of the current image
  712. sub masked {
  713. my $self = shift;
  714. $self or return undef;
  715. my %opts = (left => 0,
  716. top => 0,
  717. right => $self->getwidth,
  718. bottom => $self->getheight,
  719. @_);
  720. my $mask = $opts{mask} ? $opts{mask}{IMG} : undef;
  721. my $result = Imager->new;
  722. $result->{IMG} = i_img_masked_new($self->{IMG}, $mask, $opts{left},
  723. $opts{top}, $opts{right} - $opts{left},
  724. $opts{bottom} - $opts{top});
  725. # keep references to the mask and base images so they don't
  726. # disappear on us
  727. $result->{DEPENDS} = [ $self->{IMG}, $mask ];
  728. $result;
  729. }
  730. # convert an RGB image into a paletted image
  731. sub to_paletted {
  732. my $self = shift;
  733. my $opts;
  734. if (@_ != 1 && !ref $_[0]) {
  735. $opts = { @_ };
  736. }
  737. else {
  738. $opts = shift;
  739. }
  740. unless (defined wantarray) {
  741. my @caller = caller;
  742. warn "to_paletted() called in void context - to_paletted() returns the converted image at $caller[1] line $caller[2]\n";
  743. return;
  744. }
  745. my $result = Imager->new;
  746. $result->{IMG} = i_img_to_pal($self->{IMG}, $opts);
  747. #print "Type ", i_img_type($result->{IMG}), "\n";
  748. if ($result->{IMG}) {
  749. return $result;
  750. }
  751. else {
  752. $self->{ERRSTR} = $self->_error_as_msg;
  753. return;
  754. }
  755. }
  756. # convert a paletted (or any image) to an 8-bit/channel RGB images
  757. sub to_rgb8 {
  758. my $self = shift;
  759. my $result;
  760. unless (defined wantarray) {
  761. my @caller = caller;
  762. warn "to_rgb8() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
  763. return;
  764. }
  765. if ($self->{IMG}) {
  766. $result = Imager->new;
  767. $result->{IMG} = i_img_to_rgb($self->{IMG})
  768. or undef $result;
  769. }
  770. return $result;
  771. }
  772. # convert a paletted (or any image) to an 8-bit/channel RGB images
  773. sub to_rgb16 {
  774. my $self = shift;
  775. my $result;
  776. unless (defined wantarray) {
  777. my @caller = caller;
  778. warn "to_rgb16() called in void context - to_rgb8() returns the converted image at $caller[1] line $caller[2]\n";
  779. return;
  780. }
  781. if ($self->{IMG}) {
  782. $result = Imager->new;
  783. $result->{IMG} = i_img_to_rgb16($self->{IMG})
  784. or undef $result;
  785. }
  786. return $result;
  787. }
  788. sub addcolors {
  789. my $self = shift;
  790. my %opts = (colors=>[], @_);
  791. unless ($self->{IMG}) {
  792. $self->_set_error("empty input image");
  793. return;
  794. }
  795. my @colors = @{$opts{colors}}
  796. or return undef;
  797. for my $color (@colors) {
  798. $color = _color($color);
  799. unless ($color) {
  800. $self->_set_error($Imager::ERRSTR);
  801. return;
  802. }
  803. }
  804. return i_addcolors($self->{IMG}, @colors);
  805. }
  806. sub setcolors {
  807. my $self = shift;
  808. my %opts = (start=>0, colors=>[], @_);
  809. unless ($self->{IMG}) {
  810. $self->_set_error("empty input image");
  811. return;
  812. }
  813. my @colors = @{$opts{colors}}
  814. or return undef;
  815. for my $color (@colors) {
  816. $color = _color($color);
  817. unless ($color) {
  818. $self->_set_error($Imager::ERRSTR);
  819. return;
  820. }
  821. }
  822. return i_setcolors($self->{IMG}, $opts{start}, @colors);
  823. }
  824. sub getcolors {
  825. my $self = shift;
  826. my %opts = @_;
  827. if (!exists $opts{start} && !exists $opts{count}) {
  828. # get them all
  829. $opts{start} = 0;
  830. $opts{count} = $self->colorcount;
  831. }
  832. elsif (!exists $opts{count}) {
  833. $opts{count} = 1;
  834. }
  835. elsif (!exists $opts{start}) {
  836. $opts{start} = 0;
  837. }
  838. $self->{IMG} and
  839. return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
  840. }
  841. sub colorcount {
  842. i_colorcount($_[0]{IMG});
  843. }
  844. sub maxcolors {
  845. i_maxcolors($_[0]{IMG});
  846. }
  847. sub findcolor {
  848. my $self = shift;
  849. my %opts = @_;
  850. $opts{color} or return undef;
  851. $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
  852. }
  853. sub bits {
  854. my $self = shift;
  855. my $bits = $self->{IMG} && i_img_bits($self->{IMG});
  856. if ($bits && $bits == length(pack("d", 1)) * 8) {
  857. $bits = 'double';
  858. }
  859. $bits;
  860. }
  861. sub type {
  862. my $self = shift;
  863. if ($self->{IMG}) {
  864. return i_img_type($self->{IMG}) ? "paletted" : "direct";
  865. }
  866. }
  867. sub virtual {
  868. my $self = shift;
  869. $self->{IMG} and i_img_virtual($self->{IMG});
  870. }
  871. sub tags {
  872. my ($self, %opts) = @_;
  873. $self->{IMG} or return;
  874. if (defined $opts{name}) {
  875. my @result;
  876. my $start = 0;
  877. my $found;
  878. while (defined($found = i_tags_find($self->{IMG}, $opts{name}, $start))) {
  879. push @result, (i_tags_get($self->{IMG}, $found))[1];
  880. $start = $found+1;
  881. }
  882. return wantarray ? @result : $result[0];
  883. }
  884. elsif (defined $opts{code}) {
  885. my @result;
  886. my $start = 0;
  887. my $found;
  888. while (defined($found = i_tags_findn($self->{IMG}, $opts{code}, $start))) {
  889. push @result, (i_tags_get($self->{IMG}, $found))[1];
  890. $start = $found+1;
  891. }
  892. return @result;
  893. }
  894. else {
  895. if (wantarray) {
  896. return map { [ i_tags_get($self->{IMG}, $_) ] } 0.. i_tags_count($self->{IMG})-1;
  897. }
  898. else {
  899. return i_tags_count($self->{IMG});
  900. }
  901. }
  902. }
  903. sub addtag {
  904. my $self = shift;
  905. my %opts = @_;
  906. return -1 unless $self->{IMG};
  907. if ($opts{name}) {
  908. if (defined $opts{value}) {
  909. if ($opts{value} =~ /^\d+$/) {
  910. # add as a number
  911. return i_tags_addn($self->{IMG}, $opts{name}, 0, $opts{value});
  912. }
  913. else {
  914. return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{value}, 0);
  915. }
  916. }
  917. elsif (defined $opts{data}) {
  918. # force addition as a string
  919. return i_tags_add($self->{IMG}, $opts{name}, 0, $opts{data}, 0);
  920. }
  921. else {
  922. $self->{ERRSTR} = "No value supplied";
  923. return undef;
  924. }
  925. }
  926. elsif ($opts{code}) {
  927. if (defined $opts{value}) {
  928. if ($opts{value} =~ /^\d+$/) {
  929. # add as a number
  930. return i_tags_addn($self->{IMG}, $opts{code}, 0, $opts{value});
  931. }
  932. else {
  933. return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{value}, 0);
  934. }
  935. }
  936. elsif (defined $opts{data}) {
  937. # force addition as a string
  938. return i_tags_add($self->{IMG}, $opts{code}, 0, $opts{data}, 0);
  939. }
  940. else {
  941. $self->{ERRSTR} = "No value supplied";
  942. return undef;
  943. }
  944. }
  945. else {
  946. return undef;
  947. }
  948. }
  949. sub deltag {
  950. my $self = shift;
  951. my %opts = @_;
  952. return 0 unless $self->{IMG};
  953. if (defined $opts{'index'}) {
  954. return i_tags_delete($self->{IMG}, $opts{'index'});
  955. }
  956. elsif (defined $opts{name}) {
  957. return i_tags_delbyname($self->{IMG}, $opts{name});
  958. }
  959. elsif (defined $opts{code}) {
  960. return i_tags_delbycode($self->{IMG}, $opts{code});
  961. }
  962. else {
  963. $self->{ERRSTR} = "Need to supply index, name, or code parameter";
  964. return 0;
  965. }
  966. }
  967. sub settag {
  968. my ($self, %opts) = @_;
  969. if ($opts{name}) {
  970. $self->deltag(name=>$opts{name});
  971. return $self->addtag(name=>$opts{name}, value=>$opts{value});
  972. }
  973. elsif (defined $opts{code}) {
  974. $self->deltag(code=>$opts{code});
  975. return $self->addtag(code=>$opts{code}, value=>$opts{value});
  976. }
  977. else {
  978. return undef;
  979. }
  980. }
  981. sub _get_reader_io {
  982. my ($self, $input) = @_;
  983. if ($input->{io}) {
  984. return $input->{io}, undef;
  985. }
  986. elsif ($input->{fd}) {
  987. return io_new_fd($input->{fd});
  988. }
  989. elsif ($input->{fh}) {
  990. my $fd = fileno($input->{fh});
  991. unless ($fd) {
  992. $self->_set_error("Handle in fh option not opened");
  993. return;
  994. }
  995. return io_new_fd($fd);
  996. }
  997. elsif ($input->{file}) {
  998. my $file = IO::File->new($input->{file}, "r");
  999. unless ($file) {
  1000. $self->_set_error("Could not open $input->{file}: $!");
  1001. return;
  1002. }
  1003. binmode $file;
  1004. return (io_new_fd(fileno($file)), $file);
  1005. }
  1006. elsif ($input->{data}) {
  1007. return io_new_buffer($input->{data});
  1008. }
  1009. elsif ($input->{callback} || $input->{readcb}) {
  1010. if (!$input->{seekcb}) {
  1011. $self->_set_error("Need a seekcb parameter");
  1012. }
  1013. if ($input->{maxbuffer}) {
  1014. return io_new_cb($input->{writecb},
  1015. $input->{callback} || $input->{readcb},
  1016. $input->{seekcb}, $input->{closecb},
  1017. $input->{maxbuffer});
  1018. }
  1019. else {
  1020. return io_new_cb($input->{writecb},
  1021. $input->{callback} || $input->{readcb},
  1022. $input->{seekcb}, $input->{closecb});
  1023. }
  1024. }
  1025. else {
  1026. $self->_set_error("file/fd/fh/data/callback parameter missing");
  1027. return;
  1028. }
  1029. }
  1030. sub _get_writer_io {
  1031. my ($self, $input, $type) = @_;
  1032. if ($input->{io}) {
  1033. return $input->{io};
  1034. }
  1035. elsif ($input->{fd}) {
  1036. return io_new_fd($input->{fd});
  1037. }
  1038. elsif ($input->{fh}) {
  1039. my $fd = fileno($input->{fh});
  1040. unless ($fd) {
  1041. $self->_set_error("Handle in fh option not opened");
  1042. return;
  1043. }
  1044. # flush it
  1045. my $oldfh = select($input->{fh});
  1046. # flush anything that's buffered, and make sure anything else is flushed
  1047. $| = 1;
  1048. select($oldfh);
  1049. return io_new_fd($fd);
  1050. }
  1051. elsif ($input->{file}) {
  1052. my $fh = new IO::File($input->{file},"w+");
  1053. unless ($fh) {
  1054. $self->_set_error("Could not open file $input->{file}: $!");
  1055. return;
  1056. }
  1057. binmode($fh) or die;
  1058. return (io_new_fd(fileno($fh)), $fh);
  1059. }
  1060. elsif ($input->{data}) {
  1061. return io_new_bufchain();
  1062. }
  1063. elsif ($input->{callback} || $input->{writecb}) {
  1064. if ($input->{maxbuffer}) {
  1065. return io_new_cb($input->{callback} || $input->{writecb},
  1066. $input->{readcb},
  1067. $input->{seekcb}, $input->{closecb},
  1068. $input->{maxbuffer});
  1069. }
  1070. else {
  1071. return io_new_cb($input->{callback} || $input->{writecb},
  1072. $input->{readcb},
  1073. $input->{seekcb}, $input->{closecb});
  1074. }
  1075. }
  1076. else {
  1077. $self->_set_error("file/fd/fh/data/callback parameter missing");
  1078. return;
  1079. }
  1080. }
  1081. # Read an image from file
  1082. sub read {
  1083. my $self = shift;
  1084. my %input=@_;
  1085. if (defined($self->{IMG})) {
  1086. # let IIM_DESTROY do the destruction, since the image may be
  1087. # referenced from elsewhere
  1088. #i_img_destroy($self->{IMG});
  1089. undef($self->{IMG});
  1090. }
  1091. my ($IO, $fh) = $self->_get_reader_io(\%input) or return;
  1092. unless ($input{'type'}) {
  1093. $input{'type'} = i_test_format_probe($IO, -1);
  1094. }
  1095. unless ($input{'type'}) {
  1096. $self->_set_error('type parameter missing and not possible to guess from extension');
  1097. return undef;
  1098. }
  1099. _reader_autoload($input{type});
  1100. if ($readers{$input{type}} && $readers{$input{type}}{single}) {
  1101. return $readers{$input{type}}{single}->($self, $IO, %input);
  1102. }
  1103. unless ($formats{$input{'type'}}) {
  1104. $self->_set_error("format '$input{'type'}' not supported");
  1105. return;
  1106. }
  1107. # Setup data source
  1108. if ( $input{'type'} eq 'jpeg' ) {
  1109. ($self->{IMG},$self->{IPTCRAW}) = i_readjpeg_wiol( $IO );
  1110. if ( !defined($self->{IMG}) ) {
  1111. $self->{ERRSTR}=$self->_error_as_msg(); return undef;
  1112. }
  1113. $self->{DEBUG} && print "loading a jpeg file\n";
  1114. return $self;
  1115. }
  1116. my $allow_incomplete = $input{allow_incomplete};
  1117. defined $allow_incomplete or $allow_incomplete = 0;
  1118. if ( $input{'type'} eq 'tiff' ) {
  1119. my $page = $input{'page'};
  1120. defined $page or $page = 0;
  1121. $self->{IMG}=i_readtiff_wiol( $IO, $allow_incomplete, $page );
  1122. if ( !defined($self->{IMG}) ) {
  1123. $self->{ERRSTR}=$self->_error_as_msg(); return undef;
  1124. }
  1125. $self->{DEBUG} && print "loading a tiff file\n";
  1126. return $self;
  1127. }
  1128. if ( $input{'type'} eq 'pnm' ) {
  1129. $self->{IMG}=i_readpnm_wiol( $IO, $allow_incomplete );
  1130. if ( !defined($self->{IMG}) ) {
  1131. $self->{ERRSTR}='unable to read pnm image: '._error_as_msg();
  1132. return undef;
  1133. }
  1134. $self->{DEBUG} && print "loading a pnm file\n";
  1135. return $self;
  1136. }
  1137. if ( $input{'type'} eq 'png' ) {
  1138. $self->{IMG}=i_readpng_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
  1139. if ( !defined($self->{IMG}) ) {
  1140. $self->{ERRSTR} = $self->_error_as_msg();
  1141. return undef;
  1142. }
  1143. $self->{DEBUG} && print "loading a png file\n";
  1144. }
  1145. if ( $input{'type'} eq 'bmp' ) {
  1146. $self->{IMG}=i_readbmp_wiol( $IO, $allow_incomplete );
  1147. if ( !defined($self->{IMG}) ) {
  1148. $self->{ERRSTR}=$self->_error_as_msg();
  1149. return undef;
  1150. }
  1151. $self->{DEBUG} && print "loading a bmp file\n";
  1152. }
  1153. if ( $input{'type'} eq 'gif' ) {
  1154. if ($input{colors} && !ref($input{colors})) {
  1155. # must be a reference to a scalar that accepts the colour map
  1156. $self->{ERRSTR} = "option 'colors' must be a scalar reference";
  1157. return undef;
  1158. }
  1159. if ($input{'gif_consolidate'}) {
  1160. if ($input{colors}) {
  1161. my $colors;
  1162. ($self->{IMG}, $colors) =i_readgif_wiol( $IO );
  1163. if ($colors) {
  1164. ${ $input{colors} } = [ map { NC(@$_) } @$colors ];
  1165. }
  1166. }
  1167. else {
  1168. $self->{IMG} =i_readgif_wiol( $IO );
  1169. }
  1170. }
  1171. else {
  1172. my $page = $input{'page'};
  1173. defined $page or $page = 0;
  1174. $self->{IMG} = i_readgif_single_wiol( $IO, $page );
  1175. if ($self->{IMG} && $input{colors}) {
  1176. ${ $input{colors} } =
  1177. [ i_getcolors($self->{IMG}, 0, i_colorcount($self->{IMG})) ];
  1178. }
  1179. }
  1180. if ( !defined($self->{IMG}) ) {
  1181. $self->{ERRSTR}=$self->_error_as_msg();
  1182. return undef;
  1183. }
  1184. $self->{DEBUG} && print "loading a gif file\n";
  1185. }
  1186. if ( $input{'type'} eq 'tga' ) {
  1187. $self->{IMG}=i_readtga_wiol( $IO, -1 ); # Fixme, check if that length parameter is ever needed
  1188. if ( !defined($self->{IMG}) ) {
  1189. $self->{ERRSTR}=$self->_error_as_msg();
  1190. return undef;
  1191. }
  1192. $self->{DEBUG} && print "loading a tga file\n";
  1193. }
  1194. if ( $input{'type'} eq 'raw' ) {
  1195. my %params=(datachannels=>3,storechannels=>3,interleave=>1,%input);
  1196. if ( !($params{xsize} && $params{ysize}) ) {
  1197. $self->{ERRSTR}='missing xsize or ysize parameter for raw';
  1198. return undef;
  1199. }
  1200. $self->{IMG} = i_readraw_wiol( $IO,
  1201. $params{xsize},
  1202. $params{ysize},
  1203. $params{datachannels},
  1204. $params{storechannels},
  1205. $params{interleave});
  1206. if ( !defined($self->{IMG}) ) {
  1207. $self->{ERRSTR}=$self->_error_as_msg();
  1208. return undef;
  1209. }
  1210. $self->{DEBUG} && print "loading a raw file\n";
  1211. }
  1212. return $self;
  1213. }
  1214. sub register_reader {
  1215. my ($class, %opts) = @_;
  1216. defined $opts{type}
  1217. or die "register_reader called with no type parameter\n";
  1218. my $type = $opts{type};
  1219. defined $opts{single} || defined $opts{multiple}
  1220. or die "register_reader called with no single or multiple parameter\n";
  1221. $readers{$type} = { };
  1222. if ($opts{single}) {
  1223. $readers{$type}{single} = $opts{single};
  1224. }
  1225. if ($opts{multiple}) {
  1226. $readers{$type}{multiple} = $opts{multiple};
  1227. }
  1228. return 1;
  1229. }
  1230. sub register_writer {
  1231. my ($class, %opts) = @_;
  1232. defined $opts{type}
  1233. or die "register_writer called with no type parameter\n";
  1234. my $type = $opts{type};
  1235. defined $opts{single} || defined $opts{multiple}
  1236. or die "register_writer called with no single or multiple parameter\n";
  1237. $writers{$type} = { };
  1238. if ($opts{single}) {
  1239. $writers{$type}{single} = $opts{single};
  1240. }
  1241. if ($opts{multiple}) {
  1242. $writers{$type}{multiple} = $opts{multiple};
  1243. }
  1244. return 1;
  1245. }
  1246. # probes for an Imager::File::whatever module
  1247. sub _reader_autoload {
  1248. my $type = shift;
  1249. return if $formats{$type} || $readers{$type};
  1250. return unless $type =~ /^\w+$/;
  1251. my $file = "Imager/File/\U$type\E.pm";
  1252. unless ($attempted_to_load{$file}) {
  1253. eval {
  1254. ++$attempted_to_load{$file};
  1255. require $file;
  1256. };
  1257. if ($@) {
  1258. # try to get a reader specific module
  1259. my $file = "Imager/File/\U$type\EReader.pm";
  1260. unless ($attempted_to_load{$file}) {
  1261. eval {
  1262. ++$attempted_to_load{$file};
  1263. require $file;
  1264. };
  1265. }
  1266. }
  1267. }
  1268. }
  1269. # probes for an Imager::File::whatever module
  1270. sub _writer_autoload {
  1271. my $type = shift;
  1272. return if $formats{$type} || $readers{$type};
  1273. return unless $type =~ /^\w+$/;
  1274. my $file = "Imager/File/\U$type\E.pm";
  1275. unless ($attempted_to_load{$file}) {
  1276. eval {
  1277. ++$attempted_to_load{$file};
  1278. require $file;
  1279. };
  1280. if ($@) {
  1281. # try to get a writer specific module
  1282. my $file = "Imager/File/\U$type\EWriter.pm";
  1283. unless ($attempted_to_load{$file}) {
  1284. eval {
  1285. ++$attempted_to_load{$file};
  1286. require $file;
  1287. };
  1288. }
  1289. }
  1290. }
  1291. }
  1292. sub _fix_gif_positions {
  1293. my ($opts, $opt, $msg, @imgs) = @_;
  1294. my $positions = $opts->{'gif_positions'};
  1295. my $index = 0;
  1296. for my $pos (@$positions) {
  1297. my ($x, $y) = @$pos;
  1298. my $img = $imgs[$index++];
  1299. $img->settag(name=>'gif_left', value=>$x);
  1300. $img->settag(name=>'gif_top', value=>$y) if defined $y;
  1301. }
  1302. $$msg .= "replaced with the gif_left and gif_top tags";
  1303. }
  1304. my %obsolete_opts =
  1305. (
  1306. gif_each_palette=>'gif_local_map',
  1307. interlace => 'gif_interlace',
  1308. gif_delays => 'gif_delay',
  1309. gif_positions => \&_fix_gif_positions,
  1310. gif_loop_count => 'gif_loop',
  1311. );
  1312. sub _set_opts {
  1313. my ($self, $opts, $prefix, @imgs) = @_;
  1314. for my $opt (keys %$opts) {
  1315. my $tagname = $opt;
  1316. if ($obsolete_opts{$opt}) {
  1317. my $new = $obsolete_opts{$opt};
  1318. my $msg = "Obsolete option $opt ";
  1319. if (ref $new) {
  1320. $new->($opts, $opt, \$msg, @imgs);
  1321. }
  1322. else {
  1323. $msg .= "replaced with the $new tag ";
  1324. $tagname = $new;
  1325. }
  1326. $msg .= "line ".(caller(2))[2]." of file ".(caller(2))[1];
  1327. warn $msg if $warn_obsolete && $^W;
  1328. }
  1329. next unless $tagname =~ /^\Q$prefix/;
  1330. my $value = $opts->{$opt};
  1331. if (ref $value) {
  1332. if (UNIVERSAL::isa($value, "Imager::Color")) {
  1333. my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
  1334. for my $img (@imgs) {
  1335. $img->settag(name=>$tagname, value=>$tag);
  1336. }
  1337. }
  1338. elsif (ref($value) eq 'ARRAY') {
  1339. for my $i (0..$#$value) {
  1340. my $val = $value->[$i];
  1341. if (ref $val) {
  1342. if (UNIVERSAL::isa($val, "Imager::Color")) {
  1343. my $tag = sprintf("color(%d,%d,%d,%d)", $value->rgba);
  1344. $i < @imgs and
  1345. $imgs[$i]->settag(name=>$tagname, value=>$tag);
  1346. }
  1347. else {
  1348. $self->_set_error("Unknown reference type " . ref($value) .
  1349. " supplied in array for $opt");
  1350. return;
  1351. }
  1352. }
  1353. else {
  1354. $i < @imgs
  1355. and $imgs[$i]->settag(name=>$tagname, value=>$val);
  1356. }
  1357. }
  1358. }
  1359. else {
  1360. $self->_set_error("Unknown reference type " . ref($value) .
  1361. " supplied for $opt");
  1362. return;
  1363. }
  1364. }
  1365. else {
  1366. # set it as a tag for every image
  1367. for my $img (@imgs) {
  1368. $img->settag(name=>$tagname, value=>$value);
  1369. }
  1370. }
  1371. }
  1372. return 1;
  1373. }
  1374. # Write an image to file
  1375. sub write {
  1376. my $self = shift;
  1377. my %input=(jpegquality=>75,
  1378. gifquant=>'mc',
  1379. lmdither=>6.0,
  1380. lmfixed=>[],
  1381. idstring=>"",
  1382. compress=>1,
  1383. wierdpack=>0,
  1384. fax_fine=>1, @_);
  1385. my $rc;
  1386. $self->_set_opts(\%input, "i_", $self)
  1387. or return undef;
  1388. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  1389. if (!$input{'type'} and $input{file}) {
  1390. $input{'type'}=$FORMATGUESS->($input{file});
  1391. }
  1392. if (!$input{'type'}) {
  1393. $self->{ERRSTR}='type parameter missing and not possible to guess from extension';
  1394. return undef;
  1395. }
  1396. _writer_autoload($input{type});
  1397. my ($IO, $fh);
  1398. if ($writers{$input{type}} && $writers{$input{type}}{single}) {
  1399. ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
  1400. or return undef;
  1401. $writers{$input{type}}{single}->($self, $IO, %input)
  1402. or return undef;
  1403. }
  1404. else {
  1405. if (!$formats{$input{'type'}}) {
  1406. $self->{ERRSTR}='format not supported';
  1407. return undef;
  1408. }
  1409. ($IO, $fh) = $self->_get_writer_io(\%input, $input{'type'})
  1410. or return undef;
  1411. if ($input{'type'} eq 'tiff') {
  1412. $self->_set_opts(\%input, "tiff_", $self)
  1413. or return undef;
  1414. $self->_set_opts(\%input, "exif_", $self)
  1415. or return undef;
  1416. if (defined $input{class} && $input{class} eq 'fax') {
  1417. if (!i_writetiff_wiol_faxable($self->{IMG}, $IO, $input{fax_fine})) {
  1418. $self->{ERRSTR} = $self->_error_as_msg();
  1419. return undef;
  1420. }
  1421. } else {
  1422. if (!i_writetiff_wiol($self->{IMG}, $IO)) {
  1423. $self->{ERRSTR} = $self->_error_as_msg();
  1424. return undef;
  1425. }
  1426. }
  1427. } elsif ( $input{'type'} eq 'pnm' ) {
  1428. $self->_set_opts(\%input, "pnm_", $self)
  1429. or return undef;
  1430. if ( ! i_writeppm_wiol($self->{IMG},$IO) ) {
  1431. $self->{ERRSTR} = $self->_error_as_msg();
  1432. return undef;
  1433. }
  1434. $self->{DEBUG} && print "writing a pnm file\n";
  1435. } elsif ( $input{'type'} eq 'raw' ) {
  1436. $self->_set_opts(\%input, "raw_", $self)
  1437. or return undef;
  1438. if ( !i_writeraw_wiol($self->{IMG},$IO) ) {
  1439. $self->{ERRSTR} = $self->_error_as_msg();
  1440. return undef;
  1441. }
  1442. $self->{DEBUG} && print "writing a raw file\n";
  1443. } elsif ( $input{'type'} eq 'png' ) {
  1444. $self->_set_opts(\%input, "png_", $self)
  1445. or return undef;
  1446. if ( !i_writepng_wiol($self->{IMG}, $IO) ) {
  1447. $self->{ERRSTR}='unable to write png image';
  1448. return undef;
  1449. }
  1450. $self->{DEBUG} && print "writing a png file\n";
  1451. } elsif ( $input{'type'} eq 'jpeg' ) {
  1452. $self->_set_opts(\%input, "jpeg_", $self)
  1453. or return undef;
  1454. $self->_set_opts(\%input, "exif_", $self)
  1455. or return undef;
  1456. if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
  1457. $self->{ERRSTR} = $self->_error_as_msg();
  1458. return undef;
  1459. }
  1460. $self->{DEBUG} && print "writing a jpeg file\n";
  1461. } elsif ( $input{'type'} eq 'bmp' ) {
  1462. $self->_set_opts(\%input, "bmp_", $self)
  1463. or return undef;
  1464. if ( !i_writebmp_wiol($self->{IMG}, $IO) ) {
  1465. $self->{ERRSTR} = $self->_error_as_msg;
  1466. return undef;
  1467. }
  1468. $self->{DEBUG} && print "writing a bmp file\n";
  1469. } elsif ( $input{'type'} eq 'tga' ) {
  1470. $self->_set_opts(\%input, "tga_", $self)
  1471. or return undef;
  1472. if ( !i_writetga_wiol($self->{IMG}, $IO, $input{wierdpack}, $input{compress}, $input{idstring}) ) {
  1473. $self->{ERRSTR}=$self->_error_as_msg();
  1474. return undef;
  1475. }
  1476. $self->{DEBUG} && print "writing a tga file\n";
  1477. } elsif ( $input{'type'} eq 'gif' ) {
  1478. $self->_set_opts(\%input, "gif_", $self)
  1479. or return undef;
  1480. # compatibility with the old interfaces
  1481. if ($input{gifquant} eq 'lm') {
  1482. $input{make_colors} = 'addi';
  1483. $input{translate} = 'perturb';
  1484. $input{perturb} = $input{lmdither};
  1485. } elsif ($input{gifquant} eq 'gen') {
  1486. # just pass options through
  1487. } else {
  1488. $input{make_colors} = 'webmap'; # ignored
  1489. $input{translate} = 'giflib';
  1490. }
  1491. if (!i_writegif_wiol($IO, \%input, $self->{IMG})) {
  1492. $self->{ERRSTR} = $self->_error_as_msg;
  1493. return;
  1494. }
  1495. }
  1496. }
  1497. if (exists $input{'data'}) {
  1498. my $data = io_slurp($IO);
  1499. if (!$data) {
  1500. $self->{ERRSTR}='Could not slurp from buffer';
  1501. return undef;
  1502. }
  1503. ${$input{data}} = $data;
  1504. }
  1505. return $self;
  1506. }
  1507. sub write_multi {
  1508. my ($class, $opts, @images) = @_;
  1509. my $type = $opts->{type};
  1510. if (!$type && $opts->{'file'}) {
  1511. $type = $FORMATGUESS->($opts->{'file'});
  1512. }
  1513. unless ($type) {
  1514. $class->_set_error('type parameter missing and not possible to guess from extension');
  1515. return;
  1516. }
  1517. # translate to ImgRaw
  1518. if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
  1519. $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
  1520. return 0;
  1521. }
  1522. $class->_set_opts($opts, "i_", @images)
  1523. or return;
  1524. my @work = map $_->{IMG}, @images;
  1525. _writer_autoload($type);
  1526. my ($IO, $file);
  1527. if ($writers{$type} && $writers{$type}{multiple}) {
  1528. ($IO, $file) = $class->_get_writer_io($opts, $type)
  1529. or return undef;
  1530. $writers{$type}{multiple}->($class, $IO, $opts, @images)
  1531. or return undef;
  1532. }
  1533. else {
  1534. if (!$formats{$type}) {
  1535. $class->_set_error("format $type not supported");
  1536. return undef;
  1537. }
  1538. ($IO, $file) = $class->_get_writer_io($opts, $type)
  1539. or return undef;
  1540. if ($type eq 'gif') {
  1541. $class->_set_opts($opts, "gif_", @images)
  1542. or return;
  1543. my $gif_delays = $opts->{gif_delays};
  1544. local $opts->{gif_delays} = $gif_delays;
  1545. if ($opts->{gif_delays} && !ref $opts->{gif_delays}) {
  1546. # assume the caller wants the same delay for each frame
  1547. $opts->{gif_delays} = [ ($gif_delays) x @images ];
  1548. }
  1549. unless (i_writegif_wiol($IO, $opts, @work)) {
  1550. $class->_set_error($class->_error_as_msg());
  1551. return undef;
  1552. }
  1553. }
  1554. elsif ($type eq 'tiff') {
  1555. $class->_set_opts($opts, "tiff_", @images)
  1556. or return;
  1557. $class->_set_opts($opts, "exif_", @images)
  1558. or return;
  1559. my $res;
  1560. $opts->{fax_fine} = 1 unless exists $opts->{fax_fine};
  1561. if ($opts->{'class'} && $opts->{'class'} eq 'fax') {
  1562. $res = i_writetiff_multi_wiol_faxable($IO, $opts->{fax_fine}, @work);
  1563. }
  1564. else {
  1565. $res = i_writetiff_multi_wiol($IO, @work);
  1566. }
  1567. unless ($res) {
  1568. $class->_set_error($class->_error_as_msg());
  1569. return undef;
  1570. }
  1571. }
  1572. else {
  1573. if (@images == 1) {
  1574. unless ($images[0]->write(%$opts, io => $IO, type => $type)) {
  1575. return 1;
  1576. }
  1577. }
  1578. else {
  1579. $ERRSTR = "Sorry, write_multi doesn't support $type yet";
  1580. return 0;
  1581. }
  1582. }
  1583. }
  1584. if (exists $opts->{'data'}) {
  1585. my $data = io_slurp($IO);
  1586. if (!$data) {
  1587. Imager->_set_error('Could not slurp from buffer');
  1588. return undef;
  1589. }
  1590. ${$opts->{data}} = $data;
  1591. }
  1592. return 1;
  1593. }
  1594. # read multiple images from a file
  1595. sub read_multi {
  1596. my ($class, %opts) = @_;
  1597. my ($IO, $file) = $class->_get_reader_io(\%opts, $opts{'type'})
  1598. or return;
  1599. my $type = $opts{'type'};
  1600. unless ($type) {
  1601. $type = i_test_format_probe($IO, -1);
  1602. }
  1603. if ($opts{file} && !$type) {
  1604. # guess the type
  1605. $type = $FORMATGUESS->($opts{file});
  1606. }
  1607. unless ($type) {
  1608. $ERRSTR = "No type parameter supplied and it couldn't be guessed";
  1609. return;
  1610. }
  1611. _reader_autoload($type);
  1612. if ($readers{$type} && $readers{$type}{multiple}) {
  1613. return $readers{$type}{multiple}->($IO, %opts);
  1614. }
  1615. if ($type eq 'gif') {
  1616. my @imgs;
  1617. @imgs = i_readgif_multi_wiol($IO);
  1618. if (@imgs) {
  1619. return map {
  1620. bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
  1621. } @imgs;
  1622. }
  1623. else {
  1624. $ERRSTR = _error_as_msg();
  1625. return;
  1626. }
  1627. }
  1628. elsif ($type eq 'tiff') {
  1629. my @imgs = i_readtiff_multi_wiol($IO, -1);
  1630. if (@imgs) {
  1631. return map {
  1632. bless { IMG=>$_, DEBUG=>$DEBUG, ERRSTR=>undef }, 'Imager'
  1633. } @imgs;
  1634. }
  1635. else {
  1636. $ERRSTR = _error_as_msg();
  1637. return;
  1638. }
  1639. }
  1640. else {
  1641. my $img = Imager->new;
  1642. if ($img->read(%opts, io => $IO, type => $type)) {
  1643. return ( $img );
  1644. }
  1645. }
  1646. $ERRSTR = "Cannot read multiple images from $type files";
  1647. return;
  1648. }
  1649. # Destroy an Imager object
  1650. sub DESTROY {
  1651. my $self=shift;
  1652. # delete $instances{$self};
  1653. if (defined($self->{IMG})) {
  1654. # the following is now handled by the XS DESTROY method for
  1655. # Imager::ImgRaw object
  1656. # Re-enabling this will break virtual images
  1657. # tested for in t/t020masked.t
  1658. # i_img_destroy($self->{IMG});
  1659. undef($self->{IMG});
  1660. } else {
  1661. # print "Destroy Called on an empty image!\n"; # why did I put this here??
  1662. }
  1663. }
  1664. # Perform an inplace filter of an image
  1665. # that is the image will be overwritten with the data
  1666. sub filter {
  1667. my $self=shift;
  1668. my %input=@_;
  1669. my %hsh;
  1670. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  1671. if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
  1672. if ( (grep { $_ eq $input{'type'} } keys %filters) != 1) {
  1673. $self->{ERRSTR}='type parameter not matching any filter'; return undef;
  1674. }
  1675. if ($filters{$input{'type'}}{names}) {
  1676. my $names = $filters{$input{'type'}}{names};
  1677. for my $name (keys %$names) {
  1678. if (defined $input{$name} && exists $names->{$name}{$input{$name}}) {
  1679. $input{$name} = $names->{$name}{$input{$name}};
  1680. }
  1681. }
  1682. }
  1683. if (defined($filters{$input{'type'}}{defaults})) {
  1684. %hsh=( image => $self->{IMG},
  1685. imager => $self,
  1686. %{$filters{$input{'type'}}{defaults}},
  1687. %input );
  1688. } else {
  1689. %hsh=( image => $self->{IMG},
  1690. imager => $self,
  1691. %input );
  1692. }
  1693. my @cs=@{$filters{$input{'type'}}{callseq}};
  1694. for(@cs) {
  1695. if (!defined($hsh{$_})) {
  1696. $self->{ERRSTR}="missing parameter '$_' for filter ".$input{'type'}; return undef;
  1697. }
  1698. }
  1699. eval {
  1700. local $SIG{__DIE__}; # we don't want this processed by confess, etc
  1701. &{$filters{$input{'type'}}{callsub}}(%hsh);
  1702. };
  1703. if ($@) {
  1704. chomp($self->{ERRSTR} = $@);
  1705. return;
  1706. }
  1707. my @b=keys %hsh;
  1708. $self->{DEBUG} && print "callseq is: @cs\n";
  1709. $self->{DEBUG} && print "matching callseq is: @b\n";
  1710. return $self;
  1711. }
  1712. sub register_filter {
  1713. my $class = shift;
  1714. my %hsh = ( defaults => {}, @_ );
  1715. defined $hsh{type}
  1716. or die "register_filter() with no type\n";
  1717. defined $hsh{callsub}
  1718. or die "register_filter() with no callsub\n";
  1719. defined $hsh{callseq}
  1720. or die "register_filter() with no callseq\n";
  1721. exists $filters{$hsh{type}}
  1722. and return;
  1723. $filters{$hsh{type}} = \%hsh;
  1724. return 1;
  1725. }
  1726. # Scale an image to requested size and return the scaled version
  1727. sub scale {
  1728. my $self=shift;
  1729. my %opts=('type'=>'max',qtype=>'normal',@_);
  1730. my $img = Imager->new();
  1731. my $tmp = Imager->new();
  1732. my ($x_scale, $y_scale);
  1733. unless (defined wantarray) {
  1734. my @caller = caller;
  1735. warn "scale() called in void context - scale() returns the scaled image at $caller[1] line $caller[2]\n";
  1736. return;
  1737. }
  1738. unless ($self->{IMG}) {
  1739. $self->_set_error('empty input image');
  1740. return undef;
  1741. }
  1742. if ($opts{'xscalefactor'} && $opts{'yscalefactor'}) {
  1743. $x_scale = $opts{'xscalefactor'};
  1744. $y_scale = $opts{'yscalefactor'};
  1745. }
  1746. elsif ($opts{'xscalefactor'}) {
  1747. $x_scale = $opts{'xscalefactor'};
  1748. $y_scale = $opts{'scalefactor'} || $x_scale;
  1749. }
  1750. elsif ($opts{'yscalefactor'}) {
  1751. $y_scale = $opts{'yscalefactor'};
  1752. $x_scale = $opts{'scalefactor'} || $y_scale;
  1753. }
  1754. else {
  1755. $x_scale = $y_scale = $opts{'scalefactor'} || 0.5;
  1756. }
  1757. # work out the scaling
  1758. if ($opts{xpixels} and $opts{ypixels} and $opts{'type'}) {
  1759. my ($xpix, $ypix)=( $opts{xpixels} / $self->getwidth() ,
  1760. $opts{ypixels} / $self->getheight() );
  1761. if ($opts{'type'} eq 'min') {
  1762. $x_scale = $y_scale = _min($xpix,$ypix);
  1763. }
  1764. elsif ($opts{'type'} eq 'max') {
  1765. $x_scale = $y_scale = _max($xpix,$ypix);
  1766. }
  1767. elsif ($opts{'type'} eq 'nonprop' || $opts{'type'} eq 'non-proportional') {
  1768. $x_scale = $xpix;
  1769. $y_scale = $ypix;
  1770. }
  1771. else {
  1772. $self->_set_error('invalid value for type parameter');
  1773. return undef;
  1774. }
  1775. } elsif ($opts{xpixels}) {
  1776. $x_scale = $y_scale = $opts{xpixels} / $self->getwidth();
  1777. }
  1778. elsif ($opts{ypixels}) {
  1779. $x_scale = $y_scale = $opts{ypixels}/$self->getheight();
  1780. }
  1781. elsif ($opts{constrain} && ref $opts{constrain}
  1782. && $opts{constrain}->can('constrain')) {
  1783. # we've been passed an Image::Math::Constrain object or something
  1784. # that looks like one
  1785. my $scalefactor;
  1786. (undef, undef, $scalefactor)
  1787. = $opts{constrain}->constrain($self->getwidth, $self->getheight);
  1788. unless ($scalefactor) {
  1789. $self->_set_error('constrain method failed on constrain parameter');
  1790. return undef;
  1791. }
  1792. $x_scale = $y_scale = $scalefactor;
  1793. }
  1794. if ($opts{qtype} eq 'normal') {
  1795. $tmp->{IMG} = i_scaleaxis($self->{IMG}, $x_scale, 0);
  1796. if ( !defined($tmp->{IMG}) ) {
  1797. $self->{ERRSTR} = 'unable to scale image';
  1798. return undef;
  1799. }
  1800. $img->{IMG}=i_scaleaxis($tmp->{IMG}, $y_scale, 1);
  1801. if ( !defined($img->{IMG}) ) {
  1802. $self->{ERRSTR}='unable to scale image';
  1803. return undef;
  1804. }
  1805. return $img;
  1806. }
  1807. elsif ($opts{'qtype'} eq 'preview') {
  1808. $img->{IMG} = i_scale_nn($self->{IMG}, $x_scale, $y_scale);
  1809. if ( !defined($img->{IMG}) ) {
  1810. $self->{ERRSTR}='unable to scale image';
  1811. return undef;
  1812. }
  1813. return $img;
  1814. }
  1815. elsif ($opts{'qtype'} eq 'mixing') {
  1816. my $new_width = int(0.5 + $self->getwidth * $x_scale);
  1817. my $new_height = int(0.5 + $self->getheight * $y_scale);
  1818. $new_width >= 1 or $new_width = 1;
  1819. $new_height >= 1 or $new_height = 1;
  1820. $img->{IMG} = i_scale_mixing($self->{IMG}, $new_width, $new_height);
  1821. unless ($img->{IMG}) {
  1822. $self->_set_error(Imager->_error_as_meg);
  1823. return;
  1824. }
  1825. return $img;
  1826. }
  1827. else {
  1828. $self->_set_error('invalid value for qtype parameter');
  1829. return undef;
  1830. }
  1831. }
  1832. # Scales only along the X axis
  1833. sub scaleX {
  1834. my $self = shift;
  1835. my %opts = ( scalefactor=>0.5, @_ );
  1836. unless (defined wantarray) {
  1837. my @caller = caller;
  1838. warn "scaleX() called in void context - scaleX() returns the scaled image at $caller[1] line $caller[2]\n";
  1839. return;
  1840. }
  1841. unless ($self->{IMG}) {
  1842. $self->{ERRSTR} = 'empty input image';
  1843. return undef;
  1844. }
  1845. my $img = Imager->new();
  1846. my $scalefactor = $opts{scalefactor};
  1847. if ($opts{pixels}) {
  1848. $scalefactor = $opts{pixels} / $self->getwidth();
  1849. }
  1850. unless ($self->{IMG}) {
  1851. $self->{ERRSTR}='empty input image';
  1852. return undef;
  1853. }
  1854. $img->{IMG} = i_scaleaxis($self->{IMG}, $scalefactor, 0);
  1855. if ( !defined($img->{IMG}) ) {
  1856. $self->{ERRSTR} = 'unable to scale image';
  1857. return undef;
  1858. }
  1859. return $img;
  1860. }
  1861. # Scales only along the Y axis
  1862. sub scaleY {
  1863. my $self = shift;
  1864. my %opts = ( scalefactor => 0.5, @_ );
  1865. unless (defined wantarray) {
  1866. my @caller = caller;
  1867. warn "scaleY() called in void context - scaleY() returns the scaled image at $caller[1] line $caller[2]\n";
  1868. return;
  1869. }
  1870. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  1871. my $img = Imager->new();
  1872. my $scalefactor = $opts{scalefactor};
  1873. if ($opts{pixels}) {
  1874. $scalefactor = $opts{pixels} / $self->getheight();
  1875. }
  1876. unless ($self->{IMG}) {
  1877. $self->{ERRSTR} = 'empty input image';
  1878. return undef;
  1879. }
  1880. $img->{IMG}=i_scaleaxis($self->{IMG}, $scalefactor, 1);
  1881. if ( !defined($img->{IMG}) ) {
  1882. $self->{ERRSTR} = 'unable to scale image';
  1883. return undef;
  1884. }
  1885. return $img;
  1886. }
  1887. # Transform returns a spatial transformation of the input image
  1888. # this moves pixels to a new location in the returned image.
  1889. # NOTE - should make a utility function to check transforms for
  1890. # stack overruns
  1891. sub transform {
  1892. my $self=shift;
  1893. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  1894. my %opts=@_;
  1895. my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
  1896. # print Dumper(\%opts);
  1897. # xopcopdes
  1898. if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
  1899. if (!$I2P) {
  1900. eval ("use Affix::Infix2Postfix;");
  1901. print $@;
  1902. if ( $@ ) {
  1903. $self->{ERRSTR}='transform: expr given and Affix::Infix2Postfix is not avaliable.';
  1904. return undef;
  1905. }
  1906. $I2P=Affix::Infix2Postfix->new('ops'=>[{op=>'+',trans=>'Add'},
  1907. {op=>'-',trans=>'Sub'},
  1908. {op=>'*',trans=>'Mult'},
  1909. {op=>'/',trans=>'Div'},
  1910. {op=>'-','type'=>'unary',trans=>'u-'},
  1911. {op=>'**'},
  1912. {op=>'func','type'=>'unary'}],
  1913. 'grouping'=>[qw( \( \) )],
  1914. 'func'=>[qw( sin cos )],
  1915. 'vars'=>[qw( x y )]
  1916. );
  1917. }
  1918. @xt=$I2P->translate($opts{'xexpr'});
  1919. @yt=$I2P->translate($opts{'yexpr'});
  1920. $numre=$I2P->{'numre'};
  1921. @pt=(0,0);
  1922. for(@xt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'xopcodes'}},'Parm',$#pt); } else { push(@{$opts{'xopcodes'}},$_); } }
  1923. for(@yt) { if (/$numre/) { push(@pt,$_); push(@{$opts{'yopcodes'}},'Parm',$#pt); } else { push(@{$opts{'yopcodes'}},$_); } }
  1924. @{$opts{'parm'}}=@pt;
  1925. }
  1926. # print Dumper(\%opts);
  1927. if ( !exists $opts{'xopcodes'} or @{$opts{'xopcodes'}}==0) {
  1928. $self->{ERRSTR}='transform: no xopcodes given.';
  1929. return undef;
  1930. }
  1931. @op=@{$opts{'xopcodes'}};
  1932. for $iop (@op) {
  1933. if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
  1934. $self->{ERRSTR}="transform: illegal opcode '$_'.";
  1935. return undef;
  1936. }
  1937. push(@ropx,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
  1938. }
  1939. # yopcopdes
  1940. if ( !exists $opts{'yopcodes'} or @{$opts{'yopcodes'}}==0) {
  1941. $self->{ERRSTR}='transform: no yopcodes given.';
  1942. return undef;
  1943. }
  1944. @op=@{$opts{'yopcodes'}};
  1945. for $iop (@op) {
  1946. if (!defined ($OPCODES{$iop}) and ($iop !~ /^\d+$/) ) {
  1947. $self->{ERRSTR}="transform: illegal opcode '$_'.";
  1948. return undef;
  1949. }
  1950. push(@ropy,(exists $OPCODES{$iop}) ? @{$OPCODES{$iop}} : $iop );
  1951. }
  1952. #parameters
  1953. if ( !exists $opts{'parm'}) {
  1954. $self->{ERRSTR}='transform: no parameter arg given.';
  1955. return undef;
  1956. }
  1957. # print Dumper(\@ropx);
  1958. # print Dumper(\@ropy);
  1959. # print Dumper(\@ropy);
  1960. my $img = Imager->new();
  1961. $img->{IMG}=i_transform($self->{IMG},\@ropx,\@ropy,$opts{'parm'});
  1962. if ( !defined($img->{IMG}) ) { $self->{ERRSTR}='transform: failed'; return undef; }
  1963. return $img;
  1964. }
  1965. sub transform2 {
  1966. my ($opts, @imgs) = @_;
  1967. require "Imager/Expr.pm";
  1968. $opts->{variables} = [ qw(x y) ];
  1969. my ($width, $height) = @{$opts}{qw(width height)};
  1970. if (@imgs) {
  1971. $width ||= $imgs[0]->getwidth();
  1972. $height ||= $imgs[0]->getheight();
  1973. my $img_num = 1;
  1974. for my $img (@imgs) {
  1975. $opts->{constants}{"w$img_num"} = $img->getwidth();
  1976. $opts->{constants}{"h$img_num"} = $img->getheight();
  1977. $opts->{constants}{"cx$img_num"} = $img->getwidth()/2;
  1978. $opts->{constants}{"cy$img_num"} = $img->getheight()/2;
  1979. ++$img_num;
  1980. }
  1981. }
  1982. if ($width) {
  1983. $opts->{constants}{w} = $width;
  1984. $opts->{constants}{cx} = $width/2;
  1985. }
  1986. else {
  1987. $Imager::ERRSTR = "No width supplied";
  1988. return;
  1989. }
  1990. if ($height) {
  1991. $opts->{constants}{h} = $height;
  1992. $opts->{constants}{cy} = $height/2;
  1993. }
  1994. else {
  1995. $Imager::ERRSTR = "No height supplied";
  1996. return;
  1997. }
  1998. my $code = Imager::Expr->new($opts);
  1999. if (!$code) {
  2000. $Imager::ERRSTR = Imager::Expr::error();
  2001. return;
  2002. }
  2003. my $channels = $opts->{channels} || 3;
  2004. unless ($channels >= 1 && $channels <= 4) {
  2005. return Imager->_set_error("channels must be an integer between 1 and 4");
  2006. }
  2007. my $img = Imager->new();
  2008. $img->{IMG} = i_transform2($opts->{width}, $opts->{height},
  2009. $channels, $code->code(),
  2010. $code->nregs(), $code->cregs(),
  2011. [ map { $_->{IMG} } @imgs ]);
  2012. if (!defined $img->{IMG}) {
  2013. $Imager::ERRSTR = Imager->_error_as_msg();
  2014. return;
  2015. }
  2016. return $img;
  2017. }
  2018. sub rubthrough {
  2019. my $self=shift;
  2020. my %opts=(tx => 0,ty => 0, @_);
  2021. unless ($self->{IMG}) {
  2022. $self->{ERRSTR}='empty input image';
  2023. return undef;
  2024. }
  2025. unless ($opts{src} && $opts{src}->{IMG}) {
  2026. $self->{ERRSTR}='empty input image for src';
  2027. return undef;
  2028. }
  2029. %opts = (src_minx => 0,
  2030. src_miny => 0,
  2031. src_maxx => $opts{src}->getwidth(),
  2032. src_maxy => $opts{src}->getheight(),
  2033. %opts);
  2034. unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty},
  2035. $opts{src_minx}, $opts{src_miny},
  2036. $opts{src_maxx}, $opts{src_maxy})) {
  2037. $self->_set_error($self->_error_as_msg());
  2038. return undef;
  2039. }
  2040. return $self;
  2041. }
  2042. sub flip {
  2043. my $self = shift;
  2044. my %opts = @_;
  2045. my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
  2046. my $dir;
  2047. return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
  2048. $dir = $xlate{$opts{'dir'}};
  2049. return $self if i_flipxy($self->{IMG}, $dir);
  2050. return ();
  2051. }
  2052. sub rotate {
  2053. my $self = shift;
  2054. my %opts = @_;
  2055. unless (defined wantarray) {
  2056. my @caller = caller;
  2057. warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
  2058. return;
  2059. }
  2060. if (defined $opts{right}) {
  2061. my $degrees = $opts{right};
  2062. if ($degrees < 0) {
  2063. $degrees += 360 * int(((-$degrees)+360)/360);
  2064. }
  2065. $degrees = $degrees % 360;
  2066. if ($degrees == 0) {
  2067. return $self->copy();
  2068. }
  2069. elsif ($degrees == 90 || $degrees == 180 || $degrees == 270) {
  2070. my $result = Imager->new();
  2071. if ($result->{IMG} = i_rotate90($self->{IMG}, $degrees)) {
  2072. return $result;
  2073. }
  2074. else {
  2075. $self->{ERRSTR} = $self->_error_as_msg();
  2076. return undef;
  2077. }
  2078. }
  2079. else {
  2080. $self->{ERRSTR} = "Parameter 'right' must be a multiple of 90 degrees";
  2081. return undef;
  2082. }
  2083. }
  2084. elsif (defined $opts{radians} || defined $opts{degrees}) {
  2085. my $amount = $opts{radians} || $opts{degrees} * 3.1415926535 / 180;
  2086. my $back = $opts{back};
  2087. my $result = Imager->new;
  2088. if ($back) {
  2089. $back = _color($back);
  2090. unless ($back) {
  2091. $self->_set_error(Imager->errstr);
  2092. return undef;
  2093. }
  2094. $result->{IMG} = i_rotate_exact($self->{IMG}, $amount, $back);
  2095. }
  2096. else {
  2097. $result->{IMG} = i_rotate_exact($self->{IMG}, $amount);
  2098. }
  2099. if ($result->{IMG}) {
  2100. return $result;
  2101. }
  2102. else {
  2103. $self->{ERRSTR} = $self->_error_as_msg();
  2104. return undef;
  2105. }
  2106. }
  2107. else {
  2108. $self->{ERRSTR} = "Only the 'right', 'radians' and 'degrees' parameters are available";
  2109. return undef;
  2110. }
  2111. }
  2112. sub matrix_transform {
  2113. my $self = shift;
  2114. my %opts = @_;
  2115. unless (defined wantarray) {
  2116. my @caller = caller;
  2117. warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
  2118. return;
  2119. }
  2120. if ($opts{matrix}) {
  2121. my $xsize = $opts{xsize} || $self->getwidth;
  2122. my $ysize = $opts{ysize} || $self->getheight;
  2123. my $result = Imager->new;
  2124. if ($opts{back}) {
  2125. $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
  2126. $opts{matrix}, $opts{back})
  2127. or return undef;
  2128. }
  2129. else {
  2130. $result->{IMG} = i_matrix_transform($self->{IMG}, $xsize, $ysize,
  2131. $opts{matrix})
  2132. or return undef;
  2133. }
  2134. return $result;
  2135. }
  2136. else {
  2137. $self->{ERRSTR} = "matrix parameter required";
  2138. return undef;
  2139. }
  2140. }
  2141. # blame Leolo :)
  2142. *yatf = \&matrix_transform;
  2143. # These two are supported for legacy code only
  2144. sub i_color_new {
  2145. return Imager::Color->new(@_);
  2146. }
  2147. sub i_color_set {
  2148. return Imager::Color::set(@_);
  2149. }
  2150. # Draws a box between the specified corner points.
  2151. sub box {
  2152. my $self=shift;
  2153. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  2154. my $dflcl=i_color_new(255,255,255,255);
  2155. my %opts=(color=>$dflcl,xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_);
  2156. if (exists $opts{'box'}) {
  2157. $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]);
  2158. $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]);
  2159. $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]);
  2160. $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]);
  2161. }
  2162. if ($opts{filled}) {
  2163. my $color = _color($opts{'color'});
  2164. unless ($color) {
  2165. $self->{ERRSTR} = $Imager::ERRSTR;
  2166. return;
  2167. }
  2168. i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
  2169. $opts{ymax}, $color);
  2170. }
  2171. elsif ($opts{fill}) {
  2172. unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
  2173. # assume it's a hash ref
  2174. require 'Imager/Fill.pm';
  2175. unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  2176. $self->{ERRSTR} = $Imager::ERRSTR;
  2177. return undef;
  2178. }
  2179. }
  2180. i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},
  2181. $opts{ymax},$opts{fill}{fill});
  2182. }
  2183. else {
  2184. my $color = _color($opts{'color'});
  2185. unless ($color) {
  2186. $self->{ERRSTR} = $Imager::ERRSTR;
  2187. return;
  2188. }
  2189. i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax},
  2190. $color);
  2191. }
  2192. return $self;
  2193. }
  2194. sub arc {
  2195. my $self=shift;
  2196. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  2197. my $dflcl=i_color_new(255,255,255,255);
  2198. my %opts=(color=>$dflcl,
  2199. 'r'=>_min($self->getwidth(),$self->getheight())/3,
  2200. 'x'=>$self->getwidth()/2,
  2201. 'y'=>$self->getheight()/2,
  2202. 'd1'=>0, 'd2'=>361, @_);
  2203. if ($opts{aa}) {
  2204. if ($opts{fill}) {
  2205. unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
  2206. # assume it's a hash ref
  2207. require 'Imager/Fill.pm';
  2208. unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  2209. $self->{ERRSTR} = $Imager::ERRSTR;
  2210. return;
  2211. }
  2212. }
  2213. i_arc_aa_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
  2214. $opts{'d2'}, $opts{fill}{fill});
  2215. }
  2216. else {
  2217. my $color = _color($opts{'color'});
  2218. unless ($color) {
  2219. $self->{ERRSTR} = $Imager::ERRSTR;
  2220. return;
  2221. }
  2222. if ($opts{d1} == 0 && $opts{d2} == 361 && $opts{aa}) {
  2223. i_circle_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{'r'},
  2224. $color);
  2225. }
  2226. else {
  2227. i_arc_aa($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
  2228. $opts{'d1'}, $opts{'d2'}, $color);
  2229. }
  2230. }
  2231. }
  2232. else {
  2233. if ($opts{fill}) {
  2234. unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
  2235. # assume it's a hash ref
  2236. require 'Imager/Fill.pm';
  2237. unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  2238. $self->{ERRSTR} = $Imager::ERRSTR;
  2239. return;
  2240. }
  2241. }
  2242. i_arc_cfill($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},$opts{'d1'},
  2243. $opts{'d2'}, $opts{fill}{fill});
  2244. }
  2245. else {
  2246. my $color = _color($opts{'color'});
  2247. unless ($color) {
  2248. $self->{ERRSTR} = $Imager::ERRSTR;
  2249. return;
  2250. }
  2251. i_arc($self->{IMG},$opts{'x'},$opts{'y'},$opts{'r'},
  2252. $opts{'d1'}, $opts{'d2'}, $color);
  2253. }
  2254. }
  2255. return $self;
  2256. }
  2257. # Draws a line from one point to the other
  2258. # the endpoint is set if the endp parameter is set which it is by default.
  2259. # to turn of the endpoint being set use endp=>0 when calling line.
  2260. sub line {
  2261. my $self=shift;
  2262. my $dflcl=i_color_new(0,0,0,0);
  2263. my %opts=(color=>$dflcl,
  2264. endp => 1,
  2265. @_);
  2266. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  2267. unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
  2268. unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
  2269. my $color = _color($opts{'color'});
  2270. unless ($color) {
  2271. $self->{ERRSTR} = $Imager::ERRSTR;
  2272. return;
  2273. }
  2274. $opts{antialias} = $opts{aa} if defined $opts{aa};
  2275. if ($opts{antialias}) {
  2276. i_line_aa($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
  2277. $color, $opts{endp});
  2278. } else {
  2279. i_line($self->{IMG},$opts{x1}, $opts{y1}, $opts{x2}, $opts{y2},
  2280. $color, $opts{endp});
  2281. }
  2282. return $self;
  2283. }
  2284. # Draws a line between an ordered set of points - It more or less just transforms this
  2285. # into a list of lines.
  2286. sub polyline {
  2287. my $self=shift;
  2288. my ($pt,$ls,@points);
  2289. my $dflcl=i_color_new(0,0,0,0);
  2290. my %opts=(color=>$dflcl,@_);
  2291. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  2292. if (exists($opts{points})) { @points=@{$opts{points}}; }
  2293. if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
  2294. @points=map { [ $opts{'x'}->[$_],$opts{'y'}->[$_] ] } (0..(scalar @{$opts{'x'}}-1));
  2295. }
  2296. # print Dumper(\@points);
  2297. my $color = _color($opts{'color'});
  2298. unless ($color) {
  2299. $self->{ERRSTR} = $Imager::ERRSTR;
  2300. return;
  2301. }
  2302. $opts{antialias} = $opts{aa} if defined $opts{aa};
  2303. if ($opts{antialias}) {
  2304. for $pt(@points) {
  2305. if (defined($ls)) {
  2306. i_line_aa($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color, 1);
  2307. }
  2308. $ls=$pt;
  2309. }
  2310. } else {
  2311. for $pt(@points) {
  2312. if (defined($ls)) {
  2313. i_line($self->{IMG},$ls->[0],$ls->[1],$pt->[0],$pt->[1],$color,1);
  2314. }
  2315. $ls=$pt;
  2316. }
  2317. }
  2318. return $self;
  2319. }
  2320. sub polygon {
  2321. my $self = shift;
  2322. my ($pt,$ls,@points);
  2323. my $dflcl = i_color_new(0,0,0,0);
  2324. my %opts = (color=>$dflcl, @_);
  2325. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  2326. if (exists($opts{points})) {
  2327. $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
  2328. $opts{'y'} = [ map { $_->[1] } @{$opts{points}} ];
  2329. }
  2330. if (!exists $opts{'x'} or !exists $opts{'y'}) {
  2331. $self->{ERRSTR} = 'no points array, or x and y arrays.'; return undef;
  2332. }
  2333. if ($opts{'fill'}) {
  2334. unless (UNIVERSAL::isa($opts{'fill'}, 'Imager::Fill')) {
  2335. # assume it's a hash ref
  2336. require 'Imager/Fill.pm';
  2337. unless ($opts{'fill'} = Imager::Fill->new(%{$opts{'fill'}})) {
  2338. $self->{ERRSTR} = $Imager::ERRSTR;
  2339. return undef;
  2340. }
  2341. }
  2342. i_poly_aa_cfill($self->{IMG}, $opts{'x'}, $opts{'y'},
  2343. $opts{'fill'}{'fill'});
  2344. }
  2345. else {
  2346. my $color = _color($opts{'color'});
  2347. unless ($color) {
  2348. $self->{ERRSTR} = $Imager::ERRSTR;
  2349. return;
  2350. }
  2351. i_poly_aa($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
  2352. }
  2353. return $self;
  2354. }
  2355. # this the multipoint bezier curve
  2356. # this is here more for testing that actual usage since
  2357. # this is not a good algorithm. Usually the curve would be
  2358. # broken into smaller segments and each done individually.
  2359. sub polybezier {
  2360. my $self=shift;
  2361. my ($pt,$ls,@points);
  2362. my $dflcl=i_color_new(0,0,0,0);
  2363. my %opts=(color=>$dflcl,@_);
  2364. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  2365. if (exists $opts{points}) {
  2366. $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
  2367. $opts{'y'}=map { $_->[1]; } @{$opts{'points'}};
  2368. }
  2369. unless ( @{$opts{'x'}} and @{$opts{'x'}} == @{$opts{'y'}} ) {
  2370. $self->{ERRSTR}='Missing or invalid points.';
  2371. return;
  2372. }
  2373. my $color = _color($opts{'color'});
  2374. unless ($color) {
  2375. $self->{ERRSTR} = $Imager::ERRSTR;
  2376. return;
  2377. }
  2378. i_bezier_multi($self->{IMG},$opts{'x'},$opts{'y'},$color);
  2379. return $self;
  2380. }
  2381. sub flood_fill {
  2382. my $self = shift;
  2383. my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
  2384. my $rc;
  2385. unless (exists $opts{'x'} && exists $opts{'y'}) {
  2386. $self->{ERRSTR} = "missing seed x and y parameters";
  2387. return undef;
  2388. }
  2389. if ($opts{border}) {
  2390. my $border = _color($opts{border});
  2391. unless ($border) {
  2392. $self->_set_error($Imager::ERRSTR);
  2393. return;
  2394. }
  2395. if ($opts{fill}) {
  2396. unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
  2397. # assume it's a hash ref
  2398. require Imager::Fill;
  2399. unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  2400. $self->{ERRSTR} = $Imager::ERRSTR;
  2401. return;
  2402. }
  2403. }
  2404. $rc = i_flood_cfill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
  2405. $opts{fill}{fill}, $border);
  2406. }
  2407. else {
  2408. my $color = _color($opts{'color'});
  2409. unless ($color) {
  2410. $self->{ERRSTR} = $Imager::ERRSTR;
  2411. return;
  2412. }
  2413. $rc = i_flood_fill_border($self->{IMG}, $opts{'x'}, $opts{'y'},
  2414. $color, $border);
  2415. }
  2416. if ($rc) {
  2417. return $self;
  2418. }
  2419. else {
  2420. $self->{ERRSTR} = $self->_error_as_msg();
  2421. return;
  2422. }
  2423. }
  2424. else {
  2425. if ($opts{fill}) {
  2426. unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) {
  2427. # assume it's a hash ref
  2428. require 'Imager/Fill.pm';
  2429. unless ($opts{fill} = Imager::Fill->new(%{$opts{fill}})) {
  2430. $self->{ERRSTR} = $Imager::ERRSTR;
  2431. return;
  2432. }
  2433. }
  2434. $rc = i_flood_cfill($self->{IMG}, $opts{'x'}, $opts{'y'}, $opts{fill}{fill});
  2435. }
  2436. else {
  2437. my $color = _color($opts{'color'});
  2438. unless ($color) {
  2439. $self->{ERRSTR} = $Imager::ERRSTR;
  2440. return;
  2441. }
  2442. $rc = i_flood_fill($self->{IMG}, $opts{'x'}, $opts{'y'}, $color);
  2443. }
  2444. if ($rc) {
  2445. return $self;
  2446. }
  2447. else {
  2448. $self->{ERRSTR} = $self->_error_as_msg();
  2449. return;
  2450. }
  2451. }
  2452. }
  2453. sub setpixel {
  2454. my $self = shift;
  2455. my %opts = ( color=>$self->{fg} || NC(255, 255, 255), @_);
  2456. unless (exists $opts{'x'} && exists $opts{'y'}) {
  2457. $self->{ERRSTR} = 'missing x and y parameters';
  2458. return undef;
  2459. }
  2460. my $x = $opts{'x'};
  2461. my $y = $opts{'y'};
  2462. my $color = _color($opts{color})
  2463. or return undef;
  2464. if (ref $x && ref $y) {
  2465. unless (@$x == @$y) {
  2466. $self->{ERRSTR} = 'length of x and y mismatch';
  2467. return;
  2468. }
  2469. my $set = 0;
  2470. if ($color->isa('Imager::Color')) {
  2471. for my $i (0..$#{$opts{'x'}}) {
  2472. i_ppix($self->{IMG}, $x->[$i], $y->[$i], $color)
  2473. or ++$set;
  2474. }
  2475. }
  2476. else {
  2477. for my $i (0..$#{$opts{'x'}}) {
  2478. i_ppixf($self->{IMG}, $x->[$i], $y->[$i], $color)
  2479. or ++$set;
  2480. }
  2481. }
  2482. $set or return;
  2483. return $set;
  2484. }
  2485. else {
  2486. if ($color->isa('Imager::Color')) {
  2487. i_ppix($self->{IMG}, $x, $y, $color)
  2488. and return;
  2489. }
  2490. else {
  2491. i_ppixf($self->{IMG}, $x, $y, $color)
  2492. and return;
  2493. }
  2494. }
  2495. $self;
  2496. }
  2497. sub getpixel {
  2498. my $self = shift;
  2499. my %opts = ( "type"=>'8bit', @_);
  2500. unless (exists $opts{'x'} && exists $opts{'y'}) {
  2501. $self->{ERRSTR} = 'missing x and y parameters';
  2502. return undef;
  2503. }
  2504. my $x = $opts{'x'};
  2505. my $y = $opts{'y'};
  2506. if (ref $x && ref $y) {
  2507. unless (@$x == @$y) {
  2508. $self->{ERRSTR} = 'length of x and y mismatch';
  2509. return undef;
  2510. }
  2511. my @result;
  2512. if ($opts{"type"} eq '8bit') {
  2513. for my $i (0..$#{$opts{'x'}}) {
  2514. push(@result, i_get_pixel($self->{IMG}, $x->[$i], $y->[$i]));
  2515. }
  2516. }
  2517. else {
  2518. for my $i (0..$#{$opts{'x'}}) {
  2519. push(@result, i_gpixf($self->{IMG}, $x->[$i], $y->[$i]));
  2520. }
  2521. }
  2522. return wantarray ? @result : \@result;
  2523. }
  2524. else {
  2525. if ($opts{"type"} eq '8bit') {
  2526. return i_get_pixel($self->{IMG}, $x, $y);
  2527. }
  2528. else {
  2529. return i_gpixf($self->{IMG}, $x, $y);
  2530. }
  2531. }
  2532. $self;
  2533. }
  2534. sub getscanline {
  2535. my $self = shift;
  2536. my %opts = ( type => '8bit', x=>0, @_);
  2537. $self->_valid_image or return;
  2538. defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
  2539. unless (defined $opts{'y'}) {
  2540. $self->_set_error("missing y parameter");
  2541. return;
  2542. }
  2543. if ($opts{type} eq '8bit') {
  2544. return i_glin($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
  2545. $opts{'y'});
  2546. }
  2547. elsif ($opts{type} eq 'float') {
  2548. return i_glinf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
  2549. $opts{'y'});
  2550. }
  2551. elsif ($opts{type} eq 'index') {
  2552. unless (i_img_type($self->{IMG})) {
  2553. $self->_set_error("type => index only valid on paletted images");
  2554. return;
  2555. }
  2556. return i_gpal($self->{IMG}, $opts{x}, $opts{x} + $opts{width},
  2557. $opts{'y'});
  2558. }
  2559. else {
  2560. $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
  2561. return;
  2562. }
  2563. }
  2564. sub setscanline {
  2565. my $self = shift;
  2566. my %opts = ( x=>0, @_);
  2567. $self->_valid_image or return;
  2568. unless (defined $opts{'y'}) {
  2569. $self->_set_error("missing y parameter");
  2570. return;
  2571. }
  2572. if (!$opts{type}) {
  2573. if (ref $opts{pixels} && @{$opts{pixels}}) {
  2574. # try to guess the type
  2575. if ($opts{pixels}[0]->isa('Imager::Color')) {
  2576. $opts{type} = '8bit';
  2577. }
  2578. elsif ($opts{pixels}[0]->isa('Imager::Color::Float')) {
  2579. $opts{type} = 'float';
  2580. }
  2581. else {
  2582. $self->_set_error("missing type parameter and could not guess from pixels");
  2583. return;
  2584. }
  2585. }
  2586. else {
  2587. # default
  2588. $opts{type} = '8bit';
  2589. }
  2590. }
  2591. if ($opts{type} eq '8bit') {
  2592. if (ref $opts{pixels}) {
  2593. return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
  2594. }
  2595. else {
  2596. return i_plin($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
  2597. }
  2598. }
  2599. elsif ($opts{type} eq 'float') {
  2600. if (ref $opts{pixels}) {
  2601. return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
  2602. }
  2603. else {
  2604. return i_plinf($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
  2605. }
  2606. }
  2607. elsif ($opts{type} eq 'index') {
  2608. if (ref $opts{pixels}) {
  2609. return i_ppal($self->{IMG}, $opts{x}, $opts{'y'}, @{$opts{pixels}});
  2610. }
  2611. else {
  2612. return i_ppal_p($self->{IMG}, $opts{x}, $opts{'y'}, $opts{pixels});
  2613. }
  2614. }
  2615. else {
  2616. $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
  2617. return;
  2618. }
  2619. }
  2620. sub getsamples {
  2621. my $self = shift;
  2622. my %opts = ( type => '8bit', x=>0, @_);
  2623. defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
  2624. unless (defined $opts{'y'}) {
  2625. $self->_set_error("missing y parameter");
  2626. return;
  2627. }
  2628. unless ($opts{channels}) {
  2629. $opts{channels} = [ 0 .. $self->getchannels()-1 ];
  2630. }
  2631. if ($opts{type} eq '8bit') {
  2632. return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
  2633. $opts{y}, @{$opts{channels}});
  2634. }
  2635. elsif ($opts{type} eq 'float') {
  2636. return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
  2637. $opts{y}, @{$opts{channels}});
  2638. }
  2639. else {
  2640. $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
  2641. return;
  2642. }
  2643. }
  2644. # make an identity matrix of the given size
  2645. sub _identity {
  2646. my ($size) = @_;
  2647. my $matrix = [ map { [ (0) x $size ] } 1..$size ];
  2648. for my $c (0 .. ($size-1)) {
  2649. $matrix->[$c][$c] = 1;
  2650. }
  2651. return $matrix;
  2652. }
  2653. # general function to convert an image
  2654. sub convert {
  2655. my ($self, %opts) = @_;
  2656. my $matrix;
  2657. unless (defined wantarray) {
  2658. my @caller = caller;
  2659. warn "convert() called in void context - convert() returns the converted image at $caller[1] line $caller[2]\n";
  2660. return;
  2661. }
  2662. # the user can either specify a matrix or preset
  2663. # the matrix overrides the preset
  2664. if (!exists($opts{matrix})) {
  2665. unless (exists($opts{preset})) {
  2666. $self->{ERRSTR} = "convert() needs a matrix or preset";
  2667. return;
  2668. }
  2669. else {
  2670. if ($opts{preset} eq 'gray' || $opts{preset} eq 'grey') {
  2671. # convert to greyscale, keeping the alpha channel if any
  2672. if ($self->getchannels == 3) {
  2673. $matrix = [ [ 0.222, 0.707, 0.071 ] ];
  2674. }
  2675. elsif ($self->getchannels == 4) {
  2676. # preserve the alpha channel
  2677. $matrix = [ [ 0.222, 0.707, 0.071, 0 ],
  2678. [ 0, 0, 0, 1 ] ];
  2679. }
  2680. else {
  2681. # an identity
  2682. $matrix = _identity($self->getchannels);
  2683. }
  2684. }
  2685. elsif ($opts{preset} eq 'noalpha') {
  2686. # strip the alpha channel
  2687. if ($self->getchannels == 2 or $self->getchannels == 4) {
  2688. $matrix = _identity($self->getchannels);
  2689. pop(@$matrix); # lose the alpha entry
  2690. }
  2691. else {
  2692. $matrix = _identity($self->getchannels);
  2693. }
  2694. }
  2695. elsif ($opts{preset} eq 'red' || $opts{preset} eq 'channel0') {
  2696. # extract channel 0
  2697. $matrix = [ [ 1 ] ];
  2698. }
  2699. elsif ($opts{preset} eq 'green' || $opts{preset} eq 'channel1') {
  2700. $matrix = [ [ 0, 1 ] ];
  2701. }
  2702. elsif ($opts{preset} eq 'blue' || $opts{preset} eq 'channel2') {
  2703. $matrix = [ [ 0, 0, 1 ] ];
  2704. }
  2705. elsif ($opts{preset} eq 'alpha') {
  2706. if ($self->getchannels == 2 or $self->getchannels == 4) {
  2707. $matrix = [ [ (0) x ($self->getchannels-1), 1 ] ];
  2708. }
  2709. else {
  2710. # the alpha is just 1 <shrug>
  2711. $matrix = [ [ (0) x $self->getchannels, 1 ] ];
  2712. }
  2713. }
  2714. elsif ($opts{preset} eq 'rgb') {
  2715. if ($self->getchannels == 1) {
  2716. $matrix = [ [ 1 ], [ 1 ], [ 1 ] ];
  2717. }
  2718. elsif ($self->getchannels == 2) {
  2719. # preserve the alpha channel
  2720. $matrix = [ [ 1, 0 ], [ 1, 0 ], [ 1, 0 ], [ 0, 1 ] ];
  2721. }
  2722. else {
  2723. $matrix = _identity($self->getchannels);
  2724. }
  2725. }
  2726. elsif ($opts{preset} eq 'addalpha') {
  2727. if ($self->getchannels == 1) {
  2728. $matrix = _identity(2);
  2729. }
  2730. elsif ($self->getchannels == 3) {
  2731. $matrix = _identity(4);
  2732. }
  2733. else {
  2734. $matrix = _identity($self->getchannels);
  2735. }
  2736. }
  2737. else {
  2738. $self->{ERRSTR} = "Unknown convert preset $opts{preset}";
  2739. return undef;
  2740. }
  2741. }
  2742. }
  2743. else {
  2744. $matrix = $opts{matrix};
  2745. }
  2746. my $new = Imager->new;
  2747. $new->{IMG} = i_convert($self->{IMG}, $matrix);
  2748. unless ($new->{IMG}) {
  2749. # most likely a bad matrix
  2750. $self->{ERRSTR} = _error_as_msg();
  2751. return undef;
  2752. }
  2753. return $new;
  2754. }
  2755. # general function to map an image through lookup tables
  2756. sub map {
  2757. my ($self, %opts) = @_;
  2758. my @chlist = qw( red green blue alpha );
  2759. if (!exists($opts{'maps'})) {
  2760. # make maps from channel maps
  2761. my $chnum;
  2762. for $chnum (0..$#chlist) {
  2763. if (exists $opts{$chlist[$chnum]}) {
  2764. $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]};
  2765. } elsif (exists $opts{'all'}) {
  2766. $opts{'maps'}[$chnum] = $opts{'all'};
  2767. }
  2768. }
  2769. }
  2770. if ($opts{'maps'} and $self->{IMG}) {
  2771. i_map($self->{IMG}, $opts{'maps'} );
  2772. }
  2773. return $self;
  2774. }
  2775. sub difference {
  2776. my ($self, %opts) = @_;
  2777. defined $opts{mindist} or $opts{mindist} = 0;
  2778. defined $opts{other}
  2779. or return $self->_set_error("No 'other' parameter supplied");
  2780. defined $opts{other}{IMG}
  2781. or return $self->_set_error("No image data in 'other' image");
  2782. $self->{IMG}
  2783. or return $self->_set_error("No image data");
  2784. my $result = Imager->new;
  2785. $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
  2786. $opts{mindist})
  2787. or return $self->_set_error($self->_error_as_msg());
  2788. return $result;
  2789. }
  2790. # destructive border - image is shrunk by one pixel all around
  2791. sub border {
  2792. my ($self,%opts)=@_;
  2793. my($tx,$ty)=($self->getwidth()-1,$self->getheight()-1);
  2794. $self->polyline('x'=>[0,$tx,$tx,0,0],'y'=>[0,0,$ty,$ty,0],%opts);
  2795. }
  2796. # Get the width of an image
  2797. sub getwidth {
  2798. my $self = shift;
  2799. if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
  2800. return (i_img_info($self->{IMG}))[0];
  2801. }
  2802. # Get the height of an image
  2803. sub getheight {
  2804. my $self = shift;
  2805. if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
  2806. return (i_img_info($self->{IMG}))[1];
  2807. }
  2808. # Get number of channels in an image
  2809. sub getchannels {
  2810. my $self = shift;
  2811. if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
  2812. return i_img_getchannels($self->{IMG});
  2813. }
  2814. # Get channel mask
  2815. sub getmask {
  2816. my $self = shift;
  2817. if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
  2818. return i_img_getmask($self->{IMG});
  2819. }
  2820. # Set channel mask
  2821. sub setmask {
  2822. my $self = shift;
  2823. my %opts = @_;
  2824. if (!defined($self->{IMG})) {
  2825. $self->{ERRSTR} = 'image is empty';
  2826. return undef;
  2827. }
  2828. unless (defined $opts{mask}) {
  2829. $self->_set_error("mask parameter required");
  2830. return;
  2831. }
  2832. i_img_setmask( $self->{IMG} , $opts{mask} );
  2833. 1;
  2834. }
  2835. # Get number of colors in an image
  2836. sub getcolorcount {
  2837. my $self=shift;
  2838. my %opts=('maxcolors'=>2**30,@_);
  2839. if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
  2840. my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
  2841. return ($rc==-1? undef : $rc);
  2842. }
  2843. # Returns a reference to a hash. The keys are colour named (packed) and the
  2844. # values are the number of pixels in this colour.
  2845. sub getcolorusagehash {
  2846. my $self = shift;
  2847. my %opts = ( maxcolors => 2**30, @_ );
  2848. my $max_colors = $opts{maxcolors};
  2849. unless (defined $max_colors && $max_colors > 0) {
  2850. $self->_set_error('maxcolors must be a positive integer');
  2851. return;
  2852. }
  2853. unless (defined $self->{IMG}) {
  2854. $self->_set_error('empty input image');
  2855. return;
  2856. }
  2857. my $channels= $self->getchannels;
  2858. # We don't want to look at the alpha channel, because some gifs using it
  2859. # doesn't define it for every colour (but only for some)
  2860. $channels -= 1 if $channels == 2 or $channels == 4;
  2861. my %color_use;
  2862. my $height = $self->getheight;
  2863. for my $y (0 .. $height - 1) {
  2864. my $colors = $self->getsamples('y' => $y, channels => [ 0 .. $channels - 1 ]);
  2865. while (length $colors) {
  2866. $color_use{ substr($colors, 0, $channels, '') }++;
  2867. }
  2868. keys %color_use > $max_colors
  2869. and return;
  2870. }
  2871. return \%color_use;
  2872. }
  2873. # This will return a ordered array of the colour usage. Kind of the sorted
  2874. # version of the values of the hash returned by getcolorusagehash.
  2875. # You might want to add safety checks and change the names, etc...
  2876. sub getcolorusage {
  2877. my $self = shift;
  2878. my %opts = ( maxcolors => 2**30, @_ );
  2879. my $max_colors = $opts{maxcolors};
  2880. unless (defined $max_colors && $max_colors > 0) {
  2881. $self->_set_error('maxcolors must be a positive integer');
  2882. return;
  2883. }
  2884. unless (defined $self->{IMG}) {
  2885. $self->_set_error('empty input image');
  2886. return undef;
  2887. }
  2888. return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
  2889. }
  2890. # draw string to an image
  2891. sub string {
  2892. my $self = shift;
  2893. unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
  2894. my %input=('x'=>0, 'y'=>0, @_);
  2895. defined($input{string}) or $input{string} = $input{text};
  2896. unless(defined $input{string}) {
  2897. $self->{ERRSTR}="missing required parameter 'string'";
  2898. return;
  2899. }
  2900. unless($input{font}) {
  2901. $self->{ERRSTR}="missing required parameter 'font'";
  2902. return;
  2903. }
  2904. unless ($input{font}->draw(image=>$self, %input)) {
  2905. return;
  2906. }
  2907. return $self;
  2908. }
  2909. sub align_string {
  2910. my $self = shift;
  2911. my $img;
  2912. if (ref $self) {
  2913. unless ($self->{IMG}) {
  2914. $self->{ERRSTR}='empty input image';
  2915. return;
  2916. }
  2917. $img = $self;
  2918. }
  2919. else {
  2920. $img = undef;
  2921. }
  2922. my %input=('x'=>0, 'y'=>0, @_);
  2923. $input{string}||=$input{text};
  2924. unless(exists $input{string}) {
  2925. $self->_set_error("missing required parameter 'string'");
  2926. return;
  2927. }
  2928. unless($input{font}) {
  2929. $self->_set_error("missing required parameter 'font'");
  2930. return;
  2931. }
  2932. my @result;
  2933. unless (@result = $input{font}->align(image=>$img, %input)) {
  2934. return;
  2935. }
  2936. return wantarray ? @result : $result[0];
  2937. }
  2938. my @file_limit_names = qw/width height bytes/;
  2939. sub set_file_limits {
  2940. shift;
  2941. my %opts = @_;
  2942. my %values;
  2943. if ($opts{reset}) {
  2944. @values{@file_limit_names} = (0) x @file_limit_names;
  2945. }
  2946. else {
  2947. @values{@file_limit_names} = i_get_image_file_limits();
  2948. }
  2949. for my $key (keys %values) {
  2950. defined $opts{$key} and $values{$key} = $opts{$key};
  2951. }
  2952. i_set_image_file_limits($values{width}, $values{height}, $values{bytes});
  2953. }
  2954. sub get_file_limits {
  2955. i_get_image_file_limits();
  2956. }
  2957. # Shortcuts that can be exported
  2958. sub newcolor { Imager::Color->new(@_); }
  2959. sub newfont { Imager::Font->new(@_); }
  2960. *NC=*newcolour=*newcolor;
  2961. *NF=*newfont;
  2962. *open=\&read;
  2963. *circle=\&arc;
  2964. #### Utility routines
  2965. sub errstr {
  2966. ref $_[0] ? $_[0]->{ERRSTR} : $ERRSTR
  2967. }
  2968. sub _set_error {
  2969. my ($self, $msg) = @_;
  2970. if (ref $self) {
  2971. $self->{ERRSTR} = $msg;
  2972. }
  2973. else {
  2974. $ERRSTR = $msg;
  2975. }
  2976. return;
  2977. }
  2978. # Default guess for the type of an image from extension
  2979. sub def_guess_type {
  2980. my $name=lc(shift);
  2981. my $ext;
  2982. $ext=($name =~ m/\.([^\.]+)$/)[0];
  2983. return 'tiff' if ($ext =~ m/^tiff?$/);
  2984. return 'jpeg' if ($ext =~ m/^jpe?g$/);
  2985. return 'pnm' if ($ext =~ m/^p[pgb]m$/);
  2986. return 'png' if ($ext eq "png");
  2987. return 'bmp' if ($ext eq "bmp" || $ext eq "dib");
  2988. return 'tga' if ($ext eq "tga");
  2989. return 'sgi' if ($ext eq "rgb" || $ext eq "bw" || $ext eq "sgi" || $ext eq "rgba");
  2990. return 'gif' if ($ext eq "gif");
  2991. return 'raw' if ($ext eq "raw");
  2992. return lc $ext; # best guess
  2993. return ();
  2994. }
  2995. # get the minimum of a list
  2996. sub _min {
  2997. my $mx=shift;
  2998. for(@_) { if ($_<$mx) { $mx=$_; }}
  2999. return $mx;
  3000. }
  3001. # get the maximum of a list
  3002. sub _max {
  3003. my $mx=shift;
  3004. for(@_) { if ($_>$mx) { $mx=$_; }}
  3005. return $mx;
  3006. }
  3007. # string stuff for iptc headers
  3008. sub _clean {
  3009. my($str)=$_[0];
  3010. $str = substr($str,3);
  3011. $str =~ s/[\n\r]//g;
  3012. $str =~ s/\s+/ /g;
  3013. $str =~ s/^\s//;
  3014. $str =~ s/\s$//;
  3015. return $str;
  3016. }
  3017. # A little hack to parse iptc headers.
  3018. sub parseiptc {
  3019. my $self=shift;
  3020. my(@sar,$item,@ar);
  3021. my($caption,$photogr,$headln,$credit);
  3022. my $str=$self->{IPTCRAW};
  3023. defined $str
  3024. or return;
  3025. @ar=split(/8BIM/,$str);
  3026. my $i=0;
  3027. foreach (@ar) {
  3028. if (/^\004\004/) {
  3029. @sar=split(/\034\002/);
  3030. foreach $item (@sar) {
  3031. if ($item =~ m/^x/) {
  3032. $caption = _clean($item);
  3033. $i++;
  3034. }
  3035. if ($item =~ m/^P/) {
  3036. $photogr = _clean($item);
  3037. $i++;
  3038. }
  3039. if ($item =~ m/^i/) {
  3040. $headln = _clean($item);
  3041. $i++;
  3042. }
  3043. if ($item =~ m/^n/) {
  3044. $credit = _clean($item);
  3045. $i++;
  3046. }
  3047. }
  3048. }
  3049. }
  3050. return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
  3051. }
  3052. sub Inline {
  3053. my ($lang) = @_;
  3054. $lang eq 'C'
  3055. or die "Only C language supported";
  3056. require Imager::ExtUtils;
  3057. return Imager::ExtUtils->inline_config;
  3058. }
  3059. 1;
  3060. __END__
  3061. # Below is the stub of documentation for your module. You better edit it!
  3062. =head1 NAME
  3063. Imager - Perl extension for Generating 24 bit Images
  3064. =head1 SYNOPSIS
  3065. # Thumbnail example
  3066. #!/usr/bin/perl -w
  3067. use strict;
  3068. use Imager;
  3069. die "Usage: thumbmake.pl filename\n" if !-f $ARGV[0];
  3070. my $file = shift;
  3071. my $format;
  3072. my $img = Imager->new();
  3073. # see Imager::Files for information on the read() method
  3074. $img->read(file=>$file) or die $img->errstr();
  3075. $file =~ s/\.[^.]*$//;
  3076. # Create smaller version
  3077. # documented in Imager::Transformations
  3078. my $thumb = $img->scale(scalefactor=>.3);
  3079. # Autostretch individual channels
  3080. $thumb->filter(type=>'autolevels');
  3081. # try to save in one of these formats
  3082. SAVE:
  3083. for $format ( qw( png gif jpg tiff ppm ) ) {
  3084. # Check if given format is supported
  3085. if ($Imager::formats{$format}) {
  3086. $file.="_low.$format";
  3087. print "Storing image as: $file\n";
  3088. # documented in Imager::Files
  3089. $thumb->write(file=>$file) or
  3090. die $thumb->errstr;
  3091. last SAVE;
  3092. }
  3093. }
  3094. =head1 DESCRIPTION
  3095. Imager is a module for creating and altering images. It can read and
  3096. write various image formats, draw primitive shapes like lines,and
  3097. polygons, blend multiple images together in various ways, scale, crop,
  3098. render text and more.
  3099. =head2 Overview of documentation
  3100. =over
  3101. =item *
  3102. Imager - This document - Synopsis, Example, Table of Contents and
  3103. Overview.
  3104. =item *
  3105. L<Imager::Tutorial> - a brief introduction to Imager.
  3106. =item *
  3107. L<Imager::Cookbook> - how to do various things with Imager.
  3108. =item *
  3109. L<Imager::ImageTypes> - Basics of constructing image objects with
  3110. C<new()>: Direct type/virtual images, RGB(A)/paletted images,
  3111. 8/16/double bits/channel, color maps, channel masks, image tags, color
  3112. quantization. Also discusses basic image information methods.
  3113. =item *
  3114. L<Imager::Files> - IO interaction, reading/writing images, format
  3115. specific tags.
  3116. =item *
  3117. L<Imager::Draw> - Drawing Primitives, lines, boxes, circles, arcs,
  3118. flood fill.
  3119. =item *
  3120. L<Imager::Color> - Color specification.
  3121. =item *
  3122. L<Imager::Fill> - Fill pattern specification.
  3123. =item *
  3124. L<Imager::Font> - General font rendering, bounding boxes and font
  3125. metrics.
  3126. =item *
  3127. L<Imager::Transformations> - Copying, scaling, cropping, flipping,
  3128. blending, pasting, convert and map.
  3129. =item *
  3130. L<Imager::Engines> - Programmable transformations through
  3131. C<transform()>, C<transform2()> and C<matrix_transform()>.
  3132. =item *
  3133. L<Imager::Filters> - Filters, sharpen, blur, noise, convolve etc. and
  3134. filter plugins.
  3135. =item *
  3136. L<Imager::Expr> - Expressions for evaluation engine used by
  3137. transform2().
  3138. =item *
  3139. L<Imager::Matrix2d> - Helper class for affine transformations.
  3140. =item *
  3141. L<Imager::Fountain> - Helper for making gradient profiles.
  3142. =item *
  3143. L<Imager::API> - using Imager's C API
  3144. =item *
  3145. L<Imager::APIRef> - API function reference
  3146. =item *
  3147. L<Imager::Inline> - using Imager's C API from Inline::C
  3148. =item *
  3149. L<Imager::ExtUtils> - tools to get access to Imager's C API.
  3150. =back
  3151. =head2 Basic Overview
  3152. An Image object is created with C<$img = Imager-E<gt>new()>.
  3153. Examples:
  3154. $img=Imager->new(); # create empty image
  3155. $img->read(file=>'lena.png',type=>'png') or # read image from file
  3156. die $img->errstr(); # give an explanation
  3157. # if something failed
  3158. or if you want to create an empty image:
  3159. $img=Imager->new(xsize=>400,ysize=>300,channels=>4);
  3160. This example creates a completely black image of width 400 and height
  3161. 300 and 4 channels.
  3162. =head1 ERROR HANDLING
  3163. In general a method will return false when it fails, if it does use the errstr() method to find out why:
  3164. =over
  3165. =item errstr
  3166. Returns the last error message in that context.
  3167. If the last error you received was from calling an object method, such
  3168. as read, call errstr() as an object method to find out why:
  3169. my $image = Imager->new;
  3170. $image->read(file => 'somefile.gif')
  3171. or die $image->errstr;
  3172. If it was a class method then call errstr() as a class method:
  3173. my @imgs = Imager->read_multi(file => 'somefile.gif')
  3174. or die Imager->errstr;
  3175. Note that in some cases object methods are implemented in terms of
  3176. class methods so a failing object method may set both.
  3177. =back
  3178. The C<Imager-E<gt>new> method is described in detail in
  3179. L<Imager::ImageTypes>.
  3180. =head1 METHOD INDEX
  3181. Where to find information on methods for Imager class objects.
  3182. addcolors() - L<Imager::ImageTypes/addcolors>
  3183. addtag() - L<Imager::ImageTypes/addtag> - add image tags
  3184. align_string() - L<Imager::Draw/align_string>
  3185. arc() - L<Imager::Draw/arc>
  3186. bits() - L<Imager::ImageTypes/bits> - number of bits per sample for the
  3187. image
  3188. box() - L<Imager::Draw/box>
  3189. circle() - L<Imager::Draw/circle>
  3190. colorcount() - L<Imager::Draw/colorcount>
  3191. convert() - L<Imager::Transformations/"Color transformations"> -
  3192. transform the color space
  3193. copy() - L<Imager::Transformations/copy>
  3194. crop() - L<Imager::Transformations/crop> - extract part of an image
  3195. def_guess_type() - L<Imager::Files/def_guess_type>
  3196. deltag() - L<Imager::ImageTypes/deltag> - delete image tags
  3197. difference() - L<Imager::Filters/"Image Difference">
  3198. errstr() - L<"Basic Overview">
  3199. filter() - L<Imager::Filters>
  3200. findcolor() - L<Imager::ImageTypes/findcolor> - search the image palette, if it
  3201. has one
  3202. flip() - L<Imager::Transformations/flip>
  3203. flood_fill() - L<Imager::Draw/flood_fill>
  3204. getchannels() - L<Imager::ImageTypes/getchannels>
  3205. getcolorcount() - L<Imager::ImageTypes/getcolorcount>
  3206. getcolors() - L<Imager::ImageTypes/getcolors> - get colors from the image
  3207. palette, if it has one
  3208. getcolorusage() - L<Imager::ImageTypes/getcolorusage>
  3209. getcolorusagehash() - L<Imager::ImageTypes/getcolorusagehash>
  3210. get_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
  3211. getheight() - L<Imager::ImageTypes/getwidth>
  3212. getmask() - L<Imager::ImageTypes/getmask>
  3213. getpixel() - L<Imager::Draw/getpixel>
  3214. getsamples() - L<Imager::Draw/getsamples>
  3215. getscanline() - L<Imager::Draw/getscanline>
  3216. getwidth() - L<Imager::ImageTypes/getwidth>
  3217. img_set() - L<Imager::ImageTypes/img_set>
  3218. init() - L<Imager::ImageTypes/init>
  3219. line() - L<Imager::Draw/line>
  3220. load_plugin() - L<Imager::Filters/load_plugin>
  3221. map() - L<Imager::Transformations/"Color Mappings"> - remap color
  3222. channel values
  3223. masked() - L<Imager::ImageTypes/masked> - make a masked image
  3224. matrix_transform() - L<Imager::Engines/matrix_transform>
  3225. maxcolors() - L<Imager::ImageTypes/maxcolors>
  3226. NC() - L<Imager::Handy/NC>
  3227. new() - L<Imager::ImageTypes/new>
  3228. newcolor() - L<Imager::Handy/newcolor>
  3229. newcolour() - L<Imager::Handy/newcolour>
  3230. newfont() - L<Imager::Handy/newfont>
  3231. NF() - L<Imager::Handy/NF>
  3232. open() - L<Imager::Files> - an alias for read()
  3233. parseiptc() - L<Imager::Files/parseiptc> - parse IPTC data from a JPEG
  3234. image
  3235. paste() - L<Imager::Transformations/paste> - draw an image onto an image
  3236. polygon() - L<Imager::Draw/polygon>
  3237. polyline() - L<Imager::Draw/polyline>
  3238. read() - L<Imager::Files> - read a single image from an image file
  3239. read_multi() - L<Imager::Files> - read multiple images from an image
  3240. file
  3241. register_filter() - L<Imager::Filters/register_filter>
  3242. register_reader() - L<Imager::Filters/register_reader>
  3243. register_writer() - L<Imager::Filters/register_writer>
  3244. rotate() - L<Imager::Transformations/rotate>
  3245. rubthrough() - L<Imager::Transformations/rubthrough> - draw an image onto an
  3246. image and use the alpha channel
  3247. scale() - L<Imager::Transformations/scale>
  3248. scaleX() - L<Imager::Transformations/scaleX>
  3249. scaleY() - L<Imager::Transformations/scaleY>
  3250. setcolors() - L<Imager::ImageTypes/setcolors> - set palette colors in
  3251. a paletted image
  3252. set_file_limits() - L<Imager::Files/"Limiting the sizes of images you read">
  3253. setmask() - L<Imager::ImageTypes/setmask>
  3254. setpixel() - L<Imager::Draw/setpixel>
  3255. setscanline() - L<Imager::Draw/setscanline>
  3256. settag() - L<Imager::ImageTypes/settag>
  3257. string() - L<Imager::Draw/string> - draw text on an image
  3258. tags() - L<Imager::ImageTypes/tags> - fetch image tags
  3259. to_paletted() - L<Imager::ImageTypes/to_paletted>
  3260. to_rgb16() - L<Imager::ImageTypes/to_rgb16>
  3261. to_rgb8() - L<Imager::ImageTypes/to_rgb8>
  3262. transform() - L<Imager::Engines/"transform">
  3263. transform2() - L<Imager::Engines/"transform2">
  3264. type() - L<Imager::ImageTypes/type> - type of image (direct vs paletted)
  3265. unload_plugin() - L<Imager::Filters/unload_plugin>
  3266. virtual() - L<Imager::ImageTypes/virtual> - whether the image has it's own
  3267. data
  3268. write() - L<Imager::Files> - write an image to a file
  3269. write_multi() - L<Imager::Files> - write multiple image to an image
  3270. file.
  3271. =head1 CONCEPT INDEX
  3272. animated GIF - L<Imager::File/"Writing an animated GIF">
  3273. aspect ratio - L<Imager::ImageTypes/i_xres>,
  3274. L<Imager::ImageTypes/i_yres>, L<Imager::ImageTypes/i_aspect_only>
  3275. blend - alpha blending one image onto another
  3276. L<Imager::Transformations/rubthrough>
  3277. blur - L<Imager::Filters/guassian>, L<Imager::Filters/conv>
  3278. boxes, drawing - L<Imager::Draw/box>
  3279. changes between image - L<Imager::Filter/"Image Difference">
  3280. color - L<Imager::Color>
  3281. color names - L<Imager::Color>, L<Imager::Color::Table>
  3282. combine modes - L<Imager::Fill/combine>
  3283. compare images - L<Imager::Filter/"Image Difference">
  3284. contrast - L<Imager::Filter/contrast>, L<Imager::Filter/autolevels>
  3285. convolution - L<Imager::Filter/conv>
  3286. cropping - L<Imager::Transformations/crop>
  3287. CUR files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
  3288. C<diff> images - L<Imager::Filter/"Image Difference">
  3289. dpi - L<Imager::ImageTypes/i_xres>,
  3290. L<Imager::Cookbook/"Image spatial resolution">
  3291. drawing boxes - L<Imager::Draw/box>
  3292. drawing lines - L<Imager::Draw/line>
  3293. drawing text - L<Imager::Draw/string>, L<Imager::Draw/align_string>
  3294. error message - L<"Basic Overview">
  3295. files, font - L<Imager::Font>
  3296. files, image - L<Imager::Files>
  3297. filling, types of fill - L<Imager::Fill>
  3298. filling, boxes - L<Imager::Draw/box>
  3299. filling, flood fill - L<Imager::Draw/flood_fill>
  3300. flood fill - L<Imager::Draw/flood_fill>
  3301. fonts - L<Imager::Font>
  3302. fonts, drawing with - L<Imager::Draw/string>,
  3303. L<Imager::Draw/align_string>, L<Imager::Font::Wrap>
  3304. fonts, metrics - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
  3305. fonts, multiple master - L<Imager::Font/"MULTIPLE MASTER FONTS">
  3306. fountain fill - L<Imager::Fill/"Fountain fills">,
  3307. L<Imager::Filters/fountain>, L<Imager::Fountain>,
  3308. L<Imager::Filters/gradgen>
  3309. GIF files - L<Imager::Files/"GIF">
  3310. GIF files, animated - L<Imager::File/"Writing an animated GIF">
  3311. gradient fill - L<Imager::Fill/"Fountain fills">,
  3312. L<Imager::Filters/fountain>, L<Imager::Fountain>,
  3313. L<Imager::Filters/gradgen>
  3314. guassian blur - L<Imager::Filter/guassian>
  3315. hatch fills - L<Imager::Fill/"Hatched fills">
  3316. ICO files - L<Imager::Files/"ICO (Microsoft Windows Icon) and CUR (Microsoft Windows Cursor)">
  3317. invert image - L<Imager::Filter/hardinvert>
  3318. JPEG - L<Imager::Files/"JPEG">
  3319. limiting image sizes - L<Imager::Files/"Limiting the sizes of images you read">
  3320. lines, drawing - L<Imager::Draw/line>
  3321. matrix - L<Imager::Matrix2d>,
  3322. L<Imager::Transformations/"Matrix Transformations">,
  3323. L<Imager::Font/transform>
  3324. metadata, image - L<Imager::ImageTypes/"Tags">
  3325. mosaic - L<Imager::Filter/mosaic>
  3326. noise, filter - L<Imager::Filter/noise>
  3327. noise, rendered - L<Imager::Filter/turbnoise>,
  3328. L<Imager::Filter/radnoise>
  3329. paste - L<Imager::Transformations/paste>,
  3330. L<Imager::Transformations/rubthrough>
  3331. pseudo-color image - L<Imager::ImageTypes/to_paletted>,
  3332. L<Imager::ImageTypes/new>
  3333. posterize - L<Imager::Filter/postlevels>
  3334. png files - L<Imager::Files>, L<Imager::Files/"PNG">
  3335. pnm - L<Imager::Files/"PNM (Portable aNy Map)">
  3336. rectangles, drawing - L<Imager::Draw/box>
  3337. resizing an image - L<Imager::Transformations/scale>,
  3338. L<Imager::Transformations/crop>
  3339. RGB (SGI) files - L<Imager::Files/"SGI (RGB, BW)">
  3340. saving an image - L<Imager::Files>
  3341. scaling - L<Imager::Transformations/scale>
  3342. SGI files - L<Imager::Files/"SGI (RGB, BW)">
  3343. sharpen - L<Imager::Filters/unsharpmask>, L<Imager::Filters/conv>
  3344. size, image - L<Imager::ImageTypes/getwidth>,
  3345. L<Imager::ImageTypes/getheight>
  3346. size, text - L<Imager::Font/bounding_box>
  3347. tags, image metadata - L<Imager::ImageTypes/"Tags">
  3348. text, drawing - L<Imager::Draw/string>, L<Imager::Draw/align_string>,
  3349. L<Imager::Font::Wrap>
  3350. text, wrapping text in an area - L<Imager::Font::Wrap>
  3351. text, measuring - L<Imager::Font/bounding_box>, L<Imager::Font::BBox>
  3352. tiles, color - L<Imager::Filter/mosaic>
  3353. unsharp mask - L<Imager::Filter/unsharpmask>
  3354. watermark - L<Imager::Filter/watermark>
  3355. writing an image to a file - L<Imager::Files>
  3356. =head1 SUPPORT
  3357. The best place to get help with Imager is the mailing list.
  3358. To subscribe send a message with C<subscribe> in the body to:
  3359. imager-devel+request@molar.is
  3360. or use the form at:
  3361. =over
  3362. L<http://www.molar.is/en/lists/imager-devel/>
  3363. =back
  3364. where you can also find the mailing list archive.
  3365. You can report bugs by pointing your browser at:
  3366. =over
  3367. L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager>
  3368. =back
  3369. or by sending an email to:
  3370. =over
  3371. bug-Imager@rt.cpan.org
  3372. =back
  3373. Please remember to include the versions of Imager, perl, supporting
  3374. libraries, and any relevant code. If you have specific images that
  3375. cause the problems, please include those too.
  3376. If you don't want to publish your email address on a mailing list you
  3377. can use CPAN::Forum:
  3378. http://www.cpanforum.com/dist/Imager
  3379. You will need to register to post.
  3380. =head1 CONTRIBUTING TO IMAGER
  3381. =head2 Feedback
  3382. I like feedback.
  3383. If you like or dislike Imager, you can add a public review of Imager
  3384. at CPAN Ratings:
  3385. http://cpanratings.perl.org/dist/Imager
  3386. This requires a Bitcard Account (http://www.bitcard.org).
  3387. You can also send email to the maintainer below.
  3388. If you send me a bug report via email, it will be copied to RT.
  3389. =head2 Patches
  3390. I accept patches, preferably against the main branch in subversion.
  3391. You should include an explanation of the reason for why the patch is
  3392. needed or useful.
  3393. Your patch should include regression tests where possible, otherwise
  3394. it will be delayed until I get a chance to write them.
  3395. =head1 AUTHOR
  3396. Tony Cook <tony@imager.perl.org> is the current maintainer for Imager.
  3397. Arnar M. Hrafnkelsson is the original author of Imager.
  3398. Many others have contributed to Imager, please see the README for a
  3399. complete list.
  3400. =head1 SEE ALSO
  3401. L<perl>(1), L<Imager::ImageTypes>(3), L<Imager::Files>(3),
  3402. L<Imager::Draw>(3), L<Imager::Color>(3), L<Imager::Fill>(3),
  3403. L<Imager::Font>(3), L<Imager::Transformations>(3),
  3404. L<Imager::Engines>(3), L<Imager::Filters>(3), L<Imager::Expr>(3),
  3405. L<Imager::Matrix2d>(3), L<Imager::Fountain>(3)
  3406. L<http://imager.perl.org/>
  3407. L<Affix::Infix2Postfix>(3), L<Parse::RecDescent>(3)
  3408. Other perl imaging modules include:
  3409. L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3).
  3410. =cut