File: processor.rb

package info (click to toggle)
ruby-image-processing 1.10.3-1%2Bdeb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,280 kB
  • sloc: ruby: 1,504; sh: 14; makefile: 3
file content (72 lines) | stat: -rw-r--r-- 2,263 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
module ImageProcessing
  # Abstract class inherited by individual processors.
  class Processor
    def self.call(source:, loader:, operations:, saver:, destination: nil)
      unless source.is_a?(String) || source.is_a?(self::ACCUMULATOR_CLASS)
        fail Error, "invalid source: #{source.inspect}"
      end

      if operations.dig(0, 0).to_s.start_with?("resize_") &&
         loader.empty? &&
         supports_resize_on_load?

        accumulator = source
      else
        accumulator = load_image(source, **loader)
      end

      operations.each do |operation|
        accumulator = apply_operation(accumulator, operation)
      end

      if destination
        save_image(accumulator, destination, **saver)
      else
        accumulator
      end
    end

    # Use for processor subclasses to specify the name and the class of their
    # accumulator object (e.g. MiniMagick::Tool or Vips::Image).
    def self.accumulator(name, klass)
      define_method(name) { @accumulator }
      protected(name)
      const_set(:ACCUMULATOR_CLASS, klass)
    end

    # Delegates to #apply_operation.
    def self.apply_operation(accumulator, (name, args, block))
      new(accumulator).apply_operation(name, *args, &block)
    end

    # Whether the processor supports resizing the image upon loading.
    def self.supports_resize_on_load?
      false
    end

    def initialize(accumulator = nil)
      @accumulator = accumulator
    end

    # Calls the operation to perform the processing. If the operation is
    # defined on the processor (macro), calls the method. Otherwise calls the
    # operation directly on the accumulator object. This provides a common
    # umbrella above defined macros and direct operations.
    def apply_operation(name, *args, &block)
      receiver = respond_to?(name) ? self : @accumulator

      if args.last.is_a?(Hash)
        kwargs = args.pop
        receiver.public_send(name, *args, **kwargs, &block)
      else
        receiver.public_send(name, *args, &block)
      end
    end

    # Calls the given block with the accumulator object. Useful for when you
    # want to access the accumulator object directly.
    def custom(&block)
      (block && block.call(@accumulator)) || @accumulator
    end
  end
end