julia_transform.pl 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 11 March 2017
  5. # https://github.com/trizen
  6. # Julia transform of an image.
  7. # See also:
  8. # https://en.wikipedia.org/wiki/Julia_set
  9. use 5.010;
  10. use strict;
  11. use warnings;
  12. use Imager;
  13. use Math::GComplex;
  14. my $file = shift(@ARGV) // die "usage: $0 [image]\n";
  15. sub map_val {
  16. my ($value, $in_min, $in_max, $out_min, $out_max) = @_;
  17. #<<<
  18. ($value - $in_min)
  19. * ($out_max - $out_min)
  20. / ($in_max - $in_min)
  21. + $out_min;
  22. #>>>
  23. }
  24. my $img = Imager->new(file => $file)
  25. or die Imager->errstr();
  26. my $width = $img->getwidth;
  27. my $height = $img->getheight;
  28. sub transform {
  29. my ($x, $y) = @_;
  30. #<<<
  31. my $z = Math::GComplex->new(
  32. (2 * $x - $width ) / $width,
  33. (2 * $y - $height) / $height,
  34. );
  35. #>>>
  36. state $c = Math::GComplex->new(-0.4, 0.6);
  37. my $i = 10;
  38. while ($z->abs < 2 and --$i >= 0) {
  39. $z = $z * $z + $c;
  40. }
  41. $z->reals;
  42. }
  43. my @matrix;
  44. my ($min_x, $min_y) = ('inf') x 2;
  45. my ($max_x, $max_y) = (-'inf') x 2;
  46. foreach my $y (0 .. $height - 1) {
  47. foreach my $x (0 .. $width - 1) {
  48. my ($new_x, $new_y) = transform($x, $y);
  49. $matrix[$y][$x] = [$new_x, $new_y];
  50. if ($new_x < $min_x) {
  51. $min_x = $new_x;
  52. }
  53. if ($new_y < $min_y) {
  54. $min_y = $new_y;
  55. }
  56. if ($new_x > $max_x) {
  57. $max_x = $new_x;
  58. }
  59. if ($new_y > $max_y) {
  60. $max_y = $new_y;
  61. }
  62. }
  63. }
  64. say "X: [$min_x, $max_x]";
  65. say "Y: [$min_y, $max_y]";
  66. my $out_img = Imager->new(xsize => $width,
  67. ysize => $height);
  68. foreach my $y (0 .. $height - 1) {
  69. foreach my $x (0 .. $width - 1) {
  70. my ($new_x, $new_y) = @{$matrix[$y][$x]};
  71. $new_x = map_val($new_x, $min_x, $max_x, 0, $width - 1);
  72. $new_y = map_val($new_y, $min_y, $max_y, 0, $height - 1);
  73. $out_img->setpixel(
  74. x => $new_x,
  75. y => $new_y,
  76. color => $img->getpixel(x => $x, y => $y),
  77. );
  78. }
  79. }
  80. $out_img->write(file => 'julia_transform.png');