Cyan101
Cyan101

Reputation: 19

How do i paste an image onto every frame in a gif in ruby with rmagick

require 'rmagick'
require 'open-uri'
include Magick

giflist = Magick::ImageList.new('pewpewpew.gif')
open('avatar.jpg', 'wb') do |file|
  file << open('https://cdn.discordapp.com/avatars/120571255635181568/8e37daf54a9c631afe659ebcb87af959.jpg').read
end

avatar = Magick::Image.read('avatar.jpg').first

newavatar = Draw.new {
  self.fill = 'black'
  self.stroke = 'transparent'
  self.tile = avatar
  self.fill_pattern = avatar
  self.stroke_pattern = avatar
  self.gravity = NorthGravity
}
giflist.each { |image| newavatar.composite(20, 20, 40, 40, image) }# x, y, width, height, image
giflist.write('newgif.gif')

So basically i'm trying to paste this jpg onto a gif, but for some reason nothings happening and i'm not getting any errors. the image is downloaded properly so i know thats not an issue

gif -> Gif Link

Upvotes: 0

Views: 241

Answers (1)

VxJasonxV
VxJasonxV

Reputation: 975

I'm going to be completely honest, I have no idea why this isn't erroring as written. I can tell you Ruby'isms on why things aren't working, but the more I try and explain the behavior, the more I fail to prove it.

Anyway, here's what I think I know:

newavatar.composite(20, 20, 40, 40, image)

This is drawing the gif on top of the avatar. But you can't just swap the variables. That blows up with "no cur_image defined".

giflist.each { |image| newavatar.composite(20, 20, 40, 40, image) }

Either each of the frames are being returned into newavatar, or they're just being thrown away since there's no assignment happening (image = giflist.each { … }). But again, no matter which way I try and put it together, I get a variety of errors.

This is the solution I came up with:

require 'rmagick'
require 'open-uri'
include Magick

giflist = Magick::ImageList.new('pewpewpew.gif')
open('avatar.jpg', 'wb') do |file|
  file << open('https://cdn.discordapp.com/avatars/120571255635181568/8e37daf54a9c631afe659ebcb87af959.jpg').read
end

avatar = Magick::Image.read('avatar.jpg').first

giflist.each { |image| image.composite!(avatar, NorthWestGravity, 40, 40, OverCompositeOp) }
giflist.write('newgif.gif')

And more importantly, the result:

Avatar overlaid on gif

You'll note the use of composite!, which replaces the frames in place (still in the giflist variable).

The last part you have to do is reduce the size of the avatar to 40x40, which should only be a single line, and I'm pretty sure that's all that's left.

Much simpler, no?

Upvotes: 1

Related Questions