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

Base64 encode png buffer #47

Closed
wulfgarpro opened this issue Jul 4, 2017 · 5 comments
Closed

Base64 encode png buffer #47

wulfgarpro opened this issue Jul 4, 2017 · 5 comments

Comments

@wulfgarpro
Copy link

wulfgarpro commented Jul 4, 2017

I'd like to:

  • Open a png image
  • Merge this png with an overlay png
  • Encode the merged result buffer as a base64 string

My test code:

gd.openPng('./my_image.png', function(err, img) {
    img.saveAlpha(1);
    gd.openPng('./my_overlay.png', function(err, overlay) {
	overlay.copy(img, 0, 0, 0, 0, overlay.width, overlay.height);

	let buff = gd.createFromPngPtr(new Buffer(img.pngPtr())); /* this returns null? */
        console.log(buff); /* prints null as per previous line */

        let b64 = buff.toString('base64'); /* error: Cannot read property 'toString' of null */
        console.log(b64);        
    });
});

Why am I getting a null return on the gd.createFromPngPtr call?

Playing around with the examples in the documentation, the following snippet core dumps:

gd.openPng('./my_image.png', function(err, img) {
    let x = img.pngPtr(9);
    let y = gd.createFromPngPtr(x); // core dump
});

With node v6:
$ nvm list
-> v6.11.0

../src/string_bytes.cc:273:static size_t node::StringBytes::Write(v8::Isolate*, char*, size_t, v8::Localv8::Value, node::encoding, int*): Assertion `val->IsString() == true' failed.

With node v8:
$ nvm list
v6.11.0
-> v8.1.0

../src/string_bytes.cc:273:static size_t node::StringBytes::Write(v8::Isolate*, char*, size_t, v8::Localv8::Value, node::encoding, int*): Assertion `val->IsString() == true' failed.

During both runs, I'm using native libgd-dev v 2.2.101ubuntu3.3:
$ apt search libgd-dev
Sorting... Done
Full Text Search... Done
libgd-dev/yakkety-updates,yakkety-security,now 2.2.1-1ubuntu3.3 amd64 [installed]
GD Graphics Library (development version)

@y-a-v-a
Copy link
Owner

y-a-v-a commented Jul 4, 2017

Hi,
First of all, thanks for reaching out! Second: your example code looks like it has an error, afaics:

gd.openPng('./my_image.png', function(err, overlay) {
    let x = img.pngPtr(9); // what is "img" here? shouldn't it be "overlay"?
    let y = gd.createFromPngPtr(x); // core dump
});

Also, the core dump comes probably from the fact that you're feeding img.pngPtr with a Number instead of a String or Buffer.

gd.openPng('./my_image.png', function(err, overlay) {
    let x = img.pngPtr(9); // 9 is a Number
    let y = gd.createFromPngPtr(x); // core dump
});

@y-a-v-a
Copy link
Owner

y-a-v-a commented Jul 4, 2017

Hi,
Sorry for my last comment, the number of course represents the quality.

Next to that, what you're actually trying to do in the first code block of your comment is to get a base64 representation of a node-gd gd-object, which will fail since it's not a String. Let me explain in the code:

gd.openPng('./my_image.png', function(err, img) {
    img.saveAlpha(1);
    gd.openPng('./my_overlay.png', function(err, overlay) {
	overlay.copy(img, 0, 0, 0, 0, overlay.width, overlay.height);

        // "buff" is not a buffer here, but a gd#Image object, because you're creating one based on a buffer!
	let buff = gd.createFromPngPtr(new Buffer(img.pngPtr())); /* this returns null? */
        console.log(buff); /* prints null as per previous line */

        let b64 = buff.toString('base64'); /* error: Cannot read property 'toString' of null */
        console.log(b64);        
    });
});

The solution is simpler than you might think:

gd.openPng('./my_image.png', function(err, img) {
    img.saveAlpha(1);
    gd.openPng('./my_overlay.png', function(err, overlay) {
	overlay.copy(img, 0, 0, 0, 0, overlay.width, overlay.height);

        // create a binary buffer from the data you get from the pointer
	let buff = Buffer.from(img.pngPtr(), 'latin1');
        // and then output it to a base64 string.
        let b64 = buff.toString('base64');
        console.log(b64);        
    });
});

See also https://nodejs.org/dist/latest-v6.x/docs/api/buffer.html#buffer_class_method_buffer_from_string_encoding

@wulfgarpro
Copy link
Author

@y-a-v-a, thanks for the prompt reply.

Second: your example code looks like it has an error, afaics:

Fixed (late night copy paste error).

The solution is simpler than you might think:

Less the latin1 argument (the key to the solution!), the default utf8 encoded buffer results in an invalid base64 string (this is the original reason why I started making changes); I'm not sure why?

Actually, I've taken the latin1 argument away in your example and replaced it with binary and it's still working; thank you.

@y-a-v-a
Copy link
Owner

y-a-v-a commented Jul 6, 2017

Actually, I've taken the latin1 argument away in your example and replaced it with binary and it's still working; thank you.

True, since the documentation of nodejs (see https://nodejs.org/dist/latest-v6.x/docs/api/buffer.html#buffer_buffers_and_character_encodings ) says:

'binary' - Alias for 'latin1'.

@wulfgarpro
Copy link
Author

wulfgarpro commented Jul 9, 2017

Why does latin1 work?

Why am I required to encode the pngPtr() as latin1 in order for the base64 encoded string to be correct?

As an example:

Playing with Buffer and a png file, I can successfully encode the buffer as the default UTF-8 and the base64 encoded string is valid.

let img = fs.readFileSync('img.png');
let buff = Buffer.from(img); //, 'utf-8');
let b64 = buff.toString('base64');
console.log(b64); // this is correct

But as we've touched on above, this isn't the case for the pngPtr().

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