magick_star_trails.pl 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 30 January 2015
  5. # Edited: 31 January 2015
  6. # Website: https://github.com/trizen
  7. # Merge two or more images together and keep the most intensive pixel colors
  8. use 5.010;
  9. use strict;
  10. use autodie;
  11. use warnings;
  12. use Image::Magick;
  13. use List::Util qw(min max);
  14. use Getopt::Long qw(GetOptions);
  15. my $output_file = 'output.png';
  16. my $scale_percent = 0;
  17. my $brightness_f = 'avg';
  18. my %brightness = (
  19. # I: https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
  20. avg => sub { ($_[0] + $_[1] + $_[2]) / 3 },
  21. # L: https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
  22. hsl => sub { 0.5 * max(@_) + 0.5 * min(@_) },
  23. # https://en.wikipedia.org/wiki/Relative_luminance
  24. rl => sub { (0.2126 * $_[0] + 0.7152 * $_[1] + 0.0722 * $_[2]) },
  25. # https://en.wikipedia.org/wiki/Luma_(video)#Rec._601_luma_versus_Rec._709_luma_coefficients
  26. luma => sub { (0.299 * $_[0] + 0.587 * $_[1] + 0.114 * $_[2]) },
  27. # http://alienryderflex.com/hsp.html
  28. hsp => sub { sqrt(0.299 * ($_[0]**2) + 0.587 * ($_[1]**2) + 0.114 * ($_[2]**2)) },
  29. );
  30. sub help {
  31. local $" = ", ";
  32. print <<"HELP";
  33. usage: $0 [options] [files]
  34. options:
  35. -o --output : output file (default: $output_file)
  36. -s --scale-percent : scale image by a given percentage (default: $scale_percent)
  37. -f --formula : formula for the brightness of a pixel (default: $brightness_f)
  38. valid values: @{[sort keys %brightness]}
  39. example:
  40. $0 -o merged.png --scale -20 file1.jpg file2.jpg
  41. HELP
  42. exit;
  43. }
  44. GetOptions(
  45. 'o|output=s' => \$output_file,
  46. 's|scale-percent=i' => \$scale_percent,
  47. 'f|formula=s' => \$brightness_f,
  48. 'h|help' => \&help,
  49. )
  50. or die "Error in command-line arguments!";
  51. if (not exists $brightness{$brightness_f}) {
  52. local $" = ", ";
  53. die "[!] Invalid brightness formula: `$brightness_f'.
  54. Valid values are: @{[sort keys %brightness]}\n";
  55. }
  56. my $lightness_function = $brightness{$brightness_f};
  57. my @matrix;
  58. foreach my $image (@ARGV) {
  59. say "** Processing file: $image";
  60. my $img = Image::Magick->new;
  61. my $err = $img->Read($image);
  62. if ($err) {
  63. warn "** Can't load file <<$image>> ($err). Skipping...\n";
  64. next;
  65. }
  66. my ($width, $height) = $img->Get('width', 'height');
  67. if ($scale_percent != 0) {
  68. my $scale_width = $width + int($scale_percent / 100 * $width);
  69. my $scale_height = $height + int($scale_percent / 100 * $height);
  70. $img->Resize(width => $scale_width, height => $scale_height);
  71. ($width, $height) = ($scale_width, $scale_height);
  72. }
  73. my @pixels = $img->GetPixels(
  74. map => 'RGB',
  75. x => 0,
  76. y => 0,
  77. width => $width,
  78. height => $height,
  79. normalize => 1,
  80. );
  81. my $i = 0;
  82. while (@pixels) {
  83. my $x = int($i % $width);
  84. my $y = int($i / $width);
  85. my @rgb = splice(@pixels, 0, 3);
  86. $matrix[$x][$y] //= [0, 0, 0];
  87. if ($lightness_function->(@{$matrix[$x][$y]}) < $lightness_function->(@rgb)) {
  88. $matrix[$x][$y] = \@rgb;
  89. }
  90. ++$i;
  91. }
  92. }
  93. @matrix || die "error: No image has been processed!\n";
  94. say "** Creating the output image: $output_file";
  95. my $image = Image::Magick->new;
  96. $image->Set(size => @matrix . 'x' . @{$matrix[0]});
  97. $image->ReadImage('canvas:white');
  98. foreach my $x (0 .. $#matrix) {
  99. my $row = $matrix[$x] // next;
  100. foreach my $y (0 .. $#{$matrix[0]}) {
  101. my $entry = $row->[$y] // next;
  102. $image->SetPixel(x => $x, y => $y, color => $entry);
  103. }
  104. }
  105. open my $fh, '>:raw', $output_file;
  106. $image->Write(file => $fh, filename => $output_file);
  107. close $fh;
  108. say "** All done!";