deanm / omggif Goto Github PK
View Code? Open in Web Editor NEWJavaScript implementation of a GIF 89a encoder and decoder
JavaScript implementation of a GIF 89a encoder and decoder
This is a question about a GIF format in general.
Let's say I have a transparent background. The first frame has a black letter "L", the second frame has a black letter "I" (at the same place, as the "vertical part" of "L").
I would like to represent the second frame as a fully transparent sub-area, that would be copied into a previous frame, and would replace the bottom part of "L": like "L" - "_" = "I".
It seems like the the sub-area of a new frame is always blended "over" the content (transparent pixel can not replace non-transparent pixel). The only way how to make a pixel transparent again is by disposing it at a previous frame. Am I right? Or is there a way to copy transparent pixels from the sub-area?
Hi, i m using omggif lib in ES6, i am bit familiar about imagedata & disposal ,
i tried to play with
if (frame_num === 0 || frame_info.disposal === 2 /* restore to bg */)
Line 30 in 0ec9069
but it is not working well in all gifs, let me explain bit please.
i am referencing two situations
situation 1: clearing imageData for every single frame
for (let i = 0; index < framesLength; i++) {
imageData = ctx.createImageData(width, height); // clearing imageData for every single frame i.e. blank data
omggif.decodeAndBlitFrameRGBA(i, imageData.data);
ctx.putImageData(imageData, 0, 0);
}
situation 2: clearing imageData only if disposal===2
for (let i = 0; index < framesLength; i++) {
if( gif.frameInfo(i).disposal ===2){
imageData = ctx.createImageData(width, height); // clearing imageData on disposal ===2 i.e. blank data
}
omggif.decodeAndBlitFrameRGBA(i, imageData.data);
ctx.putImageData(imageData, 0, 0);
}
need not to mention, if i dont clear imageData at all, every gif produces ghost frames..
please guide me when to clear disposal or canvas or any suitable method.
thank u
I don't know what the structure gif binaries have, but unless gif requires some headers of how many frames are included in the beginning i would like to request a streaming functionality if it would be possible
In browser you would have to do it with ReadableStream
I would like for this to be able to run in the browser, so i would like to give you an example of what i would like to have
// Since the stream api don't include Readable stream we would
// instead have to use the readable stream. It works the same way roughly
var frameReader = new ReadableStream({
// gifWriter is gona consume this readableStream
// and for each time gifWriter call `rs.getReader().read()`
// it will call this pull function and ask for a new frame
pull(controller) {
if ( last_frame() ) return controller.close() // end the gif
var url = 'http://example.com/frame_02'
return fetch(url).then(res => res.arrayBuffer())
}
})
var gifReadableStream = omggif.gifWriter(frameReader)
// How you would consume the stream
// higher level of abstraction to concatenate all chunks
new Response(gifReadableStream).arrayBuffer().then(buffer => {
var blob = new Blob([buffer], {type: "image/gif"})
// do something with the blob
})
// lower level to consume all chunks
var reader = gifReadableStream.getReader()
var pump = () => {
reader.read().then(result => {
// one chunk is the same as if you would add a frame and
// get back what has been compiled into a gif frame
var chunk = result.value
// store or upload chunk in filesystem or the server
// calling pump here would actually result in the pull function above being executed
// this would mean omggif don't withheld any memory as everything is getting
// piped from a input stream to a output stream
if (!result.done) pump()
})
}
pump()
This would allow you to save more memory and build much larger gifs
Hi There,
A program I am using outputs gif87a format files and although your decoder can read them (I think they are a subset of Gif89a) you have a sanity check that makes sure the header is gif 89a. If I get a chance I can fix this and make a PR. Would you like me to do that or fix it yourself.
Ben
Apologies if this should be more obvious but is there a way to get the global palette buffer from GIFReader?
I am decoding GIFs into RGBA frames and then later want to encode the frames back into a GIF. I can't do this without a palette for obvious reasons but I am having trouble understanding what GIFWriter wants as the palette.
I am currently passing in something that is effectively made like this:
var globalPalette = arrayBuffer.slice(
gifReader.global_palette_offset,
gifReader.global_palette_size + offset
);
But I get the Invalid code/color length, must be power of 2 and 2
error. Any tips are greatly appreciated!
First off - this is a really awesome library so thank you for taking the time to write it! I really want to increase my total images to 180 or 360, but when I do so the resulting gif never lasts the full 360 frames... The setTimeout, progress bar, etc - all seem to be working properly for the full 360 frames, but the resulting gif always is much shorter. I'm wondering if you know why this might be or how I might be able to go about fixing this?
This GIF:
http://giphy.com/gifs/willkim-art-animation-wMymb2jKg27Je
doesn't decode well. It ends up looking like a glitchy mess. I'm just blitting the RGB data to a canvas element and then copying the canvas to images in the DOM. I have no idea what to do differently =/
I don't know why this happens but here's the GIF that triggers this error:
http://media.giphy.com/media/8OfdvDB2F9CUg/giphy-tumblr.gif
I looked in a text editor and the GIF is full of zeros. Tried to modify GifReader so it would ignore those and it complained about the following codes as well: 0xc3, 0x61. No clue =/
I know you have a permissive license, thanks for that, but would you be willing to put a standard license on this such as MIT? That would help out a lot! Thanks.
Hi, thanks for this great project!
There's no documentation I can see, and although that's ok, it's hard to know which APIs are considered public and which are unstable and possibly changing in a minor or patch semver update.
Which methods are intended to be public?
We are considering exposing the frameInfo
result in the get-pixels
module.
The decoder will go into an infinite loop upon parsing a GIF that has been truncated in such a way that the end-of-block marker never occurs. For example, this GIF.
I have a working fix, will post in a PR.
About 50% of the gifs that I am looking at seem to be compressed with a standard or a setting that this library isn't supporting, where blocks of color are missing and are rendered transparent.
Here is a screenshot of an example http://i.imgur.com/sgqGaW7.png
I would be happy to help address this issue but I'm not that familiar with the spec to know what needs to be worked on. If you have insights into next steps please let me know.
Is it true that we have to define and pass a color palette with each frame? Is there any chance that we could use something like https://github.com/antimatter15/jsgif/blob/master/NeuQuant.js to make the palette? (That project has some bugs with colors, but I don't know if it is in the quantization or the encoding.)
I can go from a gif to an array of frame objects.
How can I get an image file of some sort, for example to draw to canvas, from the objects?
So I thought that this could be handy for easily creating these hypnotic animated gifs that you can find on the internets and I decided to try to export a 3d animation with it.
After figuring out how to get a usable string out of the buffer (thus displaying the example gif on the page) I started to write my own images.
Then I realised that I need to build the palette, then remembering the 256 max colors. After crappily decimating the color values I got my palette down to 77 or so. But now I keep getting these errors:
Invalid code/color length, must be power of 2 and 2 .. 256.
Palette must be a multiple of 3 (RGB components).
I've tried to initialise the array with 256 values but it's not really helping.
https://gist.github.com/4582927
Any ideas?
I am lost on the following problem:
"gifReader.decodeAndBlitFrameRGBA(frameNumber, pixels)" works for the first frames of a gif, but for higher frame numbers, I get only corrupted image data.
Throwing this error and returning empty gif file. Please help me to resolve this.
Throwing a string doesn't include a stack trace in Node.js. This made it harder for me to figure out which code was going awry.
The solution is just to throw new Error()
on that same string. I have a PR.
I have written a GIF animation library using Jimp that supports pluggable encoders and decoders. I made a default codec by wrapping omggif. However, I'm finding problems requiring correction.
Is this repo still active, or should I maintain my own copy of omggif with my library (copying forward your license), as Jimp does?
The errors so far are:
(1) I have an improperly formed GIF that sends omggif into an infinite loop.
(2) omggif should throw instances of Error to capture the stack trace of the code that handed omggif improper data. It currently throws strings.
Thanks for your help. I'm really impressed with this library.
FYI, by necessity, my test suite is becoming a test suite for omggif.
Hi Dean,
I'm trying to make small GIFs, so I compute deltas between frames and assemble the global palette in the process. I see that omggif takes the global palette as an option only in the constructor, so it has to be prepared in advance. This means the encoder cannot be used in a streaming mode where indexed frames are fed to it ahead of finalizing the full palette. This in turn means that i have to store all frames prior to feeding them all to the encoder only at the end.
Is there any way to specify the global palette after all the frames are placed? Perhaps if there is some issue with offset re-computation, I can simply predefine some fixed palette size in the constructor without having it ready in advance.
thanks!
Leon
This package fails on https://www.npmjs.com/package/license-check
other packages are depending of this package, please fix it.
Edit: nevermind I worked it out after a good night sleep.
I'm using some library in JS and they used this project.
Unfortunately, there is no package in bower manager.
Please upload this one into bower :).
Thanks.
Attempting to decode bytes 474946383961494638fd627a4421
raises an error:
TypeError: Cannot read property 'toString' of undefined
It seems to happen on line 459 of omggif.js
:
"Unknown graphic control label: 0x" + buf[p-1].toString(16));
This code reproduces:
const omggif = require('omggif')
const bytes = Buffer.from('474946383961494638fd627a4421', 'hex')
omggif.GifReader(bytes)
This was found by running jsfuzz on the module.
During the development of gifwrap
, I occasionally provided omggif
with a buffer that was too small to handle the encoding. It would throw an exception that I found unhelpful and always left me grasping at straws to ID the problem.
I have a PR that detects this situation and throws a meaningful exception.
Thanks to your library, I implemented GIF opening and saving into my online editor Photopea.com. It can convert between APNG and GIF and also minify GIFs and APNGs (by shrinking a color palette). In order to make an efficient GIF encoder, color quantization (256 colors) and efficient frame "cropping" is necessary.
I made a library UPNG.js for decoding and encoding PNG (APNG). There is a function UPNG.encode.compress()
, which performs quantization and frame cropping on 8-bit RGBA images. Its output can be used as an input for omggif.
Maybe you could mention UPNG.js in Readme, so your users could combine both libraries to make an efficient encoder :)
I have no idea what GIF 89a is..and why I should use such a thing..thanks!
Hello,
first thanks for this great library. I'm using it for a experimental javascript strategy game, where games can be recorded as gif. Here is a sample gif:
The project page is here: http://pl4n3.blogspot.de/2013/03/strategy-game-experiment.html
So, while testing it, some resulting gifs were corrupt. They contained e.g. 100 frames but only e.g. 30 frames were shown (looped).
This happened with following preconditions: global palette is 6bit, no local palette, the frames are smaller than the image, with a position. Also disposal:1 and a transparent index is used. When I changed the gif creation so that all frames are image size and position (0,0), the bug didnt occured.
Next I tried to read the corrupt gif with GifReader and got the error "Unknown gif block: 0x0". With a binary editor I removed the 0 byte at the respective adress and the gif was fine, all frames were shown. So there was one 0 byte wrong in the gif data. I looked into GifWriter code but couldnt spot the cause, I guess its within GifWriterOutputLZWCodeStream. A problem is, that the bug occures very seldom (here about once in 100 frames).
So my current workaround is now: After the gif is generated I call "new GifReader(buf)", but the GifReader is modified, so that it doesnt throw an error, but splices the buffer were a wrong 0 byte is. As result I get a bugfree gif.
I am curious, if the cause of this bug can be found.
Greetings & again thanks for the great lib!
When disposal method 2 is set, canvas needs to be cleared to the background color before doing the blit operation when using the decodeAndBlitFrame* functions.
example gif / JS attached.
gif_test.zip
There are many gifs out there, which throw "Error: Invalid block size" in this library.
Could we add partial support for corrupted GIFs? The question is "how much corrupted".
I would like the GIF reader to be at least as good as a web browser. I.e. it should be able to recover those frames, which a web browser can recover and play. I believe it should be enough to add just several lines of code, to make GIF reader work with this "type of corruption". What do you think?
Would you be interested in splitting the reader and writer into two separate files? It would make it easier to just use one or the other in node/browserify.
I could make a PR
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.