RMagick (+ CarrierWave) でウォーターマーク(透かし)付きの画像を作る

  • 10
    Like
  • 0
    Comment
More than 1 year has passed since last update.

ウォーターマーク(透かし)を敷き詰めた画像を RMagick で作る方法です。
また、CarrierWave と組み合わせるサンプルも一緒に紹介します。

ウォーターマークとは

サンプル画像とかに良く被さっているアレです。
fotowa1 ロゴで作るとこんな感じになります。

watermark.png

透け透けなのでほとんど見えませんが、例えばこの画像と組み合わせるとこうなります。

watermarked.jpg

これは今回の最終成果物でもあります。

RMagick の mosaic で敷き詰めた画像を作る

ウォーターマークを敷き詰める際に、合成処理を繰り返し行ってしまうと非常に時間がかかります。一回試してみましたが実用不可な遅さでした。

そこで、mosaic を使って最初にウォーターマークを敷き詰めた画像を作成し、それを対象となる画像に合成することにします。
こうすることで、かなり処理を高速化することができます。

また mosaic はその名の通り、画像を大量に敷き詰めてモザイクにしてくれる機能です。

image = Magick::Image.read("target.png").first

mark = Magick::Image.read("watermark.png").first
mark.background_color = "none" # 背景色が指定されていると合成後にアルファチャネル部分がその色になる

tile = Magick::ImageList.new
page = Magick::Rectangle.new(0, 0, 0, 0)

# 調度良いサイズになるようにウォーターマークを敷き詰める
(image.columns / mark.columns.to_f).ceil.times do |x|
  (image.rows / mark.rows.to_f).ceil.times do |y|
    tile << mark.dup
    page.x = x * tile.columns
    page.y = y * tile.rows
    tile.page = page
  end
end

注意すべきポイントはウォーターマークの背景色です。
例えば先程のウォーターマークには元々 "white" が指定されています。

もし背景色が設定されているまま mosaic を作りウォーターマークを敷き詰めると、

watermarked_1.jpg

このように背景色で塗りつぶされてしまいます。

CarrierWave で使う

CarrierWave では RMagick と組み合わせ、画像のリサイズなどが簡単に行なえます。
例えば、process resize_to_fit: [2000, 1000]などが利用可能です。

process ではオリジナルメソッドも使えるので、それを定義しversion の中で使用することにします。

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

  version :watermarked do
    process :watermark
  end

  def watermark
    mark = Magick::Image.read(Rails.root.join("lib", "assets", "watermark.png")).first
    mark.background_color = "none"

    manipulate! do |image|
      tile = Magick::ImageList.new
      page = Magick::Rectangle.new(0, 0, 0, 0)

      (image.columns / mark.columns.to_f).ceil.times do |x|
        (image.rows / mark.rows.to_f).ceil.times do |y|
          tile << mark.dup
          page.x = x * tile.columns
          page.y = y * tile.rows
          tile.page = page
        end
      end

      image.composite(tile.mosaic, 0, 0, Magick::OverCompositeOp)
    end
  end
end

これで保存時にウォーターマークを敷き詰めたものも一緒に保存されるようになりました!

参考


  1. 2016年1月からアーキテクト / リードエンジニアとして担当している Web サービス。