0

I'm trying to generate a .png image from a hexadecimal color string (#RRGGBB), without using modules like pngjs or jimp.

The hex string looks like this:

let colors = "ff000000ff000000ffff00ff00ffffffff00";

According to this article, all png files must start with the signature b'\x89PNG\r\n\x1a\n' and have 3 "chunks" (IHDR, IDAT and IEND), each with the following structure:

enter image description here (Data Length, Chunk Type, Chunk Data and CRC)

And according to png specs, it is compressed with zlib's deflate, so I came up with this code:

const fs = require("fs");
const zlib = require("zlib");

let colors = "ff000000ff000000ffff00ff00ffffffff00";
let data = `b'\x89PNG\r\n\x1a\n'0d00IHDR030002008200000002400IDAT${colors}0000IEND`;

zlib.deflateRaw(data, (err, buffer) => {
    fs.writeFile("output.png", buffer, (err)=>{if (err) throw err;});
});

For better readability, the split data looks like this:

b'\x89PNG\r\n\x1a\n' // signature
0d00 // chunk data length (13)
IHDR // chunk type

/* chunk data */
0300 // image width (3)
0200 // image height (2)
8 // bit depth (8)
2 // color type (2)
0 // compression method (0)
0 // filter method (0)
0 // interlace method (0)
0000 // CRC (?)

2400 // chunk data length (36)
IDAT // chunk type
ff000000ff000000ffff00ff00ffffffff00 // chunk data (#RRGGBB)
0000 // CRC (?)
IEND

What I expected to get as a result was the image below (in its 3x2 size), but all I have is a seemingly invalid png file that my image viewer doesn't support.

image with 6 pixels of different colors

Is it really possible to write a valid png file this way? If so, how?

Luna
  • 27
  • 5
  • So much wrong, I wouldn't even know where to begin. I recommend that you start with a valid, small PNG file, and figure out how to interpret it byte by byte. Instead of trying to make one. Once you see how it's put together, then try to make one yourself. – Mark Adler Dec 26 '21 at 19:18
  • @MarkAdler well, I have provided all the steps I took to reach that conclusion, if you could point me out at least the biggest mistake I made, it would be helpful. – Luna Dec 27 '21 at 00:09
  • Far and away the biggest mistake would not be spending enough time with the PNG specification, and spending time picking apart valid PNG files (the article you link is a good start), before leaping off and trying to make your own PNG file making random guesses. You will not be able to incrementally approach a valid PNG file by trying to correct your mistakes, since there is no path from here to there. Delete what you have done and start over. – Mark Adler Dec 27 '21 at 01:31
  • Alright, but do you think what I'm trying to do is a valid approach? I mean, does just converting the values ​​to hexadecimal, concatenating them into a string, encoding it, and writing it to a file with a .png extension make sense? My problem with that article (apart from being about decoding, not encoding) and a few others I've read so far is that none of them deal with this specific case of nodejs with just the fs and zlib modules. – Luna Dec 27 '21 at 01:52
  • No, that does not make any sense at all. The format is binary. Nothing is encoded in hexadecimal. – Mark Adler Dec 27 '21 at 03:23
  • I was assuming everything is converted to hexadecimal before it is encoded with deflate, if that's wrong I wonder what deflate takes as input? – Luna Dec 27 '21 at 11:32
  • Read the [PNG specification](https://www.w3.org/TR/2003/REC-PNG-20031110/). It's all there. – Mark Adler Dec 27 '21 at 20:16
  • I've read and reread the specs, unfortunately it's (obviously) not made for lay people like me so I'm kind of on a dead end here. Thanks for the tips anyway. – Luna Dec 28 '21 at 00:19
  • @MarkAdler Sorry to bother you, but I believe you are quite literate on the inner workings of png files. So could you help me with my [question](https://stackoverflow.com/questions/70463148/need-help-understanding-idat-header-in-png-image-file). It has been unanswered for more than a week. – Vasu Deo.S Dec 29 '21 at 04:02

1 Answers1

1

Those pixels in a PNG (you will need to dramatically embiggen in order to see the six pixels):

2x3 colors

Hex dump:

89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52
00 00 00 03 00 00 00 02 08 02 00 00 00 12 16 f1
4d 00 00 00 17 49 44 41 54 08 99 63 f8 cf c0 c0
f0 9f 81 81 e1 3f 0b 94 fe cf 08 00 39 04 06 00
83 e9 a9 e3 00 00 00 00 49 45 4e 44 ae 42 60 82
Mark Adler
  • 101,978
  • 13
  • 118
  • 158