joshmarinacci / node-pureimage

Pure JS implementation of the HTML Canvas 2D drawing API

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

transforms not taking effect for fillRect and drawImage?

jkozak opened this issue · comments

Expected Behaviour

The code below, run with the commented line enabled and then disabled
should produce two files that differ.

Actual Behaviour

The files produced are identical.

Steps To Reproduce

  1. run code below, copy output file to out1.png

  2. comment out commented line, rerun

  3. compare out.png and out1.png

Any Relevant Code Snippets

"use strict";

const PImage = require("pureimage");
const fs = require('fs');

const img1 = PImage.make(100, 100)
const ctx = img1.getContext('2d');

ctx.scale(0.5,1.0);  // !!! comment this out and rerun !!!

ctx.fillStyle = 'red';
ctx.fillRect(0,0,50,50);

PImage.encodePNGToStream(img1, fs.createWriteStream('out.png')).then(() => {
    console.log("wrote out the png file to out.png");
}).catch((e)=>{
    console.log("there was an error writing");
});

Platform

OS: NixOS 22.11
Node Version: v18.12.1
NPM Version: 8.9.12
PureImage Version: 0.3.14

Any Additional Info

I observe similar problems with context.drawImage.

Can you confirm this is happening with the current version from master? I just created a test from your code and was able to see the rectangle be resized. Note that the background is transparent, so a 50x50 red rect will look similar to a 100x100 red rect.

Still happening using commit 355ea2b.

The files produced on the two runs are identical:

[nix-shell:/tmp/flatland]$ sha1sum out*
e97ee940bf787779a67b0734ebc43a840fc3c842  out0.png
e97ee940bf787779a67b0734ebc43a840fc3c842  out.png

Worried that I was doing something stupid, I rewrote the test code to write out both cases:

"use strict";

const PImage = require("pureimage");
const fs = require('fs');

function drawRect(doScale,fn) {
    const img1 = PImage.make(100, 100)
    const ctx = img1.getContext('2d');

    if (doScale)
        ctx.scale(0.5,1.0);

    ctx.fillStyle = 'red';
    ctx.fillRect(0,0,50,50);

    PImage.encodePNGToStream(img1, fs.createWriteStream(fn)).then(() => {
        console.log(`wrote out the png file to ${fn}`);
    }).catch(e=>{
        console.log(`there was an error writing: ${e}`);
    });
}

drawRect(false,"out-f.png");
drawRect(true, "out-t.png");

same results.

Okay. I see now. The fillRect method directly sets pixels. It doesn't use the transforms. Really it should just create a rect path and fill it, but that breaks other things. Researching.

doing fillRect() as a path isn't filling the exact same pixels as the plain for loop. I've made a few tweaks to improve it but it still isn't perfect. For now I'm using to use the forLoop path if the current transform is the identity transform. If it's not then it takes the path root. This should fix the bug.

I just released 0.3.16. Can you test that this fixes the transforms for you?

Happy to confirm that this fixes the issue my test code illustrates.