0

I tried to draw gradient on canvas, however, when I want to make the gradient to slope differently in many progress, the filled pixel value on canvas appears to be out of expect on Chrome.

Below is a code that can reproduce the issue. Or you can try it on jsfiddle.

var canvas = document.getElementById('test');
var ctx = canvas.getContext('2d');

var grd = ctx.createLinearGradient(0, 200, canvas.width, 200);

/*  The real logic is like below
var start = 0, end = 255;
var i, steps = 10
var val, ratio, gamma = 0.75;
for (i = 0; i <= steps; ++i) {
    ratio = i / steps;
    val = ratio * end + (1 - ratio) * start;
    val = val / 255;
    val = Math.round(255 * Math.pow(val, gamma));
    grd.addColorStop(ratio, 'rgb(' + val + ', ' + val + ', ' + val + ')');
    console.log('colorStop:', ratio,  'rgb(' + val + ', ' + val + ', ' + val + ')');
}
*/

// Simple color steps./
grd.addColorStop(0, 'rgb(0, 0, 0)');
grd.addColorStop(0.5, 'rgb(112, 112, 112)');
grd.addColorStop(1, 'rgb(255, 255, 255)');


ctx.fillStyle = grd;
ctx.fillRect(0, 0, canvas.width, canvas.height);

// For check value.
canvas.addEventListener('click', function() {
    var width = canvas.width;
    var imageData = ctx.getImageData(0, 0, width, 1);
    var pVal;   
    for (var x = 0; x < width; ++x) {
        pVal = imageData.data[x * 4];
        console.log(pVal);
    }
});
<canvas id="test" width="1024" height="400"></canvas>

When I click on the canvas, I expect the console will output a sequence of non-descending number like:

0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, .....

But the console output is :

0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 1, 2, 2, ....

which will step back on some pixels.

Currently I have to get imageData and put the correct value by each pixel's position, but its much slower than fill the gradient.

It seems only happen on Chrome, I've test the code above on IE and firefox, works fine. But for some reason, I can't switch to other browser.

Is there any method to make Chrome act like other browsers? Or is there's any other method that can achieve the same effect while faster than compute for each pixel's value.

Chrome version is : 44.0.2403.107 m (64-bit) with canvas GPU Status: Software only, hardware acceleration unavailable.

The working environment : 28.0.1500.95, with NO GPU.

fuyushimoya
  • 9,715
  • 3
  • 27
  • 34
  • I would say rounding and anti-aliasing. On my machine, Chrome performs [this test](http://jsfiddle.net/8j59b70k/1/) better than FF which breaks at `pVal[128]`. – Kaiido Jul 29 '15 at 05:27
  • I think that you simply can't rely on `ctx.getImageData()` to return any strict value, see [this other question](http://stackoverflow.com/questions/4309364/). Further to read an also prone to differences `linearGradient()` – Kaiido Jul 29 '15 at 05:30
  • As I'm using the color with `alpha=1` I believe the value in `ctx.getImageData()` is Ok, because I met the premultiply fact at other part and solved them, anyway, thanks for the notice. – fuyushimoya Jul 29 '15 at 06:39
  • rounding is still relevant I checked this [fiddle](http://jsfiddle.net/8j59b70k/2/) with different browsers and almost every one gives me different results – Kaiido Jul 29 '15 at 07:11

0 Answers0