UNPKG

9.38 kBMarkdownView Raw
1![build](https://github.com/pngjs/pngjs/actions/workflows/ci.yml/badge.svg?branch=main) [![codecov](https://codecov.io/gh/pngjs/pngjs/branch/master/graph/badge.svg)](https://codecov.io/gh/pngjs/pngjs) [![npm version](https://badge.fury.io/js/pngjs.svg)](http://badge.fury.io/js/pngjs)
2
3# pngjs
4
5Simple PNG encoder/decoder for Node.js with no dependencies.
6
7Based on the original [pngjs](https://github.com/niegowski/node-pngjs) with the follow enhancements.
8
9- Support for reading 1,2,4 & 16 bit files
10- Support for reading interlace files
11- Support for reading `tTRNS` transparent colours
12- Support for writing colortype 0 (grayscale), colortype 2 (RGB), colortype 4 (grayscale alpha) and colortype 6 (RGBA)
13- Sync interface as well as async
14- API compatible with pngjs and node-pngjs
15
16Known lack of support for:
17
18- Extended PNG e.g. Animation
19- Writing in colortype 3 (indexed color)
20
21# Table of Contents
22
23- [Requirements](#requirements)
24- [Comparison Table](#comparison-table)
25- [Tests](#tests)
26- [Installation](#installation)
27- [Browser](#browser)
28- [Example](#example)
29- [Async API](#async-api)
30- [Sync API](#sync-api)
31- [Changelog](#changelog)
32
33# Comparison Table
34
35| Name | Forked From | Sync | Async | 16 Bit | 1/2/4 Bit | Interlace | Gamma | Encodes | Tested |
36| ------------- | ----------- | ---- | ----- | ------ | --------- | --------- | ------ | ------- | ------ |
37| pngjs | | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
38| node-png | pngjs | No | Yes | No | No | No | Hidden | Yes | Manual |
39| png-coder | pngjs | No | Yes | Yes | No | No | Hidden | Yes | Manual |
40| pngparse | | No | Yes | No | Yes | No | No | No | Yes |
41| pngparse-sync | pngparse | Yes | No | No | Yes | No | No | No | Yes |
42| png-async | | No | Yes | No | No | No | No | Yes | Yes |
43| png-js | | No | Yes | No | No | No | No | No | No |
44
45Native C++ node decoders:
46
47- png
48- png-sync (sync version of above)
49- pixel-png
50- png-img
51
52# Tests
53
54Tested using [PNG Suite](http://www.schaik.com/pngsuite/). We read every file into pngjs, output it in standard 8bit colour, synchronously and asynchronously, then compare the original with the newly saved images.
55
56To run the tests, fetch the repo (tests are not distributed via npm) and install with `npm i`, run `npm test`.
57
58The only thing not converted is gamma correction - this is because multiple vendors will do gamma correction differently, so the tests will have different results on different browsers.
59
60# Installation
61
62```
63$ npm install pngjs --save
64```
65
66# Browser
67
68The package has been build with a [Browserify](browserify.org) version (`npm run browserify`) and you can use the browser version by including in your code:
69
70```
71import { PNG } from 'pngjs/browser';
72```
73
74# Example
75
76```js
77var fs = require("fs"),
78 PNG = require("pngjs").PNG;
79
80fs.createReadStream("in.png")
81 .pipe(
82 new PNG({
83 filterType: 4,
84 })
85 )
86 .on("parsed", function () {
87 for (var y = 0; y < this.height; y++) {
88 for (var x = 0; x < this.width; x++) {
89 var idx = (this.width * y + x) << 2;
90
91 // invert color
92 this.data[idx] = 255 - this.data[idx];
93 this.data[idx + 1] = 255 - this.data[idx + 1];
94 this.data[idx + 2] = 255 - this.data[idx + 2];
95
96 // and reduce opacity
97 this.data[idx + 3] = this.data[idx + 3] >> 1;
98 }
99 }
100
101 this.pack().pipe(fs.createWriteStream("out.png"));
102 });
103```
104
105For more examples see `examples` folder.
106
107# Async API
108
109As input any color type is accepted (grayscale, rgb, palette, grayscale with alpha, rgb with alpha) but 8 bit per sample (channel) is the only supported bit depth. Interlaced mode is not supported.
110
111## Class: PNG
112
113`PNG` is readable and writable `Stream`.
114
115### Options
116
117- `width` - use this with `height` if you want to create png from scratch
118- `height` - as above
119- `checkCRC` - whether parser should be strict about checksums in source stream (default: `true`)
120- `deflateChunkSize` - chunk size used for deflating data chunks, this should be power of 2 and must not be less than 256 and more than 32\*1024 (default: 32 kB)
121- `deflateLevel` - compression level for deflate (default: 9)
122- `deflateStrategy` - compression strategy for deflate (default: 3)
123- `deflateFactory` - deflate stream factory (default: `zlib.createDeflate`)
124- `filterType` - png filtering method for scanlines (default: -1 => auto, accepts array of numbers 0-4)
125- `colorType` - the output colorType - see constants. 0 = grayscale, no alpha, 2 = color, no alpha, 4 = grayscale & alpha, 6 = color & alpha. Default currently 6, but in the future may calculate best mode.
126- `inputColorType` - the input colorType - see constants. Default is 6 (RGBA)
127- `bitDepth` - the bitDepth of the output, 8 or 16 bits. Input data is expected to have this bit depth.
128 16 bit data is expected in the system endianness (Default: 8)
129- `inputHasAlpha` - whether the input bitmap has 4 bytes per pixel (rgb and alpha) or 3 (rgb - no alpha).
130- `bgColor` - an object containing red, green, and blue values between 0 and 255
131 that is used when packing a PNG if alpha is not to be included (default: 255,255,255)
132
133### Event "metadata"
134
135`function(metadata) { }`
136Image's header has been parsed, metadata contains this information:
137
138- `width` image size in pixels
139- `height` image size in pixels
140- `palette` image is paletted
141- `color` image is not grayscale
142- `alpha` image contains alpha channel
143- `interlace` image is interlaced
144
145### Event: "parsed"
146
147`function(data) { }`
148Input image has been completely parsed, `data` is complete and ready for modification.
149
150### Event: "error"
151
152`function(error) { }`
153
154### png.parse(data, [callback])
155
156Parses PNG file data. Can be `String` or `Buffer`. Alternatively you can stream data to instance of PNG.
157
158Optional `callback` is once called on `error` or `parsed`. The callback gets
159two arguments `(err, data)`.
160
161Returns `this` for method chaining.
162
163#### Example
164
165```js
166new PNG({ filterType: 4 }).parse(imageData, function (error, data) {
167 console.log(error, data);
168});
169```
170
171### png.pack()
172
173Starts converting data to PNG file Stream.
174
175Returns `this` for method chaining.
176
177### png.bitblt(dst, sx, sy, w, h, dx, dy)
178
179Helper for image manipulation, copies a rectangle of pixels from current (i.e. the source) image (`sx`, `sy`, `w`, `h`) to `dst` image (at `dx`, `dy`).
180
181Returns `this` for method chaining.
182
183For example, the following code copies the top-left 100x50 px of `in.png` into dst and writes it to `out.png`:
184
185```js
186var dst = new PNG({ width: 100, height: 50 });
187fs.createReadStream("in.png")
188 .pipe(new PNG())
189 .on("parsed", function () {
190 this.bitblt(dst, 0, 0, 100, 50, 0, 0);
191 dst.pack().pipe(fs.createWriteStream("out.png"));
192 });
193```
194
195### Property: adjustGamma()
196
197Helper that takes data and adjusts it to be gamma corrected. Note that it is not 100% reliable with transparent colours because that requires knowing the background colour the bitmap is rendered on to.
198
199In tests against PNG suite it compared 100% with chrome on all 8 bit and below images. On IE there were some differences.
200
201The following example reads a file, adjusts the gamma (which sets the gamma to 0) and writes it out again, effectively removing any gamma correction from the image.
202
203```js
204fs.createReadStream("in.png")
205 .pipe(new PNG())
206 .on("parsed", function () {
207 this.adjustGamma();
208 this.pack().pipe(fs.createWriteStream("out.png"));
209 });
210```
211
212### Property: width
213
214Width of image in pixels
215
216### Property: height
217
218Height of image in pixels
219
220### Property: data
221
222Buffer of image pixel data. Every pixel consists 4 bytes: R, G, B, A (opacity).
223
224### Property: gamma
225
226Gamma of image (0 if not specified)
227
228## Packing a PNG and removing alpha (RGBA to RGB)
229
230When removing the alpha channel from an image, there needs to be a background color to correctly
231convert each pixel's transparency to the appropriate RGB value. By default, pngjs will flatten
232the image against a white background. You can override this in the options:
233
234```js
235var fs = require("fs"),
236 PNG = require("pngjs").PNG;
237
238fs.createReadStream("in.png")
239 .pipe(
240 new PNG({
241 colorType: 2,
242 bgColor: {
243 red: 0,
244 green: 255,
245 blue: 0,
246 },
247 })
248 )
249 .on("parsed", function () {
250 this.pack().pipe(fs.createWriteStream("out.png"));
251 });
252```
253
254# Sync API
255
256## PNG.sync
257
258### PNG.sync.read(buffer)
259
260Take a buffer and returns a PNG image. The properties on the image include the meta data and `data` as per the async API above.
261
262```
263var data = fs.readFileSync('in.png');
264var png = PNG.sync.read(data);
265```
266
267### PNG.sync.write(png)
268
269Take a PNG image and returns a buffer. The properties on the image include the meta data and `data` as per the async API above.
270
271```
272var data = fs.readFileSync('in.png');
273var png = PNG.sync.read(data);
274var options = { colorType: 6 };
275var buffer = PNG.sync.write(png, options);
276fs.writeFileSync('out.png', buffer);
277```
278
279### PNG.adjustGamma(src)
280
281Adjusts the gamma of a sync image. See the async adjustGamma.
282
283```
284var data = fs.readFileSync('in.png');
285var png = PNG.sync.read(data);
286PNG.adjustGamma(png);
287```