complex_transform.pl 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 31 January 2018
  5. # https://github.com/trizen
  6. # Complex transform of an image, by mapping each pixel position to a complex function.
  7. use 5.020;
  8. use strict;
  9. use warnings;
  10. use feature qw(lexical_subs);
  11. use experimental qw(signatures);
  12. use Imager;
  13. use List::Util qw(min max);
  14. use Math::GComplex qw(cplx);
  15. sub map_range ($this, $in_min, $in_max, $out_min, $out_max) {
  16. $this =~ /[0-9]/ or return 0;
  17. ($this - $in_min) * ($out_max - $out_min) / ($in_max - $in_min) + $out_min;
  18. }
  19. sub complex_transform ($file) {
  20. my $img = Imager->new(file => $file);
  21. my $width = $img->getwidth;
  22. my $height = $img->getheight;
  23. my @vals;
  24. foreach my $y (0 .. $height - 1) {
  25. foreach my $x (0 .. $width - 1) {
  26. my $z = cplx(
  27. (2 * $x - $width) / $width,
  28. (2 * $y - $height) / $height,
  29. );
  30. push @vals, [$x, $y, $z->sin->reals];
  31. }
  32. }
  33. my $max_x = max(map { $_->[2] } grep { $_->[2] =~ /[0-9]/ } @vals);
  34. my $max_y = max(map { $_->[3] } grep { $_->[3] =~ /[0-9]/ } @vals);
  35. my $min_x = min(map { $_->[2] } grep { $_->[2] =~ /[0-9]/ } @vals);
  36. my $min_y = min(map { $_->[3] } grep { $_->[3] =~ /[0-9]/ } @vals);
  37. say "X: [$min_x, $max_x]";
  38. say "Y: [$min_y, $max_y]";
  39. my $new_img = Imager->new(
  40. xsize => $width,
  41. ysize => $height,
  42. );
  43. foreach my $val (@vals) {
  44. $new_img->setpixel(
  45. x => sprintf('%.0f', map_range($val->[2], $min_x, $max_x, 0, $width - 1)),
  46. y => sprintf('%.0f', map_range($val->[3], $min_y, $max_y, 0, $height - 1)),
  47. color => $img->getpixel(x => $val->[0], y => $val->[1]),
  48. );
  49. }
  50. return $new_img;
  51. }
  52. sub usage {
  53. die "usage: $0 [input image] [output image]\n";
  54. }
  55. my $input = shift(@ARGV) // usage();
  56. my $output = shift(@ARGV) // 'complex_transform.png';
  57. complex_transform($input)->write(file => $output);