Class: Fleximage::Operator::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/fleximage/operator/base.rb

Overview

The Operator::Base class is what all other Operator classes inherit from. To write your own Operator class, simply inherit from this class, and implement your own operate methods, with your own arguments. Just return a new RMagick image object that represents the new image, and the model will be updated automatically.

You have access to a few instance variables in the operate method:

  • @image : The current image from the model. Use this is a starting point for all transformations.

  • @model : The model instance that this image transformation is happenining in. Use it to get data out of your model for display in your image.

Direct Known Subclasses

Background, Border, Crop, ImageOverlay, Resize, Shadow, Text, Trim, UnsharpMask

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(proxy, image, model_obj) ⇒ Base

Create a operator, capturing the model object to operate on



24
25
26
27
28
# File 'lib/fleximage/operator/base.rb', line 24

def initialize(proxy, image, model_obj) #:nodoc:
  @proxy = proxy
  @image = image
  @model = model_obj
end

Class Method Details

.color(*args) ⇒ Object

This method will return a valid color Magick::Pixel object. It will also auto adjust for the bit depth of your ImageMagick configuration.

Usage:

color('red')          #=> Magick::Pixel with a red color
color(0, 255, 0)      #=> Magick::Pixel with a green color
color(0, 0, 255, 47)  #=> Magick::Pixel with a blue clolor and slightly transparent

# on an ImageMagick with a QuantumDepth of 16
color(0, 255, 0)      #=> Magick::Pixel with rgb of (0, 65535, 0) (auto adjusted to 16bit channels)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/fleximage/operator/base.rb', line 82

def self.color(*args)
  if args.size == 1 && args.first.is_a?(String)
    args.first
  else
    
    # adjust color to proper bit depth
    if Magick::QuantumDepth != 8
      max = case Magick::QuantumDepth
      when 16
        65_535
      when 32
        4_294_967_295
      end
      
      args.map! do |value|
        (value.to_f/255 * max).to_i
      end
    end
    
    # create the pixel
    Magick::Pixel.new(*args)
  end
end

.size_to_xy(size) ⇒ Object

Allows access to size conversion globally. See size_to_xy for a more detailed explanation



56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/fleximage/operator/base.rb', line 56

def self.size_to_xy(size)
  case          
  when size.is_a?(Array) && size.size == 2  # [320, 240]
    size

  when size.to_s.include?('x')              # "320x240"
    size.split('x').collect(&:to_i)
  
  else # Anything else, convert the object to an integer and assume square dimensions
    [size.to_i, size.to_i]
    
  end
end

Instance Method Details

#color(*args) ⇒ Object



106
107
108
# File 'lib/fleximage/operator/base.rb', line 106

def color(*args)
  self.class.color(*args)
end

#execute(*args) ⇒ Object

Start the operation



31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/fleximage/operator/base.rb', line 31

def execute(*args) #:nodoc:
  # Get the result of the Operators #operate method
  result = operate(*args)
  
  # Ensure that the result is an RMagick:Image object
  unless result.is_a?(Magick::Image)
    raise BadOperatorResult, "expected #{self.class}#operate to return an instance of Magick::Image. \n"+
                             "Got instance of #{result.class} instead."
  end
  
  # Save the result to the operator proxy
  @proxy.image = result
end

#operate(*args) ⇒ Object

Perform the operation. Override this method in your Operator::Base subclasses in order to write your own image operators.



47
48
49
# File 'lib/fleximage/operator/base.rb', line 47

def operate(*args)
  raise OperationNotImplemented, "Override this method in your own subclass."
end

#scale(size, img = @image) ⇒ Object

Scale the image, respecting aspect ratio.

Operation will happen in the main @image unless you supply the img argument to operate on instead.



127
128
129
130
131
132
133
# File 'lib/fleximage/operator/base.rb', line 127

def scale(size, img = @image)
  img.change_geometry!(size_to_xy(size).join('x')) do |cols, rows, _img|
    cols = 1 if cols < 1
    rows = 1 if rows < 1
    _img.resize!(cols, rows)
  end
end

#scale_and_crop(size, img = @image) ⇒ Object

Scale to the desired size and crop edges off to get the exact dimensions needed. Operation will happen in the main @image unless you supply the img argument to operate on instead.



138
139
140
# File 'lib/fleximage/operator/base.rb', line 138

def scale_and_crop(size, img = @image)
  img.crop_resized!(*size_to_xy(size))
end

#size_to_xy(size) ⇒ Object

Converts a size object to an [x,y] array. Acceptible formats are:

  • 10

  • “10”

  • “10x20”

  • 10, 20

Usage:

x, y = size_to_xy("10x20")


120
121
122
# File 'lib/fleximage/operator/base.rb', line 120

def size_to_xy(size)
  self.class.size_to_xy size
end

#stretch(size, img = @image) ⇒ Object

Resize the image, with no respect to aspect ratio.

Operation will happen in the main @image unless you supply the img argument to operate on instead.



145
146
147
# File 'lib/fleximage/operator/base.rb', line 145

def stretch(size, img = @image)
  img.resize!(*size_to_xy(size))
end

#symbol_to_blending_mode(mode) ⇒ Object

Convert a symbol to an RMagick blending mode.

The blending mode governs how the overlay gets composited onto the image. You can get some funky effects with modes like :copy_cyan or :screen. For a full list of blending modes checkout the RMagick documentation (www.simplesystems.org/RMagick/doc/constants.html#CompositeOperator). To use a blend mode remove the CompositeOp form the name and “unserscorize” the rest. For instance, MultiplyCompositeOp becomes :multiply, and CopyBlackCompositeOp becomes :copy_black.



156
157
158
159
160
# File 'lib/fleximage/operator/base.rb', line 156

def symbol_to_blending_mode(mode)
  "Magick::#{mode.to_s.camelize}CompositeOp".constantize
rescue NameError
  raise ArgumentError, ":#{mode} is not a valid blending mode."
end

#symbol_to_gravity(gravity_name) ⇒ Object



162
163
164
165
166
167
168
169
170
# File 'lib/fleximage/operator/base.rb', line 162

def symbol_to_gravity(gravity_name)
  gravity = GRAVITIES[gravity_name]
  
  if gravity
    gravity
  else
    raise ArgumentError, ":#{gravity_name} is not a valid gravity name.\n\nValid names are :center, :top, :top_right, :right, :bottom_right, :bottom, :bottom_left, :left, :top_left"
  end
end