resize_images.pl 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #!/usr/bin/perl
  2. # Author: Trizen
  3. # Date: 30 October 2023
  4. # Edit: 25 June 2024
  5. # https://github.com/trizen
  6. # Resize images to a given width or height, keeping aspect ratio.
  7. use 5.036;
  8. use Imager qw();
  9. use File::Find qw(find);
  10. use List::Util qw(min max);
  11. use Getopt::Long qw(GetOptions);
  12. my $width = 'auto';
  13. my $height = 'auto';
  14. my $min = 'auto';
  15. my $max = 'auto';
  16. my $qtype = 'mixing';
  17. my $img_formats = '';
  18. my @img_formats = qw(
  19. jpeg
  20. jpg
  21. png
  22. );
  23. sub usage ($code) {
  24. local $" = ",";
  25. print <<"EOT";
  26. usage: $0 [options] [dirs | files]
  27. options:
  28. -w --width=i : resize images to this width
  29. -h --height=i : resize images to this height
  30. --min=i : resize images to have the smallest side equal to this
  31. --max=i : resize images to have the largest side equal to this
  32. -q --quality=s : quality of scaling: 'normal', 'preview' or 'mixing' (default: $qtype)
  33. -f --formats=s,s : specify more image formats (default: @img_formats)
  34. examples:
  35. $0 --min=1080 *.jpg # smallest side = 1080 pixels
  36. $0 --height=1080 *.jpg # height = 1080 pixels
  37. EOT
  38. exit($code);
  39. }
  40. GetOptions(
  41. 'w|width=i' => \$width,
  42. 'h|height=i' => \$height,
  43. 'minimum=i' => \$min,
  44. 'maximum=i' => \$max,
  45. 'q|quality=s' => \$qtype,
  46. 'f|formats=s' => \$img_formats,
  47. 'help' => sub { usage(0) },
  48. )
  49. or die("Error in command line arguments");
  50. push @img_formats, map { quotemeta } split(/\s*,\s*/, $img_formats);
  51. my $img_formats_re = do {
  52. local $" = '|';
  53. qr/\.(@img_formats)\z/i;
  54. };
  55. sub resize_image ($image) {
  56. my $img = Imager->new(file => $image) or do {
  57. warn "Failed to load <<$image>>: ", Imager->errstr();
  58. return;
  59. };
  60. my ($curr_width, $curr_height) = ($img->getwidth, $img->getheight);
  61. if ($min ne 'auto' and $min > 0) {
  62. if (min($curr_width, $curr_height) <= $min) {
  63. say "Image too small to resize";
  64. return;
  65. }
  66. if ($curr_width < $curr_height) {
  67. $img = $img->scale(xpixels => $min, qtype => $qtype);
  68. }
  69. else {
  70. $img = $img->scale(ypixels => $min, qtype => $qtype);
  71. }
  72. }
  73. elsif ($max ne 'auto' and $max > 0) {
  74. if (max($curr_width, $curr_height) <= $max) {
  75. say "Image too small to resize";
  76. return;
  77. }
  78. if ($curr_height > $curr_width) {
  79. $img = $img->scale(ypixels => $max, qtype => $qtype);
  80. }
  81. else {
  82. $img = $img->scale(xpixels => $max, qtype => $qtype);
  83. }
  84. }
  85. elsif ($height ne 'auto' and $height > 0) {
  86. if ($curr_height <= $height) {
  87. say "Image too small to resize";
  88. return;
  89. }
  90. $img = $img->scale(ypixels => $height, qtype => $qtype);
  91. }
  92. elsif ($width ne 'auto' and $width > 0) {
  93. if ($curr_width <= $width) {
  94. say "Image too small to resize";
  95. return;
  96. }
  97. $img = $img->scale(xpixels => $width, qtype => $qtype);
  98. }
  99. else {
  100. die "No --width or --height specified...";
  101. }
  102. $img->write(file => $image);
  103. }
  104. @ARGV || usage(1);
  105. find {
  106. no_chdir => 1,
  107. wanted => sub {
  108. (/$img_formats_re/o && -f) || return;
  109. say "Resizing: $_";
  110. resize_image($_);
  111. }
  112. } => @ARGV;