Automattic/node-canvas

Inaccurate RGB values due to a rounding error caused by premultiplication

開放

#1,933 建立於 2021年11月19日

 (0 則留言) (1 個反應) (0 位負責人)JavaScript (1,195 個分叉)batch import
BugGood first issue

倉庫指標

星標
 (10,689 顆星)
PR 合併指標
 (PR 指標待抓取)

描述

Issue or Feature

When dealing with specific RGBA values, there's a chance that the RGB values will be incorrect. For example, with the RGBA values (252, 252, 252, 252), the RGB values are expected to be (252, 252, 252), but in practice, they're rounded down to (251, 251, 251) (with the alpha value remaining the same).

The root of the issue is somewhere within this area: https://github.com/Automattic/node-canvas/blob/198080580a0e3938c48daae357b88a1638a9ddcd/src/CanvasRenderingContext2d.cc#L1067 (Although I do not know where the premultiplication is done.)

Steps to Reproduce

const { createCanvas, createImageData } = require('canvas');

var canvas = createCanvas(1, 1);
var context = canvas.getContext('2d');

var data = createImageData(Uint8ClampedArray.from([252, 252, 252, 252]), 1);
context.putImageData(data, 0, 0);

var newData = context.getImageData(0, 0, 1, 1);
console.log(newData.data);
// expected to be Uint8ClampedArray[252, 252, 252, 252]

Minireprex of the issue in C++:

#include <cstdint>
#include <assert.h>

int main()
{
    uint32_t rgba = 4227858432u;
    uint8_t a = rgba >> 24;
    
    // premultiplied value: 252 * (252 / 255)
    float r = 249.03529411764708f;
    
    float alphaR = (float)255 / a;
    uint8_t undone = (int)((float)r * alphaR);
    
    assert(undone == 252);
    
    return 0;
}

Your Environment

  • Version of node-canvas (output of npm list canvas or yarn list canvas): `-- canvas@2.6.1
  • Environment (e.g. node 4.2.0 on Mac OS X 10.8): node v15.2.1 on Windows 10 Home v1909 (build 18363.1198)

貢獻者指南