I want to manipulate the image data of every frame of an animated gif as it plays in the browser, and I want to do it using HTML5 canvas and Javascript. For example, I have an animated gif, and I want to convert every frame to grayscale as it plays in the browser. Is this possible? Whenever I manipulate the image data in an animated gif, only the first frame is shown (correctly manipulated) and the gif won't play any further. This would be a very useful technique if there was a solution for this. Thank you.
EDIT: Is there a way to query the current frame of an animated gif in Javascript, so I can just use putImageData into the image as the animation progresses?
As this page points out, you can use drawImage() to draw the GIF on the canvas, and at the moment it'll draw the current frame from the GIF in Gecko and WebKit -- but not in Opera, and also not according to the spec, so it's not a good idea to rely on this behavior. As far as I know there's no way to get individual frame data from the DOM; I looked into this for a while before writing jsgif (which was mentioned in another answer, but isn't really meant for any sort of practical use as it is -- it's very inefficient, for one).
If you can get away with unpacking the frames on the server and then animating them manually (e.g. like Gmail does), that might be your best option.
Related
I am trying to create a water ripple effect in a video embedded in HTML5 default web player.
I am doing it fine with using images and and a overlay canvas on top of it, but what I am trying to do now is to get single frames from a video and output it to a canvas every 1-5ms using this tutorial.
And I am stuck at this point, I can output frame into another canvas using
canvas.toDataURL() function.
I have seen advanced web-based video players that allow for applying Processing.js sketches on top of videos, would that be a good solution?
My question is: what would be the best and most reliable solution for applying visual effects (water ripples in this case) using JavaScript to a video playing in HTML5 media player.
My question is: what would be the best and most reliable solution for applying visual effects (water ripples in this case) using JavaScript to a video playing in HTML5 media player.
In my opinion the best approach would be to use WebGL to create the effects, using the video as input texture and a simple flat geometry that is manipulated using a animated bump-map - or - directly manipulating the vertices - or - a perhaps a shader program, and then output the result to a canvas.
I would not place the video in DOM at all but create control buttons and display those together with the output [webgl-]canvas in DOM.
The obvious drawback would be besides from slightly more complex code, when used on computers which doesn't have a GPU (but that would be a drawback in any case and more so if you used a regular 2D canvas and pixel manipulation).
This is of course very broad in terms of code example. But I assume you get the general idea.
A couple of notes:
[...] what I am trying to do now is to get single frames from a video and output it to a canvas every 1-5ms [...]
This is sort of pointless in regards to the time-budget, as the typical monitor can only refresh the image every ~16.7ms which means you're wasting at least 3-4 frames that are never displayed.
Also, a typical video source never runs faster than 30 FPS (in the US, 25 FPS in Europe) which means there is only a new frame every 33.3ms (there are of course special case videos such as VR/AR, stereoscopic, games and "Mac" recorded video etc. that may use higher fps - but for the most part anything > 30 fps is usually wasted cycles) which allows for a higher time-budget for processing per frame.
I can output frame into another canvas using canvas.toDataURL() function [...]
Outch! :) This comes which a huge overhead. The browser would have to use line filtering (in case of PNG - well, some browsers skip this and use filter 0), compression, base-64 encoding, then apply the source to an image element, decode the base-64, decompress, defilter...
You can instead simply use the source canvas for drawImage() directly and only have to deal with a in-memory bitmap (super fast!).
All that being said: if simplicity is important code-wise, you can of course do all this using a 2D canvas. You can use drawImage() to displace pixels/blocks and therefor work on the GPU (but not necessarily faster than working on the bitmap directly depending on how you apply the actual displacement).
But there are still many caveats such as video source and destination resolution which has a exponential impact on performance, limited use of the GPU as you still would have to do multiple serial operations versus parallel operations with webgl/gpu and so forth. In essence, the performance will suffer compared to a webgl solution.
If you want to get high performance you can use WebGL. Following is a github reop for Water ripple project.
https://github.com/sirxemic/jquery.ripples/
Following is a ruining example for jQuery WebGL Ripples
http://sirxemic.github.io/jquery.ripples/
Think this might help
You can do it in several ways. You can write core javascript code with canvas.
But I think it is best to use Jquery plugins. There are several plugins available for water ripple.
You may check the following links:
https://github.com/virtyaluk/paper-ripple
https://github.com/sirxemic/jquery.ripples
https://github.com/andyvr/water-ripple
I am using createjs library, and my game has a large bitmap on the background, in order to fill a window in full HD resolution. In lower resolutions i use a pan and scan like method. But the action is always limited in a smaller area of the canvas.
So i would like to know if it is possible, and how, to gain performance by caching static areas, or using any other technique.
For the sake of the argument here is a graph that demonstrates my situation :
I 've already tried to put the background image behind the canvas element using CSS here :
How to center a canvas on top of a background image
But CSS is driving me insane...so please bear with me...
:)
Thank you in advance!
In EaselJS every DisplayObject has a cache method, which is exactly doing what you want - it takes the painted stuff and puts in on a off-screen Canvas: http://www.createjs.com/docs/easeljs/classes/DisplayObject.html
Afterwards it takes the image-data from the off-canvas for every repaint (basically it's just a drawImage call afterwards).
Try to only cache painted areas - if you cache empty areas, you will lose performance. However if your background is just a static image you should still keep it as a normal DOM/CSS background - there isn't any performance benefit from caching a bitmap.
I had the same idea once, and I think what you are asking for is getImageData() and putImageDate()
image = context.getImageData(x,y,width,height);
context.putImageData(image,x,y);
However, I still found the performance of this to be very poor (sorry, I can't provide any actual numbers any more), and the best and also most popular way to achieve better performance seems to be to make a second canvas just for the background, or, if you really just have a static background image, use pure CSS like you originally wanted.
context.drawImage() can also draw from another canvas element, maybe you can utilise this in some way and create inivisible "canvas caches". But I still think that it's easier to learn CSS than implement something like this.
I am not familear with createjs, but you can try to draw / clear only on active area. This way you will not redraw inactive areas with each frame.
if inactive areas are not completely static, you can use separate canvas elements for them, and draw those on the main canvas once something have changed on that area (inactive area). I ho
I am making a game that allows the player to link to their own gif images and immediately make them playable in the game, and need to convert animated .gif files into spritesheets.
I have a jsfiddle that will load any image you past into the input, but it only loads the first frame:
http://jsfiddle.net/40k7g0cL/
var animatedGif = PIXI.Sprite.fromImage('http://i.imgur.com/egzJbiI.gif');
But pixi.js asset loader can only seem to load the first frame of an animated .gif file and not the rest.
All the information I can find on this subject says I should convert the animated .gif file into a SpriteSheet ahead of time, however this is not possible because the player is going to be supplying the .gif images as they play, so I can not pre-process them ahead of time.
Is there an easy way to load an animated .gif image, having it automatically converted to a SpriteSheet or MovieClip or even an array of Texture objects?
If there is not a simple solution already in pixi.js, do I need to write my own plugin, perhaps using something like jsgif to process the .gif and separate each frame manually?
Any suggestions on how to go about generating a SpriteSheet from an animated .gif client-side in the browser (in javascript) could be useful.
Sorry, there is no way to achieve this directly with pixi.js.
As you suggest, it seems that jsgif is the only low-level implementation of gif for client-side javascript. Also, exists a fork of this called libgif-js, a little easier to analyze, and it can offer a clue for build the SpriteSheet.
The process to separate the frames would be:
Load the image data.
If your app is online, you have to use the File API (see here) to read local files.
You'll get an ArrayBuffer or String with the gif's raw data, that can be passed to new Stream(data).
Parse the data:
Call parseGIF(stream, handler). The second library can help a lot to understand this process.
Customize handler and callbacks to get what you need (width, height, frames...).
Create your SpriteSheet according to your rules:
If you chose save the frames as ImageData, use a hidden canvas (it can be the same that in the parse) to draw them in the right positions to form your SpriteSheet.
Take the final image and use it:
You can use, for example, canvas.toDataURL(*format*) (first, resize canvas to SpriteSheet dimensions) to get the image as a base64 url.
I have been looking at plenty of tutorials on how to do proper HTML5 animations using javascript and request animation frame and even in the demos it seems like the animations look blury like the image being redrawn leaves a ghosted image of itself behind for a breif second. But then I see games like microsofts ported version of cut the rope that appears to have fixed this issue. Does anyone know a way to make this canvas effect less apparent?
I'm guessing the problem you have is that the new image is being redrawn before the previous image was cleared. I suggest making sure the canvas is cleared, or at least the area in which the image is being re-drawn. Although, I experimented with clearing the whole canvas vs clearing a specific section of the canvas, and up to a certain size (roughly 800x600), clearing the whole canvas was faster.
I use canvas for my (in-progress) game: http://www.dacheng.me/dBoom
Feel free to browse the JS source code!
I think what you're looking for is window buffering:
http://en.wikipedia.org/wiki/Multiple_buffering
Basically the idea is to use two different windows/canvas elements that are interchanged after being drawn completely so that you're switching between fully drawn "frames". This technique is used in OpenGL and almost any other legitimate graphics program that exists today.
Is there a way to resize the actual image using JavaScript? I'm not talking about modifying the DOM to get the browser to resize the image. I actually want to resize the image's pixel data and then display that.
Basically my problem is: Firefox completely fails at downsizing images with delicate features because it only has Nearest Neighbor and Binlinear. Every other browser -- even IE -- has Bicubic support. There's talk of this being included in the near future but that talk has been going on for over a year.
I don't mind downloading the full sized images because I want them downloaded anyway. When the user hovers over the small version of an image, the large version immediately appears elsewhere on the page. If I did server-side resizing I'd have to download BOTH copies of the images which would result in even more traffic. If there's no other workaround then this is what I'm going to have to do... I just don't want to.
It is possible. You get a image on the same domain, write to canvas, then manipulate pixel data from there (complicated, but possible I'm sure), and then either use that or output as png/gif/jpg... BUT... I don't think you will find it will better way to preserve delicate features that CSS.