Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to control png chunks generation? #1627

Open
mastrodaro opened this issue Jul 22, 2020 · 7 comments
Open

How to control png chunks generation? #1627

mastrodaro opened this issue Jul 22, 2020 · 7 comments

Comments

@mastrodaro
Copy link

Hello,

I have created png using canvas.createPNGStream(). Passed palette for indexed png. As a result I get chunks: IHDR, PLTE, tRNS, bKGD, IDAT. I dont want tRNS and bKGD, but instead I would like to set pHYs. How can I control over what chunks will be generated?

@zbjornson
Copy link
Collaborator

There's no way to control that from node-canvas. Your best bet would be to use canvas.toBuffer("raw") to get raw pixel data, and then use as separate PNG encoder. (I'm not aware of any Node.js encoders that provide control over chunks, however.) Alternatively you could modify just those header chunks in node-canvas's output fairly easily with vanilla JS.

@mastrodaro
Copy link
Author

Thanks for your answer.
I was looking for any encoders but they dont seem to be so far advanced. I think the things is I am forced to create palette with colors including alpha byte data, usually color table should be dividable by 3, here it has to be 4. I believe this is adding tRNS chunk.

When use canvas.toBuffer("raw") on indexed image will I get IDAT part before it getting deflated?

@zbjornson
Copy link
Collaborator

The PNG encoder code starts here if you want to take a look:

https://github.com/Automattic/node-canvas/blob/master/src/PNG.h#L96

and the indexed image code is here:

https://github.com/Automattic/node-canvas/blob/master/src/PNG.h#L216

The palette is expected to be an array of RGBA and it does write tRNS, yeah.

Without changing the Canvas API we could support {pixelFormat: "A8", alpha: false} to indicate that no tRNS chunk should be written (TBD if the palette argument should then be RGBx or RGB, i.e. if it should remain padded to 4 bytes per color or not), and createPNGStream({palette, backgroundIndex: null}) to mean no bKGD chunk. (That would have been a better default than backgroundIndex: 0, my bad.)

I'm low on time to make any of these changes anytime soon, but can review PRs for them.

When use canvas.toBuffer("raw") on indexed image will I get IDAT part before it getting deflated?

This would just be raw palette indices without encoding. If you add the chunk header and crc, that's basically IDAT.

@mastrodaro
Copy link
Author

Thanks for being responsive. Unfortunatelly, using alpha: false completly removes PLTE (png is not indexed anymore) nor setting null as backgroundIndex changes anything.
I have checked the C code (but well its been like 12 years when I touched C last time :)) and I could not find definition of png_set_bKGD as this is invoked with null then:
https://github.com/Automattic/node-canvas/blob/master/src/PNG.h#L235

The same goes to png_set_tRNS which is invoked no matter of args and I cannot check the definition but still, we are bound to set 4th color at palette definition. (https://github.com/Automattic/node-canvas/blob/master/lib/pngstream.js#L21)

On the other hand I could just manually create byte stream and write to it just as I reached so far I could make this project even better, since its so close to what I need exactly. Is there any instruction how to run this C+js code for dev?

@zbjornson
Copy link
Collaborator

using alpha: false completly removes PLTE (png is not indexed anymore) nor setting null as backgroundIndex changes anything.

Ah I was proposing new behaviors, not describing the current behavior, sorry.

I could not find definition of png_set_bKGD

Sourceforge is down right now, but that's a libpng function that I think is documented here: http://www.libpng.org/pub/png/pngdocs.html

Is there any instruction how to run this C+js code for dev?

To build it from source? You need to install the dependencies (see https://github.com/Automattic/node-canvas/wiki), and then you can build it with node-gyp configure and then node-gyp build. (https://github.com/nodejs/node-gyp#how-to-use)

@mastrodaro
Copy link
Author

mastrodaro commented Jul 23, 2020

Ok thanks, so I will try to prepare PR on the weekend. As I see all we need is to conditionally run some png_set_* functions. It seems to be PNG12 library and let to specify palette dividable by 3 as well with ignoring of transparency allocation and invocation of png_set_tRNS.
Seems easy, just dont want to randomly break anything.

@mastrodaro
Copy link
Author

I have created PR. #1629 Added control over tRNS.

I need good review. I have noticed if you pass an index ouf of palette defined indexes it will not generate bKGD. I tried to make use of backgroundIndex: null but it gets converted to 0 in C code (uint).

Also there is tricky code that makes {pixelFormat: "A8", alpha: false} use regular RGB and forget indexing, I decided to leave it as is and add alpha parameter to stream generation where alpha (defaults to true) will force you to generate valid palette.

We can switch discussion to PR and close this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants