Tự động watermark ảnh với ImageMagick
Khách hàng trong dự án gần đây của tôi yêu cầu mỗi hình ảnh upload lên đều phải được watermark. Điều này khá quan trọng vì hiện nay, việc sử dụng hình ảnh vi phạm bản quyền là rất phổ biến. Để làm việc này, chúng ta có thể chèn một ảnh mờ hoặc một đoạn text chứa thông tin liên hệ lên trên ảnh gốc ...
Khách hàng trong dự án gần đây của tôi yêu cầu mỗi hình ảnh upload lên đều phải được watermark. Điều này khá quan trọng vì hiện nay, việc sử dụng hình ảnh vi phạm bản quyền là rất phổ biến. Để làm việc này, chúng ta có thể chèn một ảnh mờ hoặc một đoạn text chứa thông tin liên hệ lên trên ảnh gốc mà không che đi thông tin chính của ảnh gốc, điều này vừa để đánh dấu bản quyền vừa giúp khách hàng đỡ mất công tìm kiếm cách liên hệ. Để chỉnh sửa hình ảnh, chúng ta cần một công cụ riêng biệt. Mặc định Carrierwave có hỗ trợ các gem RMagick và MiniMagick, sử dụng để thao tác lên hình ảnh với sự giúp đỡ của ImageMagick. ImageMagick là một giải pháp mã nguồn mở được hỗ trợ trên tất cả các nền tảng lớn, cho phép chỉnh sửa các hình ảnh hiện có và tạo ra những hình ảnh mới, do đó, trước khi tiến hành bạn cần phải tải về và cài đặt nó. Tiếp theo, bạn có thể chọn một trong hai gem. Tôi chọn MiniMagick vì nó dễ cài đặt và có hỗ trợ tốt hơn. Đầu tiên, thêm gem "mini_magick" vào Gemfile. Chạy bundle install để cài đặt. Trong file image_uploader.rb, thêm include CarrierWave::MiniMagick và xử lý process :watermark. File sau khi thêm sẽ có dạng sau:
class ImageUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: # include CarrierWave::RMagick include CarrierWave::MiniMagick # Choose what kind of storage to use for this uploader: storage :file process :watermark # storage :fog # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end # Provide a default URL as a default if there hasn't been a file uploaded: def default_url(*args) # For Rails 3.1+ asset pipeline compatibility: # ActionController::Base.helpers.asset_path("fallback/default.png") "/preview_no_image.jpg" end # Process files as they are uploaded: # process scale: [200, 300] # # def scale(awidth, height) # # do something # end # Create different versions of your uploaded files: version :blog_thumb, if: :is_blog_img? do process resize_to_fit: [290, 230] end version :product_thumb, if: :is_product_img? do process resize_to_fit: [210, 210] end def extension_whitelist %w(jpg jpeg png) end def watermark end end
Vậy là xong phần khung, giờ chúng ta đi vào chi tiết là định nghĩa hàm watermark. Như đã nói ở trên, có hai dạng watermark, giờ chúng ta vào dạng đầu tiên.
Watermark với hình ảnh
Đoạn xử lý dưới đây sẽ lấy url của một ảnh trong model hoặc một ảnh mặc định làm ảnh watermark, với mỗi ảnh được upload (img) sẽ dùng hàm composite của ImageMagick với tham số là ảnh mở bằng MiniMagick với url được lấy bên trên, bạn có thể dùng một trong ba hàm composite, watermark hoặc dissolve để mogrify ảnh.
watermark_url = Company.first.watermark.url || "public/watermark.png" watermark = MiniMagick::Image.open(watermark_url) manipulate! do |img| img = img.composite(MiniMagick::Image.open(watermark), "png") do |c| c.gravity "South" end end
Chúng ta có thể đặt watermark ở bất cứ vị trí nào bằng cách điều chỉnh gravity và geometry. Có các lựa chọn cho gravity như NorthWest, North, NorthEast, West, Center, East, SouthWest, South, SouthEast. Nếu muốn xoay ảnh, có thể dùng hàm rotate watermark = watermark.rotate(-45). Ngoài ra, có thể dùng combine_options, một dạng command-line của ImageMagick:
manipulate! do |img| img.combine_options do |cmd| cmd.draw 'image Over 0,0 0,0 "public/watermark.png"' end img end
Ví dụ với ảnh watermark này Sẽ cho ra kết quả:
Watermark với văn bản
Tương tự như với hình ảnh, chỉ khác một chút là trước khi mogrify, bạn cần chỉnh các thông số cho text hiển thị đúng ý muốn.
img = MiniMagick::Image.read("/home/aditya/Pictures/old_england_pic.jpg").first mark = MiniMagick::Image.new(img.rows, img.columns) {self.background_color = "none"} draw = MiniMagick::Draw.new draw.annotate(mark, 0, 0, 0, 0, "creative commons") do draw.gravity = MiniMagick::CenterGravity draw.pointsize = 100 draw.font_family = "Times" # set font draw.fill = "black" # set text color draw.stroke = "none" # remove stroke end mark = mark.rotate(-45) img = img.composite(mark, MiniMagick::CenterGravity, Magick::SoftLightCompositeOp)
hoặc
manipulate! do |img| img.combine_options do |cmd| draw_text = Company.first.mark cmd.gravity 'south' cmd.draw "text 10,10 '#{draw_text}'" cmd.font '-*-helvetica-*-r-*-*-25-*-*-*-*-*-*-2' cmd.fill 'black' end img end
Kết quả
Nếu không muốn sử dụng minimagick bạn có thể dùng rmagick sử dụng convert. convert là một công cụ được cung cấp bởi ImageMagick và được xử lý trên cùng một hình ảnh. Nó tiêu tốn nhiều bộ nhớ so với ImageMagick mogrify. convert thích hợp cho nhiều thao tác trên cùng một tập tin trong khi mogrify phù hợp hơn cho việc xử lý hàng loạt.
Tham khảo https://github.com/minimagick/minimagick https://github.com/rmagick-temp/rmagick https://snippets.aktagon.com/snippets/196-how-to-add-a-watermark-to-pictures-with-minimagick-and-ruby