3

I have the script that works with pixels in html5 canvas element. And there is some strange behavior by Google Chrome (version: 17.0.942.0 dev). I have 2 kind of operations with pixels:

  • changing the hue of pixels inside particular polygone
  • pixel selection by wand tool

The problem is when I'm changing the hue, the memory of that tab grows after every change up to 250MB (sometimes even more) and than being reseted to the initial size. But when I'm using wand tool selection, the memory doesn't grow, it goes up or down depending how many pixels are selected (this is normal behavior in my opinion). Please help me to understand why memory grows after every change in first case.

P.S. in FF there is no issue like that, that's why I think that this is Chrome-specific "strange" behavior

Here is the code of hue change:

function isPointInPoly(poly, pt){
    for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
        ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y))
        && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x)
        && (c = !c);
    return c;
}

function changeHue(hue){
    var modifyCanvas = $("#canvas-modify").get(0);
    var modifyContext = modifyCanvas.getContext('2d');
    modifyContext.clearRect(0, 0, modifyCanvas.width, modifyCanvas.height);
    var imageData = $$.mainCanvasContext.getImageData(0, 0, $$.mainCanvasElem.width, $$.mainCanvasElem.height);
    for(var i=0;i<imageData.data.length;i+=4) {
        var p = {x: (i/4)%imageData.width, y: parseInt((i/4)/imageData.width)};
        for(var j=0;j<$$.globalSelection.length;j++){
            var poly = $$.globalSelection[j].slice(0, $$.globalSelection[j].length-1);
            if(isPointInPoly(poly, p)) {
                var hsl = rgbToHsl(imageData.data[i], imageData.data[i+1], imageData.data[i+2]);
                hsl[0] = hue;
                var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
                imageData.data[i]   = rgb[0];
                imageData.data[i+1] = rgb[1];
                imageData.data[i+2] = rgb[2];
            } else {
                imageData.data[i]   = 0;
                imageData.data[i+1] = 0;
                imageData.data[i+2] = 0;
                imageData.data[i+3] = 0;
            }
        }
    }
    modifyContext.putImageData(imageData, 0, 0);
}
haynar
  • 5,961
  • 7
  • 33
  • 53
  • Did you take a look here ? http://ajaxian.com/archives/canvas-image-data-optimization-tip (found in first related question http://stackoverflow.com/questions/2573212/why-is-setting-html5s-canvaspixelarray-values-ridiculously-slow-and-how-can-i-d) – soju Nov 24 '11 at 14:17

1 Answers1

3

It's not just you.

There have been off and on memory leaks in Chrome with anything canvas imageData related.

For instance:

http://code.google.com/p/chromium/issues/detail?id=51171

http://code.google.com/p/chromium/issues/detail?id=20067

etc.

Chromium's issue tracker policies are weird. The issues aren't necessarily fixed even though they close them.

It's possible its a webkit thing and not a Chrome thing but I can't say for certain. All I can say is that you yourself aren't doing anything wrong.

Though while we're here let me say that you should not be doing this:

var modifyCanvas = $("#canvas-modify").get(0);
var modifyContext = modifyCanvas.getContext('2d');

Every time, for performance's sake. Especially if this operation happens often.

Simon Sarris
  • 62,212
  • 13
  • 141
  • 171
  • thanks for your remark, I'll fix that... and I hope that this kind of issues will be fixed sooner by chromium if this is not my fault... – haynar Nov 24 '11 at 21:21