Reputation: 1818
I'm doing image processing with ImageMagick commands and I would like to port them to RMagick. The goal of this task is to take a picture and to pixelate given areas (one or more) for privacy purpose.
Here is my bash script (script.sh
), which works very well using the convert
command:
convert invoice.png -scale 10% -scale 1000% pixelated.png
convert invoice.png -gamma 0 -fill white -draw "rectangle 35, 110, 215, 250" mask.png
convert invoice.png pixelated.png mask.png -composite result.png
Now I want to create the Ruby version of this script using ImageMagick. Here is what I have now:
require 'rmagick'
# pixelate_areas('invoice.png', [ [ x1, y1, width, height ] ])
def pixelate_areas(image_path, areas)
image = Magick::Image::read(image_path).first
pixelated = image.scale(0.1).scale(10)
mask = Magick::Image.new(image.columns, image.rows) { self.background_color = '#000' }
areas.each do |coordinates|
area = Magick::Image.new(coordinates[2], coordinates[3]) { self.background_color = '#fff' }
mask.composite!(area, coordinates[0], coordinates[1], Magick::OverCompositeOp)
end
# Now, how can I merge my 3 images?
# I need to extract the part of pixelated that overlap with the white part of the mask (everything else must be transparent).
# Then I have to superpose the resulting image to the original (it's the easy part).
end
As you can see, I'm stuck at the last step. What operation do I need to do with my original picture, my pixelated picture and my mask in order to have this result?
How can I build an image with just the overlapping of the white part of the mask and the pixelated picture. Just like this one but with transparency instead of black?
Upvotes: 2
Views: 829
Reputation: 34031
First, why are you porting commands to RMagick when you've got something that already works? The bash version is short and comprehensible. If this is just part of a larger script that you're porting, don't be afraid of system()
.
That said, here's a different tack that I believe accomplishes what you're trying to do in a more straightforward manner.
require 'RMagick'
def pixelate_area(image_path, x1, y1, x2, y2)
image = Magick::Image::read(image_path).first
sensitive_area = image.crop(x1, y1, x2 - x1, y2 - y1).scale(0.1).scale(10)
image.composite!(sensitive_area, x1, y1, Magick::AtopCompositeOp)
image.write('result.png') { self.depth = image.depth }
end
This then seems to do the same as your original bash commands:
pixelate_area('invoice.png', 35, 110, 215, 250)
Since it looks like you want to handle multiple areas to blur out, here's a version that takes an array of areas (each as [x1, y1, x2, y2]
):
def pixelate_areas(image_path, areas)
image = Magick::Image::read(image_path).first
areas.each do |area|
x1, y1, x2, y2 = area
sensitive_area = image.crop(x1, y1, x2 - x1, y2 - y1).scale(0.1).scale(10)
image.composite!(sensitive_area, x1, y1, Magick::AtopCompositeOp)
end
image.write('result.png') { self.depth = image.depth }
end
Upvotes: 2