I am simply loading a ton of images (about 5000) into "new Image()" objects and draw them each in a canvas by calling canvas.drawImage(image, 0, 0);
This works totally fine with IE10, but as soon as I am using Firefox I will get an stack overflow error, because somehow the memory usage of the Firefox rises and rises till it overflows. Does anyone have an idea why? I think the GC dont really collect my images after drawing them into the canvas. Even when I am using 100 Image objects and just cycle the src of the Image objects before drawing them, the memory usage rises and rises. I will test Chrome and Safari soon, but still need a solution for that, cause everyone is using "the best browser" Firefox.
EDIT:
function play() {
//calculated iLag here
//calculated wondow.FrameCtr here
var iFrameRate = Math.round(1000 / 25);
var oImage = new Image();
oImage.onload = function () {
renderImage(this);
}
//window.Video is an array of window.URL.createObjectURL(data) (about 500 items)
oImage.src = window.Video[window.FrameCtr];
oImage = null;
setTimeout(
function () {
play()
}, iFrameRate - iLag
);
function renderImage(oImage) {
$("#video")[0].getContext("2d").drawImage(oImage, 0, 0);
}
I do loop this video (500 items, 25fps) 10 times, and ff isn't even able to play it once, cause of stack overflow.
As I mentioned before it is working fine with IE10 and works even better with Chrome, so I don't think the problem here is the recursion. Is there any other way to get binary data into in canvas, than using an Image object and setting the src?
It is already noted as a bug in Firefox. You can see the bug report here. It is showing a last modified date of 2010-09-17 but I am not sure has it been resolved in newer version or what.
But I guess newer version of Firefox should not have that problem.
Related
I need some help understanding what the best practice is for creating a PIXI.extras.AnimatedSprite from spritesheet(s). I am currently loading 3 medium-sized spritesheets for 1 animation, created by TexturePacker, I collect all the frames and then play. However the first time playing the animation is very unsmooth, and almost jumps immediately to the end, from then on it plays really smooth. I have read a bit and I can see 2 possible causes. 1) The lag might be caused by the time taken to upload the textures to the GPU. There is a PIXI plugin called prepare renderer.plugins.prepare.upload which should enable me to upload them before playing and possibly smoothen out the initial loop. 2) Having an AnimatedSprite build from more than one texture/image is not ideal and could be the cause.
Question 1: Should I use the PIXI Prepare plugin, will this help, and if so how do I actually use it. Documentation for it is incredibly limited.
Question 2: Is having frames across multiple textures a bad idea, could it be the cause & why?
A summarised example of what I am doing:
function loadSpriteSheet(callback){
let loader = new PIXI.loaders.Loader()
loader.add('http://mysite.fake/sprite1.json')
loader.add('http://mysite.fake/sprite2.json')
loader.add('http://mysite.fake/sprite3.json')
loader.once('complete', callback)
loader.load()
}
loadSpriteSheet(function(resource){
// helper function to get all the frames from multiple textures
let frameArray = getFrameFromResource(resource)
let animSprite = new PIXI.extras.AnimatedSprite(frameArray)
stage.addChild(animSprite)
animSprite.play()
})
Question 1
So I have found a solution, possibly not the solution but it works well for me. The prepare plugin was the right solution but never worked. WebGL needs the entire texture(s) uploaded not the frames. The way textures are uploaded to the GPU is via renderer.bindTexture(texture). When the PIXI loader receives a sprite atlas url e.g. my_sprites.json it automatically downloads the image file and names it as mysprites.json_image in the loaders resources. So you need to grab that, make a texture and upload it to the GPU. So here is the updated code:
let loader = new PIXI.loaders.Loader()
loader.add('http://mysite.fake/sprite1.json')
loader.add('http://mysite.fake/sprite2.json')
loader.add('http://mysite.fake/sprite3.json')
loader.once('complete', callback)
loader.load()
function uploadToGPU(resourceName){
resourceName = resourceName + '_image'
let texture = new PIXI.Texture.fromImage(resourceName)
this.renderer.bindTexture(texture)
}
loadSpriteSheet(function(resource){
uploadToGPU('http://mysite.fake/sprite1.json')
uploadToGPU('http://mysite.fake/sprite2.json')
uploadToGPU('http://mysite.fake/sprite3.json')
// helper function to get all the frames from multiple textures
let frameArray = getFrameFromResource(resource)
let animSprite = new PIXI.extras.AnimatedSprite(frameArray)
this.stage.addChild(animSprite)
animSprite.play()
})
Question 2
I never really discovered and answer but the solution to Question 1 has made my animations perfectly smooth so in my case, I see no performance issues.
i am making a game based on draw images and clear it every some part of second.
i started with:
var peng = new Image();
and then:
peng.onload = function() {
context.drawImage(peng, pengXPosition, pengYPosition, pengWidth, pengHight);
};
and in the loop:
var i=0;
function pengMoveRight(){ i++;if(i==1){peng.src = 'images/1.png';}else if(i==2)
{peng.src = 'images/2.png';} else if(i==3){peng.src = 'images/3.png';}else if(i==4){
peng.src = 'images/4.png';}else if(i==5){peng.src = 'images/5.png';}else if(i==6){
peng.src = 'images/6.png';i-=6;}}
when i run it it works well on IE but on chrome and mozilla it`s too slow and the character is about to disappear .. i used setinterval(); once and window.requestAnimationFrame(); once and both of them cause the same problem.
what should i do to make it smooth move?
here is the full script http://mark-tec.com/custom%20game/
Instead of changing the source, try to create several Image objects instead. That way, the drawImage call can always use a pre-loaded image.
You need to preload all the images or use the sprite method (all images packed into a single sprite) in order to avoid the initial delay caused by the image loading only when it's needed.
However, after that initial problem, your example should run fine once all the images are cached.
I am using SmoothieCharts (http://smoothiecharts.org/tutorial.html) first time in one of my projects and have discovered huge memory consumption while running it in Chrome browser. Looking in TaskManager shows me, that there are about 300kB additionally consumed every second. After some amount of time the memory of this chrome task grows from around 50MB up to 1,3GB resulting in a freezing system.
The leak also occurs if no data is streamed to the chart and it just updates the grid lines. So maybe it's not about SmoothieCharts but Canvas implementation in Chrome?
Tests with IE(11) and current FireFox could not reproduce the problem.
Had anyone else such a problem in the past? I'm using Chrome 37.0.2062.103.
Looking at the timeline(chrome dev tools[f12]) for memory usage its points to the animation frame fired event as increase in memory.
SmoothieChart.prototype.start = function() {
if (this.frame) {
// We're already running, so just return
return;
}
// Renders a frame, and queues the next frame for later rendering
var animate = function() {
// the line below is where the leak is happening, I believe!!
this.frame = SmoothieChart.AnimateCompatibility.requestAnimationFrame(function() {
this.render();
animate();
}.bind(this));
}.bind(this);
animate();
};
Since downloading the current version of chrome (Version 31.0.1650.57) I've been completely unable to draw images in a HTML5 Canvas with my code; there are no errors and it's finding the resources, they just aren't drawing. I'd really appreciate some help on this!
var grass_img = new Image();
grass_img.src = 'grass.gif';
grass_img.onload = draw_here(grass_img, (center_x + base_x + xpos), (center_y + base_y + ypos),1);
Which appears here and there on several different images and calls:
function draw_here(image, x, y, scale){
draw_canv.drawImage(image, x, y, image.width * scale, image.height * scale);
}
X and Y are correct, as is the scale; there are no coding errors picked up by the debugger and the program worked perfectly until the latest version of chrome came out. Downgrading chrome is also not an option.
The problem is in this line:
grass_img.onload = draw_here( /* ... */ );
You seem to think that you assign the function draw_here as an onload-handler. But that's not what really happens in this line. What you really do is execute draw_here immediately and assign the return-value of that function (which is undefined) to grass_img.onload.
Try this instead:
grass_img.onload = function() {
draw_here(grass_img, (center_x + base_x + xpos), (center_y + base_y + ypos),1);
}
This creates an anonymous function which is assigned to the onload-handler. When that anonymous function is called (which will happen when the load-event is triggered) it calls your draw-handler with your arguments.
I solved the problem. It seems that the latest version of Chrome does not like it if you declare your image in every frame iteration. (Something it seems to have allowed previously, but I really shouldn't have been doing.) If you declare your images and their sources at the top of your js, outside of any functions, and only draw them in functions then the problem is solved, eg:
var image = new Image();
image.src='image.jpg';
someFunction() {
canvas.drawImage(image,0,0);
}
Note: .src should always be called AFTER .onload. Otherwise lots of hard-to-track-down buggies (like this one) appear. Especially if your image loads before onload can be parsed. Your currently accepted solution is possibly functional due to a race condition with function overhead timing.
I'm getting started with ProcessingJS and I'm currently playing with SVG a bit.
Unfortunately I've ran into a strange behaviour displaying SVG.
Here is the output:
and here is the code that produces that:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="http://cloud.github.com/downloads/processing-js/processing-js/processing-1.4.1.min.js"></script>
<script>
$(document).ready(function() {
$('body').append($('<canvas id="preview"><p>Your browser does not support the canvas tag.</p></canvas>'));
function onPJS(p) {
var glasses;
p.setup = function(){
glasses = p.loadShape("brighteyes.svg");
p.size(Math.floor(glasses.width), Math.floor(glasses.height)+Math.floor(glasses.height * .25));
//p.shape(glasses,0,0);
p.frameRate(1);
}
//*
p.draw = function() {
p.background(32);
p.shape(glasses, 0, 0);
console.log(p.mousePressed);//prints undefined
};
//*/
}
new Processing(document.getElementById("preview"), onPJS);
});
</script>
I'm experiencing this odd rendering (renderer seems to place a vertex at 0,0 for the shape)
on OSX 10.8 on Chrome Version 26.0.1410.65 (but not on Safari (6.0 (8536.25))). You can run the code here.
How do I get read of these weird rendering bug ?
There is another unexpected thing happening: mousePressed prints undefined, but might address that in a different question.
Processing's support for SVG is patchy. You should probably just report the bug at https://github.com/processing-js/processing-js/issues/new, and then use a PNG copy instead.
NB: renders OK on Firefox 35.
Edit: reported for you. https://github.com/processing-js/processing-js/issues/137
GoToLoop at the above link says that your problem with mousepressed is caused by the fact that to avoid name collisions in JS, the boolean mousepressed is called __mousePressed in JS. They recommend that you use Java syntax to code your app and have it automatically translated into JS, to avoid these gotchas.
Result: just update Chrome, which you've probably done anyway now.