File: pipeline.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 (97 lines) | stat: -rw-r--r-- 2,551 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
require "tempfile"

module ImageProcessing
  class Pipeline
    DEFAULT_FORMAT = "jpg"

    attr_reader :loader, :saver, :format, :operations, :processor, :destination

    # Initializes the pipeline with all the processing options.
    def initialize(options)
      fail Error, "source file is not provided" unless options[:source]

      options.each do |name, value|
        instance_variable_set(:"@#{name}", value)
      end
    end

    # Determines the destination and calls the processor.
    def call(save: true)
      if save == false
        call_processor
      elsif destination
        handle_destination do
          call_processor(destination: destination)
        end
      else
        create_tempfile do |tempfile|
          call_processor(destination: tempfile.path)
        end
      end
    end

    # Retrieves the source path on disk.
    def source_path
      source if source.is_a?(String)
    end

    # Determines the appropriate destination image format.
    def destination_format
      format   = File.extname(destination)[1..-1] if destination
      format ||= self.format
      format ||= File.extname(source_path)[1..-1] if source_path

      format || DEFAULT_FORMAT
    end

    private

    def call_processor(**options)
      processor.call(
        source:     source,
        loader:     loader,
        operations: operations,
        saver:      saver,
        **options
      )
    end

    # Creates a new tempfile for the destination file, yields it, and refreshes
    # the file descriptor to get the updated file.
    def create_tempfile
      tempfile = Tempfile.new(["image_processing", ".#{destination_format}"], binmode: true)

      yield tempfile

      tempfile.open
      tempfile
    rescue
      tempfile.close! if tempfile
      raise
    end

    # In case of processing errors, both libvips and imagemagick will leave the
    # empty destination file they created, so this method makes sure it is
    # deleted in case an exception is raised on saving the image.
    def handle_destination
      destination_existed = File.exist?(destination)
      yield
    rescue
      File.delete(destination) if File.exist?(destination) && !destination_existed
      raise
    end

    # Converts the source image object into a path or the accumulator object.
    def source
      if @source.is_a?(String)
        @source
      elsif @source.respond_to?(:path)
        @source.path
      elsif @source.respond_to?(:to_path)
        @source.to_path
      else
        @source
      end
    end
  end
end