-
Notifications
You must be signed in to change notification settings - Fork 0
Creating animated logo
kkrmno edited this page Dec 31, 2020
·
3 revisions
This example makes use of different dispose and blend operations to animate a logo together with different frame delays to adjust timing. The code also shows an example of applying a Gaussian blur. The logo is saved along with an ancillary tIME chunk saving information on when the image was last modified and a text chunk with a comment describing the image.
require 'imgrb'
#Scaling factor
scale = 1
#Scaled image and object sizes
width = (400*scale).round
height = width
center = [width/2, height/2]
small_radius = (width*0.075).round
small_size = small_radius*2 + 1
#Colors
small_circle_color = [255,111,100]
i_dot_color = [255, 190, 80]
i_color = [125, 210, 170]
#Radius of large circle being drawn
large_radius = (width/2 - small_radius*1.333).round
#Initial transparent black frame
logo = Imgrb::Image.new(width, height, [0, 0, 0, 0])
#Small circle used as brush to gradually paint the large circle
small_circle = Imgrb::Image.new(small_size, small_size, small_circle_color+[0])
small_circle.height.times do
|y|
small_circle.width.times do
|x|
xd = x - small_radius
yd = y - small_radius
dist = Math.sqrt(xd*xd + yd*yd)
if dist <= small_radius
small_circle.set_pixel(x, y, small_circle_color + [255])
end
end
end
#Apply a Gaussian blur with sigma = 1 to smooth out the edges of the "brush"
gauss = Imgrb::gaussian(1)
#2D convolution by 1D convolutions, since the Gaussian is separable.
small_circle_filtered = small_circle.convolve(gauss, :replicate)
.convolve(gauss.transpose, :replicate)
#The "radius" of the dot of the i-shape
i_radius = (small_radius*0.5).round
i_size = i_radius*2+1
#The two parts of the i-shape
small_square = Imgrb::Image.new(i_size, i_size, i_dot_color+[255])
small_rectangle = Imgrb::Image.new(i_size, (3.333*i_size).round, i_color+[255])
#Start of drawing:
#===================================
#Paint the large circle using the small circle as a brush
angle_step = Math::PI/50
(0..2*Math::PI).step(angle_step).each do
|theta|
x = Math.cos(theta) * large_radius + center[0] - small_radius
y = Math.sin(theta) * large_radius + center[1] - small_radius
#Alpha overlay the brush (circle) at its new position without removing
#pixels from previous frames. Play at 60 fps.
logo.push_frame(small_circle_filtered, x.round, y.round, 1, 60, :none, :over)
end
#After the large circle is painted, display the stem of the i-shape for 0.2s
#in the middle of the circle
i_stem_x = center[0]-i_radius
i_stem_y = (center[1]-i_radius-large_radius*0.05).round
logo.push_frame(small_rectangle, i_stem_x, i_stem_y, 1, 5, :none, :over)
#Then add the dot of the i-shape, thus completing the logo. Display this for 3s
#The :previous dispose_op is used so that, after the logo is done displaying,
#the animation is reverted to the logo before drawing the dot of the i-shape.
#This is done so that the dot can be drawn again at a different position.
i_dot_x = center[0]-i_radius
i_dot_y = (center[1]-i_radius-large_radius*0.35).round
logo.push_frame(small_square, i_dot_x, i_dot_y, 3, 1, :previous, :over)
#Drop the dot of the i-shape and have it bounce on top of the stem once before
#falling out of frame.
x_speed = -width * 0.0012
y_speed = -width * 0.0175
gravity = width * 0.00175
bounced = false
70.times do
#Use :previous so that the position of the dot can be updated by drawing on
#top of the logo without the dot.
logo.push_frame(small_square, i_dot_x.round, i_dot_y.round, 1, 60, :previous, :over)
i_dot_x = i_dot_x + x_speed
i_dot_y = i_dot_y + y_speed
if (i_dot_y + i_size) > i_stem_y && !bounced
i_dot_y = i_stem_y - i_size
y_speed = -y_speed
bounced = true
end
y_speed += gravity
end
#Add a 3s delay at the end of the animation before looping.
logo.set_frame_time(-1, 3, 1)
#Add a comment describing the image.
logo.add_text("Comment", "Animated logo for Imgrb.")
#Add tIME chunk showing latest modification to this image (UTC).
logo.add_chunk(Imgrb::Chunks::ChunktIME.assemble(Time.now.utc))
logo.save("imgrb_logo.png")