class Photein::Image

Constants

MAX_RES_WEB
OPTIMIZATION_FORMAT_MAP
SUPPORTED_FORMATS

Public Instance Methods

optimize() click to toggle source
# File lib/photein/image.rb, line 25
def optimize
  return if Photein::Config.optimize_for == :desktop

  case extname
  when '.jpg', '.heic'
    return false if image.dimensions.reduce(&:*) < MAX_RES_WEB

    Photein::Logger.info "optimizing #{path}"
    MiniMagick::Tool::Convert.new do |convert|
      convert << path
      convert.colorspace('sRGB')
      convert.define('jpeg:dct-method=float')
      convert.interlace('JPEG')
      convert.quality('85%')
      convert.resize("#{MAX_RES_WEB}@>")
      convert.sampling_factor('4:2:0')
      convert << tempfile
    end unless Photein::Config.dry_run
  when '.png'
    FileUtils.cp(path, tempfile, noop: Photein::Config.dry_run)
    Photein::Logger.info "optimizing #{path}"
    begin
      Optipng.optimize(tempfile, level: 4) unless Photein::Config.dry_run
    rescue Errno::ENOENT
      Photein::Logger.error('optipng is required to compress PNG images')
      raise
    end
  end
end

Private Instance Methods

filename_stamp() click to toggle source

NOTE: This may be largely unnecessary: metadata timestamps are generally present in all cases except WhatsApp

Calls superclass method
# File lib/photein/image.rb, line 77
def filename_stamp
  path.basename(path.extname).to_s.then do |filename|
    case filename
    when /^IMG_\d{8}_\d{6}(_\d{3})?$/ # Android DCIM: datetime + optional counter
      Time.strptime(filename[0, 19], 'IMG_%Y%m%d_%H%M%S')
    when /^\d{13}$/ # LINE: UNIX time in milliseconds (at download)
      Time.strptime(filename[0..-4], '%s')
    when /^IMG-\d{8}-WA\d{4}$/ # WhatsApp: date + counter (at receipt)
      Time.strptime(filename, 'IMG-%Y%m%d-WA%M%S')
    when /^IMG_\d{8}_\d{6}_\d{3}$/ # Telegram: datetime in milliseconds (at download)
      Time.strptime(filename, 'IMG_%Y%m%d_%H%M%S_%L')
    when /^signal-\d{4}-\d{2}-\d{2}-\d{6}( \(\d+\))?$/ # Signal: datetime + optional counter (at receipt)
      Time.strptime(filename[0, 24], 'signal-%F-%H%M%S')
    when /^\d{13}$/ # LINE: UNIX time in milliseconds (at download)
      Time.strptime(filename[0..-4], '%s')
    else
      super
    end
  end
end
image() click to toggle source
# File lib/photein/image.rb, line 57
    def image
      @image ||= MiniMagick::Image.open(path)
    rescue MiniMagick::Invalid => e
      Photein::Logger.error(<<~MSG) if e.message.match?(/You must have ImageMagick/)
        ImageMagick is required to manipulate image files
      MSG
      raise
    end
metadata_stamp() click to toggle source
# File lib/photein/image.rb, line 66
    def metadata_stamp
      MiniExiftool.new(path.to_s).date_time_original
    rescue MiniExiftool::Error => e
      Photein::Logger.error(<<~MSG) if e.message.match?(/exiftool: not found/)
        exiftool is required to read timestamp metadata
      MSG
      raise
    end
non_optimizable_format?() click to toggle source
# File lib/photein/image.rb, line 98
def non_optimizable_format?
  return false if !Photein::Config.optimize_for
  return false if Photein::Config.optimize_for == :desktop
  return true if extname == '.dng'

  return false
end