Page 1 of 1

GIF to animation

Posted: Mon Feb 24, 2014 8:26 pm
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 ?

Re: GIF to animation

Posted: Mon Feb 24, 2014 8:34 pm
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.

Re: GIF to animation

Posted: Mon Feb 24, 2014 8:47 pm
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:

Re: GIF to animation

Posted: Mon Feb 24, 2014 8:48 pm
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.

Re: GIF to animation

Posted: Mon Feb 24, 2014 8:54 pm
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.

Re: GIF to animation

Posted: Sat Aug 02, 2014 5:46 pm
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