-
Notifications
You must be signed in to change notification settings - Fork 0
Drawing
To draw lines or disk shapes on top of an image, use draw_line
and draw_disk
.
The method draw_line
takes 5 or 6 arguments (the width
argument is optional) specifying the start and end points of the line as well as its color and, optionally, its width.
The following line draws a red line from (x0, y0) to (x1, y1) of width 1. The coordinates as well as the width can be floats. The color argument must have the same number of channels as the image on which the line is being drawn.
img_with_line = img.draw_line(x0, y0, x1, y1, [255, 0, 0], 1)
Below we show a more involved example where draw_line
is used to create the following animation:
Although not visible on a white background, the image fades out towards the edges by decreasing alpha after a certain distance from the center of the image. Thus the image can be placed on top of any background without creating a jarring white square around it.
require 'imgrb'
#Two 'planets' orbiting around a common center at different distances and speeds
radius0 = 60
radius1 = 100
angle_speed0 = Math::PI/(7*3)
angle_speed1 = Math::PI/(13*3)
planet0_angle = 0
planet1_angle = 0
width = (radius1+35)*2
height = width
center_x = width/2.0
center_y = height/2.0
anim = Imgrb::Image.new(width, height, [255, 255])
#Create a disk shaped white background that fades out (alpha -> 0 as we approach
#the edge of the image)
fade_out_dist = 32
bg_limit_border = 5
coeff = -255.0/(fade_out_dist - bg_limit_border)
const = -coeff*(radius1 + fade_out_dist)
anim.height.times do |y|
anim.width.times do |x|
center = width / 2
dx = x - center
dy = y - center
dist = Math.sqrt(dx**2 + dy**2)
alpha = coeff*dist + const
alpha = [0, alpha].max
alpha = [alpha, 255].min
alpha = alpha
anim[y, x] = [255, alpha.round]
end
end
##
#Update 'planet' positions for a number of time steps and draw straight lines
#between old and new locations for each planet as well as a line between the
#two planets.
planet0_pos = [Math.cos(planet0_angle)*radius0,
Math.sin(planet0_angle)*radius0]
planet1_pos = [Math.cos(planet1_angle)*radius1,
Math.sin(planet1_angle)*radius1]
546.times do |i|
frame = Imgrb::Image.new(width, height, [0, 0])
planet0_pos_old = planet0_pos
planet1_pos_old = planet1_pos
planet0_pos = [Math.cos(planet0_angle)*radius0,
Math.sin(planet0_angle)*radius0]
planet1_pos = [Math.cos(planet1_angle)*radius1,
Math.sin(planet1_angle)*radius1]
frame = frame.draw_line(planet0_pos[0]+width/2, planet0_pos[1]+height/2,
planet1_pos[0]+width/2, planet1_pos[1]+height/2, [0,55], 1)
frame = frame.draw_line(planet0_pos_old[0]+center_x, planet0_pos_old[1]+center_y,
planet0_pos[0]+center_x, planet0_pos[1]+center_y, [0, 55], 1)
frame = frame.draw_line(planet1_pos_old[0]+center_x, planet1_pos_old[1]+center_y,
planet1_pos[0]+center_x, planet1_pos[1]+center_y, [0, 55], 1)
#Safer to do anim.push_frame(frame.round, ...), since frame contains floats,
#but skipping is faster, and the floats should be truncated without issue.
anim.push_frame(frame, 0, 0, 1, 60, :none, :over)
planet0_angle += angle_speed0
planet1_angle += angle_speed1
end
#Pause the animation for 5 seconds
pause_frame = Imgrb::Image.new(1,1,[0,0])
anim.push_frame(pause_frame,0,0,5,1,:none,:over)
#Create a white translucent disk that is overlaid on top of the image several
#times to fade to white over time.
fade_frame = Imgrb::Image.new(width, height, [255, 0])
fade_frame.height.times do |y|
fade_frame.width.times do |x|
center = width / 2
dx = x - center
dy = y - center
dist = Math.sqrt(dx**2 + dy**2)
if dist <= radius1+5
fade_frame[y, x] = [255, 30]
end
end
end
30.times{anim.push_frame(fade_frame,0,0,1,30,:none,:over)}
anim.add_comment("Line animation")
anim.save("anim_orbit.png")
The method draw_disk
takes 4 arguments specifying the origin of the disk as well as its radius and color.
The following line draws a purple disk centered at (x0, y0) with a radius of 5.5. The coordinates as well as the radius can be floats. The color argument must have the same number of channels as the image on which the disk is being drawn.
img_with_disk = img.draw_disk(x0, y0, 5.5, [155, 0, 155])