optimize_images_littleutils.pl 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 19 December 2020
  4. # https://github.com/trizen
  5. # Optimize JPEG, PNG and GIF images in a given directory (recursively) using the "opt-png", "opt-jpg" and "opt-gif" tools from littleutils.
  6. # Littleutils:
  7. # https://sourceforge.net/projects/littleutils/
  8. use 5.036;
  9. use File::Find qw(find);
  10. use Getopt::Long qw(GetOptions);
  11. my $batch_size = 100; # how many files to process at once
  12. my $use_exiftool = 0; # true to use `exiftool` instead of `File::MimeInfo::Magic`
  13. sub optimize_JPEGs (@files) {
  14. say ":: Optimizing a batch of ", scalar(@files), " JPEG images...";
  15. system(
  16. "opt-jpg",
  17. "-m", "all", # copy all extra markers
  18. "-t", # preserve timestamp on modified files
  19. @files
  20. );
  21. }
  22. sub optimize_PNGs (@files) {
  23. say ":: Optimizing a batch of ", scalar(@files), " PNG images...";
  24. system(
  25. "opt-png",
  26. "-t", # preserve timestamp on modified files
  27. @files
  28. );
  29. }
  30. sub optimize_GIFs (@files) {
  31. say ":: Optimizing a batch of ", scalar(@files), " GIF images...";
  32. system(
  33. "opt-gif",
  34. "-t", # preserve timestamp on modified files
  35. @files
  36. );
  37. }
  38. sub determine_mime_type ($file) {
  39. if ($file =~ /\.jpe?g\z/i) {
  40. return "image/jpeg";
  41. }
  42. if ($file =~ /\.png\z/i) {
  43. return "image/png";
  44. }
  45. if ($use_exiftool) {
  46. my $res = `exiftool \Q$file\E`;
  47. $? == 0 or return;
  48. defined($res) or return;
  49. if ($res =~ m{^MIME\s+Type\s*:\s*(\S+)}mi) {
  50. return $1;
  51. }
  52. return;
  53. }
  54. require File::MimeInfo::Magic;
  55. File::MimeInfo::Magic::magic($file);
  56. }
  57. my %types = (
  58. 'image/jpeg' => {
  59. files => [],
  60. call => \&optimize_JPEGs,
  61. },
  62. 'image/png' => {
  63. files => [],
  64. call => \&optimize_PNGs,
  65. },
  66. 'image/gif' => {
  67. files => [],
  68. call => \&optimize_GIFs,
  69. },
  70. );
  71. GetOptions('exiftool!' => \$use_exiftool,
  72. 'batch-size=i' => \$batch_size,)
  73. or die "Error in command-line arguments!";
  74. @ARGV or die <<"USAGE";
  75. usage: perl $0 [options] [dirs | files]
  76. options:
  77. --batch=i : how many files to process at once (default: $batch_size)
  78. --exiftool : use `exiftool` to determine the MIME type (default: $use_exiftool)
  79. USAGE
  80. find(
  81. {
  82. no_chdir => 1,
  83. wanted => sub {
  84. (-f $_) || return;
  85. my $type = determine_mime_type($_) // return;
  86. if (exists $types{$type}) {
  87. my $ref = $types{$type};
  88. push @{$ref->{files}}, $_;
  89. if (scalar(@{$ref->{files}}) >= $batch_size) {
  90. $ref->{call}->(splice(@{$ref->{files}}));
  91. }
  92. }
  93. }
  94. } => @ARGV
  95. );
  96. foreach my $type (keys %types) {
  97. my $ref = $types{$type};
  98. if (@{$ref->{files}}) {
  99. $ref->{call}->(splice(@{$ref->{files}}));
  100. }
  101. }
  102. say ":: Done!";