gd_png2jpg.pl 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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 GD library.
  6. # The original PNG files are deleted.
  7. use 5.036;
  8. use GD;
  9. use File::Find qw(find);
  10. use Getopt::Long qw(GetOptions);
  11. GD::Image->trueColor(1);
  12. my $batch_size = 100; # how many files to process at once
  13. my $quality = 95; # default quality value for JPEG (between 0-100)
  14. my $use_exiftool = 0; # true to use `exiftool` instead of `File::MimeInfo::Magic`
  15. sub convert_PNGs (@files) {
  16. say ":: Converting a batch of ", scalar(@files), " PNG images...";
  17. foreach my $file (@files) {
  18. say ":: Processing: $file";
  19. my $image = eval { GD::Image->new($file) } // do {
  20. warn "[!] Can't load file <<$file>>. Skipping...\n";
  21. next;
  22. };
  23. my $jpeg_data = $image->jpeg($quality);
  24. my $orig_file = $file;
  25. my $jpeg_file = $file;
  26. if ($jpeg_file =~ s/\.png\z/.jpg/i) {
  27. ## ok
  28. }
  29. else {
  30. $jpeg_file .= '.jpg';
  31. }
  32. if (-e $jpeg_file) {
  33. warn "[!] File <<$jpeg_file>> already exists...\n";
  34. next;
  35. }
  36. open(my $fh, '>:raw', $jpeg_file) or do {
  37. warn "[!] Can't open file <<$jpeg_file>> for writing: $!\n";
  38. next;
  39. };
  40. print {$fh} $jpeg_data;
  41. close $fh;
  42. if (-e $jpeg_file and ($orig_file ne $jpeg_file)) {
  43. say ":: Saved as: $jpeg_file";
  44. unlink($orig_file); # remove the original PNG file
  45. }
  46. }
  47. }
  48. sub determine_mime_type ($file) {
  49. if ($use_exiftool) {
  50. my $res = `exiftool \Q$file\E`;
  51. $? == 0 or return;
  52. defined($res) or return;
  53. if ($res =~ m{^MIME\s+Type\s*:\s*(\S+)}mi) {
  54. return $1;
  55. }
  56. return;
  57. }
  58. require File::MimeInfo::Magic;
  59. File::MimeInfo::Magic::magic($file);
  60. }
  61. my %types = (
  62. 'image/png' => {
  63. files => [],
  64. call => \&convert_PNGs,
  65. },
  66. );
  67. GetOptions(
  68. 'exiftool!' => \$use_exiftool,
  69. 'batch-size=i' => \$batch_size,
  70. 'q|quality=i' => \$quality,
  71. )
  72. or die "Error in command-line arguments!";
  73. @ARGV or die <<"USAGE";
  74. usage: perl $0 [options] [dirs | files]
  75. options:
  76. -q INT : quality level for JPEG (default: $quality)
  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!";