Blog

Feb

Mirror Images with CarrierWave


Inspired by this post on how to create mirror images with Paperclip, I decided to write up how to do the same thing with CarrierWave. It's a nice example of how CarrierWave's Uploader class makes manipulating files very easy.

This assumes you've already generated an uploader and probably mounted it on a model somewhere. If this doesn't make sense to you, check out the CarrierWave documentation.

Add this method to you uploader:

def add_mirror_effect(mirror_length)
  manipulate! do |img|
    mirror_rows = img.rows * mirror_length

    gradient = Magick::GradientFill.new(0, 0, mirror_rows, 0, "#888", "#000")
    gradient = Magick::Image.new(img.columns, mirror_rows, gradient)
    gradient.matte = false

    flipped = img.flip
    flipped.matte = true
    flipped.composite!(gradient, 0, 0, Magick::CopyOpacityCompositeOp)

    new_frame = Magick::Image.new(img.columns, img.rows + mirror_rows)
    new_frame.composite!(img, 0, 0, Magick::OverCompositeOp)
    new_frame.composite!(flipped, 0, img.rows, Magick::OverCompositeOp)
    new_frame
  end
end

This will first create a gradient. It will then flip the image and use that gradient as the alpha channel for the flipped image. Finally it will create a new image, putting the original, and the faded out mirror image together.

Next, add a version to your Uploader, which calls the new add_mirror_effect method:

version :with_mirror do
  process :add_mirror_effect => 0.2
end

That's it! The end result should look something like this:

class AvatarUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick

  version :with_mirror do
    process :resize_to_fill => [200, 200]
    process :add_mirror_effect => 0.2
  end

private

  def add_mirror_effect(mirror_length)
    manipulate! do |img|
      mirror_rows = img.rows * mirror_length

      gradient = Magick::GradientFill.new(0, 0, mirror_rows, 0, "#888", "#000")
      gradient = Magick::Image.new(img.columns, mirror_rows, gradient)
      gradient.matte = false

      flipped = img.flip
      flipped.matte = true
      flipped.composite!(gradient, 0, 0, Magick::CopyOpacityCompositeOp)

      new_frame = Magick::Image.new(img.columns, img.rows + mirror_rows)
      new_frame.composite!(img, 0, 0, Magick::OverCompositeOp)
      new_frame.composite!(flipped, 0, img.rows, Magick::OverCompositeOp)
    end
  end

end

For extra props, put the add_mirror_effect method in a module and include it in your Uploader.

blog comments powered by Disqus