# coding: utf-8 require 'imagetools/version' require 'fileutils' require 'optparse' require 'yaml' module Imagetools class Config FILENAME_SEARCH = 's (\d+)-(\d+)-(\d+) (\d+)\.(\d+)\.(\d+)' FILENAME_REPLACE = 's_\1\2\3_\4\5\6' RESIZE_WIDTH = 1280 def self.create_from_yaml(yaml) config = Config.new config.filename_search1 = config_value(yaml, "filename", "search1", false) config.filename_replace1 = config_value(yaml, "filename", "replace1", false) config.filename_search2 = config_value(yaml, "filename", "search2", false) config.filename_replace2 = config_value(yaml, "filename", "replace2", false) config.filename_search3 = config_value(yaml, "filename", "search3", false) config.filename_replace3 = config_value(yaml, "filename", "replace3", false) config.resize_width = config_value(yaml, "resize", "width", false) config.init_default config end def self.config_value(yaml, section, key, require) return nil unless yaml return nil unless yaml[section] value = yaml[section][key] if require && (value.nil? || value.empty?) raise RuntimeError, "#{section}:#{key}: is empty" end value end def initialize end def init_default @filename_search1 ||= FILENAME_SEARCH @filename_replace1 ||= FILENAME_REPLACE @resize_width ||= RESIZE_WIDTH end attr_accessor :filename_search1, :filename_replace1, :filename_search2, :filename_replace2, :filename_search3, :filename_replace3 attr_accessor :resize_width def filename_patterns [ [@filename_search1, @filename_replace1], [@filename_search2, @filename_replace2], [@filename_search3, @filename_replace3], ] end end class Imagefilter OTHER_JPG_SEARCH = /\.(large|huge|jpg_large|JPG)$/i OTHER_JPG_REPLACE = '.jpg' CONVERT_CMD = "convert" DWEBP_CMD = "dwebp" CWEBP_CMD = "cwebp" RESIZE_CMD = "mogrify -background white -resize %dx\\> " ROTATE_CMD = "exiftran -ai " COMPRESS_CMD = "jpegoptim --strip-all --max=90 " EXTERNAL_CMDS = [CONVERT_CMD, RESIZE_CMD, ROTATE_CMD, COMPRESS_CMD, DWEBP_CMD, CWEBP_CMD] WEBP_SEARCH = /(.+)\.webp/i WEBP_REPLACE = '\1.webp' PNG_SEARCH = /(.+)\.png/i PNG_REPLACE = '\1.jpg' JPG_SEARCH = /(.+)\.jpe?g/i HEIC_SEARCH = /(.+)\.heic/i HEIC_REPLACE = '\1.jpg' EXCLUDE_PAT = /^_/ # 先頭が"_"の場合は除外 def self.run(argv) STDOUT.sync = true opts = {} opt = OptionParser.new(argv) opt.banner = "Usage: #{opt.program_name} [-h|--help] " opt.version = VERSION opt.separator('') opt.separator('Parameters:') param =< #{topath}" # FileUtils.mv(filepath, topath, :force => true) unless @opts[:n] # aaa.JPG => aaa.jpgを成功させるためにFIleUtils.mv(same fileエラーがでる)ではなくmvを使う cmd = "mv \"#{filepath}\" \"#{topath}\"" system(cmd) return topath end # def webp2png(filepath) # fromname = File.basename(filepath) # toname = self.class.replace_webp2png(fromname) # return filepath if fromname == toname # dir = File.dirname(filepath) # topath = File.join(dir, toname) # puts "convert: #{filepath} => #{topath}" # # dwebp ~/Desktop/1.webp -o ~/Desktop/1.jpg # cmd = "#{DWEBP_CMD} \"#{filepath}\" -o \"#{topath}\"" # if system(cmd) # FileUtils.rm(filepath) # end # return topath # end # def png2jpg(filepath) # fromname = File.basename(filepath) # toname = self.class.replace_png2jpg(fromname) # return filepath if fromname == toname # dir = File.dirname(filepath) # topath = File.join(dir, toname) # puts "convert: #{filepath} => #{topath}" # # convert test.png -background "#ffff00" -flatten test.jpg # cmd = "#{CONVERT_CMD} \"#{filepath}\" -background \"#ffffff\" -flatten \"#{topath}\"" # if system(cmd) # FileUtils.rm(filepath) # end # return topath # end def heic2jpg(filepath) fromname = File.basename(filepath) toname = self.class.replace_heic2jpg(fromname) # puts "heic2jpg #{fromname}=>#{toname}" return filepath if fromname == toname dir = File.dirname(filepath) topath = File.join(dir, toname) puts "convert: #{filepath} => #{topath}" # convert ~/Desktop/test.heic -o ~/Desktop/test.jpg cmd = "#{CONVERT_CMD} \"#{filepath}\" \"#{topath}\"" if system(cmd) FileUtils.rm(filepath) end return topath end def resize_image(filepath) fromname = File.basename(filepath) # .JPEG .PNG .WEBPを許す is_image = (fromname =~ JPG_SEARCH || fromname =~ PNG_SEARCH || fromname =~ WEBP_SEARCH) unless is_image return filepath end puts "resize: #{filepath}" resize_cmd = sprintf(RESIZE_CMD, @config.resize_width) cmd = "#{resize_cmd} \"#{filepath}\"" system(cmd) return filepath end def rotate_jpg(filepath) fromname = File.basename(filepath) unless fromname =~ JPG_SEARCH return filepath end puts "rotate: #{filepath}" cmd = "#{ROTATE_CMD} \"#{filepath}\"" system(cmd) return filepath end # def compress_jpg(filepath) # fromname = File.basename(filepath) # unless fromname =~ JPG_SEARCH # return filepath # end # puts "compress: #{filepath}" # cmd = "#{COMPRESS_CMD} \"#{filepath}\"" # system(cmd) # return filepath # end def image2webp(filepath) fromname = File.basename(filepath) toname = self.class.replace_image2webp(fromname) return filepath if fromname == toname dir = File.dirname(filepath) topath = File.join(dir, toname) puts "image2webp: #{filepath} => #{topath}" # cwebp ~/Desktop/1.webp -o ~/Desktop/1.jpg cmd = "#{CWEBP_CMD} -quiet \"#{filepath}\" -o \"#{topath}\"" # puts cmd if system(cmd) FileUtils.rm(filepath) end return topath end end end