magick_png2jpg.pl 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 23 March 2021
  4. # https://github.com/trizen
  5. # Convert PNG images to JPEG, using the ImageMagick library.
  6. # The original PNG files are deleted.
  7. use 5.036;
  8. use File::Find qw(find);
  9. use Image::Magick qw();
  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 convert_PNGs (@files) {
  14. say ":: Converting a batch of ", scalar(@files), " PNG images...";
  15. foreach my $file (@files) {
  16. say ":: Processing: $file";
  17. my $image = Image::Magick->new;
  18. $image->Read(filename => $file) && do {
  19. warn "[!] Can't load file <<$file>>. Skipping...\n";
  20. next;
  21. };
  22. my $orig_file = $file;
  23. my $jpeg_file = $file;
  24. if ($jpeg_file =~ s/\.png\z/.jpg/i) {
  25. ## ok
  26. }
  27. else {
  28. $jpeg_file .= '.jpg';
  29. }
  30. if (-e $jpeg_file) {
  31. warn "[!] File <<$jpeg_file>> already exists...\n";
  32. next;
  33. }
  34. open(my $fh, '>:raw', $jpeg_file) or do {
  35. warn "[!] Can't open file <<$jpeg_file>> for writing: $!\n";
  36. next;
  37. };
  38. $image->Write(file => $fh, filename => $jpeg_file);
  39. close $fh;
  40. if (-e $jpeg_file and ($orig_file ne $jpeg_file)) {
  41. say ":: Saved as: $jpeg_file";
  42. unlink($orig_file); # remove the original PNG file
  43. }
  44. }
  45. }
  46. sub determine_mime_type ($file) {
  47. if ($file =~ /\.jpe?g\z/i) {
  48. return "image/jpeg";
  49. }
  50. if ($file =~ /\.png\z/i) {
  51. return "image/png";
  52. }
  53. if ($use_exiftool) {
  54. my $res = `exiftool \Q$file\E`;
  55. $? == 0 or return;
  56. defined($res) or return;
  57. if ($res =~ m{^MIME\s+Type\s*:\s*(\S+)}mi) {
  58. return $1;
  59. }
  60. return;
  61. }
  62. require File::MimeInfo::Magic;
  63. File::MimeInfo::Magic::magic($file);
  64. }
  65. my %types = (
  66. 'image/png' => {
  67. files => [],
  68. call => \&convert_PNGs,
  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!";