gd_star_trails.pl 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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 GD;
  13. use Getopt::Long qw(GetOptions);
  14. GD::Image->trueColor(1);
  15. my $output_file = 'output.png';
  16. my $file_format = 'png';
  17. my $png_compression = 9;
  18. my $jpeg_quality = 90;
  19. my $scale_percent = 0;
  20. sub help {
  21. print <<"HELP";
  22. usage: $0 [options] [files]
  23. options:
  24. -o --output : output file (default: $output_file)
  25. -f --format : image format (default: $file_format)
  26. -q --jpeg-quality : JPEG quality (default: $jpeg_quality)
  27. -c --png-compression : PNG compression level (default: $png_compression)
  28. -s --scale-percent : scale image by a given percentage (default: $scale_percent)
  29. example:
  30. $0 -o merged.png --scale -20 file1.jpg file2.jpg
  31. HELP
  32. exit;
  33. }
  34. GetOptions(
  35. 'o|output=s' => \$output_file,
  36. 'f|format=s' => \$file_format,
  37. 'q|jpeg-quality=i' => \$jpeg_quality,
  38. 'c|png-compression=i' => \$png_compression,
  39. 's|scale-percent=i' => \$scale_percent,
  40. 'h|help' => \&help,
  41. )
  42. or die "Error in command-line arguments!";
  43. sub intensity {
  44. ($_[0] + $_[1] + $_[2]) / 3;
  45. }
  46. my @matrix;
  47. my %color_cache;
  48. my %intensity_cache;
  49. foreach my $image (@ARGV) {
  50. say "** Processing file: $image";
  51. my $gd = GD::Image->new($image) // do {
  52. warn "** Can't load file <<$image>>. Skipping...\n";
  53. next;
  54. };
  55. my ($width, $height) = $gd->getBounds;
  56. if ($scale_percent != 0) {
  57. my $scale_width = $width + int($scale_percent / 100 * $width);
  58. my $scale_height = $height + int($scale_percent / 100 * $height);
  59. my $scaled_gd = GD::Image->new($scale_width, $scale_height);
  60. $scaled_gd->copyResampled($gd, 0, 0, 0, 0, $scale_width, $scale_height, $width, $height);
  61. ($width, $height) = ($scale_width, $scale_height);
  62. $gd = $scaled_gd;
  63. }
  64. foreach my $x (0 .. $width - 1) {
  65. foreach my $y (0 .. $height - 1) {
  66. my $index = $gd->getPixel($x, $y);
  67. $matrix[$x][$y] //= [0, 0, 0];
  68. if (intensity(@{$matrix[$x][$y]}) <
  69. ($intensity_cache{$index} //= (intensity(@{$color_cache{$index} //= [$gd->rgb($index)]})))) {
  70. $matrix[$x][$y] = $color_cache{$index};
  71. }
  72. }
  73. }
  74. }
  75. @matrix || die "error: No image has been processed!\n";
  76. say "** Creating the output image: $output_file";
  77. my $image = GD::Image->new($#matrix + 1, $#{$matrix[0]} + 1);
  78. foreach my $x (0 .. $#matrix) {
  79. my $row = $matrix[$x] // next;
  80. foreach my $y (0 .. $#{$matrix[0]}) {
  81. my $entry = $row->[$y] // next;
  82. my $color = $image->colorAllocate(@{$entry});
  83. $image->setPixel($x, $y, $color);
  84. }
  85. }
  86. open my $fh, '>:raw', $output_file;
  87. print $fh lc($file_format) =~ /png/
  88. ? $image->png($png_compression)
  89. : $image->jpeg($jpeg_quality);
  90. close $fh;
  91. say "** All done!";