Cut circle out of image with RMagick - ruby

I want to cut a circle out of an image using rmagick.
Here's an example of what I'd like to be able to accomplish:
-->
It seems like I want to use http://studio.imagemagick.org/RMagick/doc/draw.html#circle to cut a circle, and then clip_path to mask it, but the docs aren't very clear. Would anyone be able to point me in the right direction?

require 'rmagick'
im = Magick::Image.read('walter.jpg').first
circle = Magick::Image.new 200, 200
gc = Magick::Draw.new
gc.fill 'black'
gc.circle 100, 100, 100, 1
gc.draw circle
mask = circle.blur_image(0,1).negate
mask.matte = false
im.matte = true
im.composite!(mask, Magick::CenterGravity, Magick::CopyOpacityCompositeOp)
im.write 'walter_circle.png'

This is how I would do it with Imagemagick and php:
// Canvas the same size as the final image
exec("convert -size 800x533 xc:white white.jpg");
// The mask
exec("convert -size 800x533 xc:none -draw \"fill black circle 400,265 400,50\" write_mask.png");
// Cut the whole out of the canvas
exec("composite -compose Dst_Out write_mask.png white.jpg -matte step.png");
// Put the canvas over the image and trim off excess white background
exec("convert IMG_5745.jpg step.png -composite -trim final.jpg");
You should be able to follow the process?
Cleanup tempory images afterwards - I tend to save the tempory images in a .miff format and then write a loop to delete all .miff images afterwards. Alternativly just leave them and if you use the same name for the tempory images they will be overwritten every time the code is run.

Related

Translate a ImageMagick convert shell script to Python/PIL script

I'm trying to translate some shell scripts using the convert cmd to python script using PIL.
Here's the original shell script:
convert \
-resize 25% \
+repage \
-background white
-quality 95 \
-flatten \
-gravity center \
-extent 200x200 \
img_a.png img_b.jpg
Here's what I've being able to translate so far:
# Paths
img_a_png_filepath = '/foo/bar/img_a.png'
img_a_name = Path(img_a_png_filepath).stem
img_b_name = f'{img_a_name}.jpg'
img_b_jpg_filepath = f'/foo/bar/{img_b_name}'
# Converting to JPEG
img_a_png = Image.open(img_a_png_filepath)
# -background white
white_bg = Image.new('RGBA',img_a_png.size ,(255, 255, 255, 255))
white_bg.paste(img_a_png, (0, 0), img_a_png)
white_bg = white_bg.convert('RGB')
white_bg.save(img_b_name, 'JPEG')
# -resize 25%
img_b_jpg = Image.open(img_b_jpg_filepath)
img_b_jpg = img_b_jpg.resize((img_b_jpg.size[0]*0.25, img_b_jpg.size[0]*0.25))
img_b_jpg.save(img_b_name, 'JPEG')
I guess the original script is trying to crop from the center with the -gravity center and extent 200x200 but I have no clue how to translate both of those options to PIL.
You're nearly there! You've got the white background, the -flatten (using paste) and the resizing.
You just need to do the -extent from the centre, so...
get the width, and halve it int(im.width/2) and subtract 100 to use as the left edge and add 100 to use as the right edge
get the height and do the same to get top and bottom
crop.
If smaller than 200x200 paste onto a 200x200 canvas.
By the way, there's no need to save the images repeatedly as you are currently doing - just carry on processing what you've got.

How to fit images within fixed aspect ratio without resizing or cropping with ImageMagick?

My photography website is connected to print services, but they only offer a few standard aspect ratios (2:3, 4:5, 1:1, etc.). Many of my photos use other aspect ratios, and are not offered as prints at all as a result.
To fix this, I'd like to use ImageMagick CLI or another tool to put the images on a canvas with a standard aspect ratio, say, 4:5. There must be no resampling or cropping of the source image at any stage, only the outer dimensions (canvas) may grow.
The concept I've come up with is:
Take a source image with non-standard aspect ratio, and expand its canvas by 20% in all directions with white. This must be in relative terms due to varying source image sizes, as pixel dimensions would require resampling of the image.
Set the resulting matted image inside another white canvas in 4:5 aspect ratio. Either vertical or horizontal sides would be cropped in most cases, but the crop would only affect the 20% white border, not the source image.
The output should be images of varying pixel dimensions, in a fixed 4:5 aspect ratio, with white borders around all four edges of varying thickness. I've created a sample page with before and after views on my website.
Due to wildly varying aspect ratios, I would have to run all my photos multiple times through the script with varying destination aspect ratios, and pick and choose the most balanced aspect ratio for each. Tedious, but I don't think there's a way to automate that.
Any idea how to accomplish this? Or better suggestions?
I'm using 6.x of IM in either Windows or Linux, not on a website.
I tend to work in php and am off to bed now but here is an example using php and version 7. As you can see in version 7 you can have some of the calculations within the command. On version 6 it will have to be a separate line saved into a variable and then the variable will be used in the command.
Only tested quickly to see if it worked and I may have the landscape/portrate logic the wrong way around. But it should give you an idea how it could work.
<?php
// Setup the image to use
$image = '_MG_4949.jpg';
// Get the dimensions of the image into an array
$size = getimagesize("$image");
// Aspect array
$aspect = array(.87, 1.45);
// If landscape original image do this
If ($size[0] > $size[1]) {
foreach ( $aspect as $value ) {
exec("magick $image -background white -gravity center -extent \"%[fx:w*1.2]\"x\"%[fx:w*$value]\" $value.jpg");
}
}
// If portrate image do this
else {
foreach ( $aspect as $value ) {
exec("magick $image -background white -gravity center -extent \"%[fx:h*$value]\"x\"%[fx:h*1.2]\" $value.jpg");
}
}
?>
EDIT the above code should be OK now
Here is a php version for V6 ( no php getimagesize function this time ) and both versions you should be able to convert to bash or batch files.
// Setup the image to use
$image = '_MG_6790.jpg';
// Get the dimensions of the image into an array
$height = exec("identify $image -ping -format %[fx:h] info:");
$width = exec("identify $image -ping -format %[fx:w] info:");
// Aspect array
$aspect = array(.87, 1.45);
// If landscape original image do this
If ($width > $height) {
foreach ( $aspect as $value ) {
$newWidth = $width*1.2;
$newHeight = $height*$value;
exec("convert $image -background white -gravity center -extent {$newWidth}x{$newHeight} $value.jpg");
}
}
// If portrate image do this
else {
foreach ( $aspect as $value ) {
$newWidth = $width*$value;
$newHeight = $height*1.2;
exec("convert $image -background white -gravity center -extent {$newWidth}x{$newHeight} $value.jpg");
}
}

powershell image transformation

I want to perform image transformation in powershell. Basically I want to insert a circle that contains different ratios of red/blue/green and yellow (this varies from picture to picture) onto another picture.
Right now I've stubmeld upon PSImageTools (http://psimagetools.start-automating.com/), but as far as I can tell, they only allow me to overlay one picture on to another, but since the ratios of the 4 colours vary, I have to dynamically create a circle that can be mapped onto the existing picture.
How can I perform the hardcore pixel that I require, not just pasting 2 images together, but defining the colour of the single pixel in powershell?
The following makes edits to an image:
$imageOld = "C:\My\File.jpg"
$imagenew = "C:\My\File2.jpg"
# Load the System.Windows.Forms library
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms");
$image = [System.Drawing.Image]::FromFile($imageOld)
$graphics = [System.Drawing.Graphics]::FromImage($image)
# 50% transparent white
$color = [System.Drawing.Color]::FromArgb(128, 255, 255, 255)
$brush = New-Object System.Drawing.SolidBrush($color)
# Draw a 500px circle located at (300, 300)
$graphics.FillEllipse($brush, 300, 300, 500, 500)
$image.Save($imageNew)

Using rmagick to colorize an image like in photoshop

So I have this base image:
And in photoshop I do a basic layer color overlay, with the rgb colors:
r: 244, g: 93, b: 0
This gives me the amazingly vibrant:
What I'm trying to do is colorize the same image in rmagick, so if I do the following colorize:
img = Magick::Image.read('brush.png').first
img = img.colorize(100, 100, 100, Magick::Pixel.new(244, 93, 0, 1))
img.format = 'png'
img.to_blob
It gives me this really washed out orange image:
My questions is, how do I colorize this image with those rgb params in imagemagick / rmagick, to get the same vibrant color that I got in photoshop.
Thanks.
At the commandline, I think you want something like this:
convert brush.png \( +clone -fill "rgb(244,93,0)" -colorize 100% \) -compose colorize -composite out.png
So, with the +clone I am creating another layer the same size as your image and entirely filling it 100% with your orange colour and then composing it over your image with the -composite to blend the opacity and colour.
I really don't speak Ruby, but I think it will be along these lines:
#!/usr/bin/ruby
require 'RMagick'
include Magick
infile=ARGV[0]
img=Magick::Image.read(infile).first
w=img.columns
h=img.rows
ovl=Image.new(w,h){self.background_color=Magick::Pixel.new(244*256,93*256,0)}
img.composite!(ovl,0,0,Magick::ColorizeCompositeOp)
img.write('result.png')
Mark Setchell's command line works for me (Windows), with slight modifications...
convert greyscale.png +clone -fill "rgb(244,93,0)" -colorize 100% -compose colorize -composite colour.png
Found this link on recolouring with rmagick...
ftp://belagro.com/Redmine/ruby/lib/ruby/gems/1.8/gems/rmagick-2.12.0/doc/colorize.rb.html
Based on the code in the above link, with the greyscale conversion removed, does the example below work (I don't have ruby)?
# load the greyscale image
img = Magick::Image.read('greyscale.png').first
# Colorize with a 100% blend of the orange color
colorized = img.colorize(1, 1, 1, '#A50026')
# save the colour image
colorized.write('colour.png')
Used a colour picker to get the hex of your orange colour - rgb(244,93,0) = #A50026

Add a rectangle to the image using image magic

Good day.
How to impose white_rectangle.jpg on logo.jpg in the image below
using Imagemagic.
And a bonus question: what's Ruby's method can make the task.
def (path_to_image)
# impose white_rectangle.jpg on logo
end
This can easily be accomplished using RMagick:
require 'RMagick'
logo = Magick::Image.read("logo.jpg").first
rect = Magick::Image.read("white_rectangle.jpg").first
result = logo.composite(rect, x, y, Magick::CopyCompositeOp)
result.write "result.jpg"
An alternative is to just draw a white rectangle without using a composite image:
image = Magick::Image.read("logo.jpg").first
gc = Magick::Draw.new
gc.stroke = 'white'
gc.fill = 'white'
gc.rectangle x_start, y_start, x_end, y_end
gc.draw(image)
image.write "result.jpg"
Using ImageMagick command line tools, you can overlay one image with another like this:
$ composite white_rectangle.jpg logo.jpg -geometry +x+y result.jpg

Resources