GIF to animation

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Ranguna259
Party member
Posts: 911
Joined: Tue Jun 18, 2013 10:58 pm
Location: I'm right next to you

GIF to animation

Post by Ranguna259 »

Is there a way to transforme a gif into a LÖVE animation ? (it can be throught ANaL or any other animation code)

I'm currently thinking on making a pokemon clone to test out some of my libs and I wanted to make this clone a little different from others, I wanted to make all pokemon animated like the Black and White (1 and 2) animations, it was realy hard to find the pokemon spriteSheets (front, back, shiny front and shiny back) animations but I came across this website which has ALL of the pokemon in all their state, it's an awesome compilation.
The thing is LÖVE doesn't load gifs, I've tried unpacking a gif but I got 680 pngs as output and I don't want to make huge spriteSheets out all the pngs, maybe my problem here is the program I used to unapck, ffmpeg and this was the command I used:

Code: Select all

ffmpeg -i 494.gif assets\frames\a%d.png
on this gif:
Image

Then I used this code to pack them all into a png sheet file:

Code: Select all

	sheet = love.image.newImageData(53*680,62)
	local rem = 0
	for i,file in ipairs(love.filesystem.getDirectoryItems('assets/frames')) do
		if string.find(file, '.png') then
			local img = love.graphics.newImage('assets/frames/'..file)
			sheet:paste(img:getData(),53*(i-rem)-53,0,0,0,53,62)
		else
			rem = rem +1
		end
	end
	sheet:encode('sheet.png')]]
All the code does is it goes throught the frames of the gif (that I got throught ffmpeg) and it "pastes" each frame into a huge sheet (36040x62).
This was the output:
Image
(link to the image on mediafire)

And then I tried loading it into ANaL, I got a static image:
Image
How I loaded it:

Code: Select all

function love.load()
  test = newAnimation(love.graphics.newImage('assets/sheet.png'),53,62,1,680)
end
function love.update(dt)
  test:update(dt)
end

function load.draw()
  test:draw(0,0)
end
So I guess LÖVE doens't load assets that big or I'm doing something wrong, but do you guys have a better ideia to port all gifs into LÖVE ?
LoveDebug- A library that will help you debug your game with an on-screen fully interactive lua console, you can even do code hotswapping :D

Check out my twitter.
User avatar
slime
Solid Snayke
Posts: 3170
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: GIF to animation

Post by slime »

Ranguna259 wrote:it "pastes" each frame into a huge sheet (36040x62).
[wiki]love.graphics.getMaxImageSize[/wiki].

I don't believe any graphics card / driver will load images with a width or height greater than 16384 pixels, and even that is only supported on GPUs with DirectX 11-capable hardware, generally.

Making sure the width or height of your images isn't greater than 2048 is pretty safe. You can probably get away with 4096 without it failing on anyone's system if you also require shader and canvas support.
User avatar
Ranguna259
Party member
Posts: 911
Joined: Tue Jun 18, 2013 10:58 pm
Location: I'm right next to you

Re: GIF to animation

Post by Ranguna259 »

I got 16384 but it'd be kind of stupid from my part to tell people that they'd have to have a DirectX11 compatible GPU to play a pokemon clone :P
But I want to port a gif into an animation and maybe I get 680 frames out of the gif because I'm using the wrong program(? maybe), if anyone knows a good program to unpack gifs into frame-by-frame animations or a technic to load gifs then I'd really want to know how because I'm completely lost I need to port 2596++ gifs :ultrashocked:
Last edited by Ranguna259 on Mon Feb 24, 2014 8:57 pm, edited 1 time in total.
LoveDebug- A library that will help you debug your game with an on-screen fully interactive lua console, you can even do code hotswapping :D

Check out my twitter.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: GIF to animation

Post by Robin »

53 * 680 = 36040 pixels. Most graphics cards don't support textures that large.

The only solution I see would be to split it up. First, use multiple rows, second (because just using multiple rows doesn't get more efficient than 1431x1612 px), split them up in multiple images. If you use, say, ten images for the animation, you'd have ten images of roughly 150x170 px, which would definitely work.

You can adjust the packing code to do it that way quite easily. It's harder to change the animation code. You're going to have to ditch AnAL, but it's really simple to whip up a replacement using [wiki]Quad[/wiki]s (it's how AnAL itself is implemented). It'd be maybe an hour of work.

Another angle is this: why are there so many frames? 680 frames -- you would expect a minute long loop with that number of frames, but it seems to loop after only ten seconds or so, so does that mean there are some redundant frames in the .gif? Or does it have something to do with how ffmpeg handles frames of different length?

I hope you can investigate these things yourself, and learn some things about ffmpeg, the GIF format and Quads. :)

EDIT: got ninja'd twice. This is how snails must feel.
Help us help you: attach a .love.
User avatar
Ranguna259
Party member
Posts: 911
Joined: Tue Jun 18, 2013 10:58 pm
Location: I'm right next to you

Re: GIF to animation

Post by Ranguna259 »

Alright thanks, time to study a little more on these subjects, I think I'm using the wrong ffmpeg code I'll search it on the web.

EDIT: was using the wrong ffmpeg code, here's the right one:

Code: Select all

ffmpeg -i gifimage.gif -f image2 -vf fps=fps=25 outputFile%d.png
I got 171 pngs out of this code :rofl:
Time to code some quads.

Coded the atlas packer (dirty code):

Code: Select all

	local n = 0
	local width,height
	for i,file in ipairs(love.filesystem.getDirectoryItems('assets/hello')) do
		if string.find(file, '.png') then
			if not width then
				width,height = love.graphics.newImage('assets/hello/out1.png'):getWidth(),love.graphics.newImage('assets/hello/out1.png'):getHeight()
			end
			n = n + 1
		end
	end
	local rows = 1
	done = false
	local on = n
	if n*width > 2048 then
		flimit = math.floor(2048/width)
	end
	while not done and flimit do
		if n*width > 2048 then
			rows = rows + 1
			if rows*height > 2048 then
				error('Limit reached, '..(rows*height)..'px.\nNumber of rows reached: '..rows ..' \nFrames left: '..n)
			end
			n = n - flimit
		else
		    done = true
		end
	end
	local atlas = {}
	local c = 0
	for i=1,rows do
		atlas[i] = {}
		for ii=1,flimit do
			c = c + 1
			atlas[i][ii] = {img = c, ii*width-width, i*height-height}
		end
	end
	local check = true
	if check then
		local c = 0
		for i,v in ipairs(atlas) do
			c = c + #v
		end
		if c < 171 then
			error('Frames missmatch, processed '.. c ..' frames, should have been '..on)
		end
	end

	sheet = love.image.newImageData(flimit*width,height*rows)
	for i,row in ipairs(atlas) do
		for ii,coords in ipairs(row) do
			if coords['img'] <= on then
				local img = love.graphics.newImage('assets/hello/out'..coords['img']..'.png')
				sheet:paste(img:getData(),coords[1],coords[2],0,0,width,height)
			else
				goto endd
			end
		end
	end
	::endd::
	flimit = nil
	sheet:encode('hello.png')
This code picks up all the frames located in assets/hello and then it will create rows as it hits the pixel limite (which is set to 2048) and then it'll add the frames side-by-side and once it's done it'll save the sheet as hello.png in the %appdata% dir in test/sheet and it'l draw the sheet on screen.
LoveDebug- A library that will help you debug your game with an on-screen fully interactive lua console, you can even do code hotswapping :D

Check out my twitter.
User avatar
AgentEnder
Prole
Posts: 5
Joined: Wed Mar 05, 2014 7:30 am

Re: GIF to animation

Post by AgentEnder »

ok, i know this is an old post but thank you so much for posting this, i was originally looking for a way to add gif animations but through the code shown here instead i was able to automate my map loading process :) thanks

Code: Select all

for k, v in pairs (love.filesystem.getDirectoryItems('/bin/maps')) do
		print(v)
		if love.filesystem.isDirectory('/bin/maps/' .. v) then
			for f, g in pairs (love.filesystem.getDirectoryItems('/bin/maps/' .. v)) do
				if love.filesystem.isFile("/bin/maps/story/" .. g) then
					table.insert(maps, "/bin/maps/story/" .. g)
				end
			end
		end
		if love.filesystem.isFile("/bin/maps/" .. v) then
			table.insert(maps, "/bin/maps/" .. v)
			print("Loaded " .. v)
		end
	end
	for k, v in pairs(maps) do
		print("Loading: " .. v)
		v = string.sub(v, 1, #v-4)
		require(v)
	end
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 15 guests