optimize_images.pl 2.7 KB

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