prettier, es6, upgrades

This commit is contained in:
Luke Page 2020-04-09 20:28:27 +02:00
parent 31bedc7bb0
commit 32271b56e3
43 changed files with 3781 additions and 2020 deletions

2
.eslintignore Normal file
View file

@ -0,0 +1,2 @@
/browser.js
/test/imagediff.js

View file

@ -1,182 +1,19 @@
{ {
"rules": { "parserOptions": { "ecmaVersion": 2018 },
"no-alert": "error", "extends": ["eslint:recommended", "prettier"],
"no-array-constructor": "off", "env": {
"no-bitwise": "off", "node": true,
"no-caller": "error", "es6": true
"no-catch-shadow": "error", },
"no-class-assign": "error", "rules": {
"no-cond-assign": "error", "no-var": "error"
"no-console": "error", },
"no-const-assign": "error", "overrides": [
"no-constant-condition": "error", {
"no-continue": "off", "files": ["test/*.js", "examples/*.js"],
"no-control-regex": "error", "rules": {
"no-debugger": "error", "no-console": "off"
"no-delete-var": "error", }
"no-div-regex": "off",
"no-dupe-keys": "error",
"no-dupe-args": "error",
"no-duplicate-case": "error",
"no-else-return": "error",
"no-empty": "error",
"no-empty-character-class": "error",
"no-eq-null": "off",
"no-eval": "error",
"no-ex-assign": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-boolean-cast": "error",
"no-extra-parens": "off",
"no-extra-semi": "error",
"no-fallthrough": "error",
"no-floating-decimal": "error",
"no-func-assign": "error",
"no-implicit-coercion": "error",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": ["error", "functions"],
"no-invalid-regexp": "error",
"no-invalid-this": "error",
"no-irregular-whitespace": "error",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "error",
"no-loop-func": "error",
"no-mixed-requires": ["error", false],
"no-mixed-spaces-and-tabs": ["error", false],
"linebreak-style": ["off", "unix"],
"no-multi-spaces": "error",
"no-multi-str": "off",
"no-multiple-empty-lines": ["error", {"max": 2}],
"no-native-reassign": "error",
"no-negated-in-lhs": "error",
"no-nested-ternary": "error",
"no-new": "error",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-obj-calls": "error",
"no-octal": "error",
"no-octal-escape": "off",
"no-param-reassign": "off",
"no-path-concat": "off",
"no-plusplus": "off",
"no-process-env": "off",
"no-process-exit": "off",
"no-proto": "off",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-restricted-modules": "off",
"no-return-assign": "error",
"no-script-url": "off",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "error",
"no-shadow-restricted-names": "error",
"no-spaced-func": "error",
"no-sparse-arrays": "error",
"no-sync": "off",
"no-ternary": "off",
"no-trailing-spaces": "error",
"no-this-before-super": "error",
"no-throw-literal": "error",
"no-undef": "error",
"no-undef-init": "error",
"no-undefined": "off",
"no-unexpected-multiline": "error",
"no-underscore-dangle": "off",
"no-unneeded-ternary": "off",
"no-unreachable": "error",
"no-unused-expressions": "error",
"no-unused-vars": ["error", {"vars": "all", "args": "after-used"}],
"no-use-before-define": "error",
"no-useless-call": "error",
"no-void": "off",
"no-var": "off",
"no-warning-comments": ["error", { "terms": ["todo", "fixme", "xxx"], "location": "start" }],
"no-with": "error",
"array-bracket-spacing": ["error", "never"],
"arrow-parens": "error",
"arrow-spacing": "error",
"accessor-pairs": "error",
"block-scoped-var": "off",
"brace-style": ["error", "stroustrup"],
"callback-return": ["error", ["callback", "cb", "next"]],
"camelcase": ["error", {"properties": "always"}],
"comma-dangle": ["error", "never"],
"comma-spacing": "error",
"comma-style": "error",
"complexity": "off",
"computed-property-spacing": ["off", "never"],
"consistent-return": "off",
"consistent-this": ["off", "that"],
"constructor-super": "error",
"curly": ["error", "all"],
"default-case": "error",
"dot-location": ["error", "property"],
"dot-notation": ["error", { "allowKeywords": true }],
"eol-last": "off",
"eqeqeq": ["error", "smart"],
"func-names": "off",
"func-style": ["off", "declaration"],
"generator-star-spacing": "off",
"guard-for-in": "error",
"handle-callback-err": "error",
"id-length": ["error", {"min": 3, "max": 25, "exceptions":["x", "y", "i", "j", "ex", "up"]}],
"indent": ["error", 2, {"SwitchCase": 1}],
"init-declarations": "off",
"key-spacing": ["error", { "beforeColon": false, "afterColon": true }],
"keyword-spacing": "error",
"lines-around-comment": "off",
"max-depth": ["error", 6],
"max-len": ["error", { "code": 160 }],
"max-nested-callbacks": ["error", 1],
"max-params": ["error", 6],
"max-statements": "off",
"new-cap": "error",
"new-parens": "error",
"newline-after-var": "off",
"object-curly-spacing": ["error", "always"],
"object-shorthand": "off",
"one-var": ["error", {
"initialized": "never"
}],
"operator-assignment": ["off", "always"],
"operator-linebreak": ["error", "after"],
"padded-blocks": "off",
"prefer-const": "off",
"prefer-spread": "off",
"prefer-reflect": "off",
"quote-props": "off",
"quotes": ["error", "single"],
"radix": "off",
"id-match": "off",
"require-yield": "off",
"semi": ["error", "always"],
"semi-spacing": ["error", {"before": false, "after": true}],
"sort-vars": "off",
"space-before-blocks": ["error", "always"],
"space-before-function-paren": ["error", "never"],
"space-in-parens": ["error", "never"],
"space-infix-ops": "error",
"space-unary-ops": ["error", { "words": true, "nonwords": false }],
"spaced-comment": "off",
"strict": ["error", "global"],
"use-isnan": "error",
"valid-jsdoc": "off",
"valid-typeof": "error",
"vars-on-top": "off",
"wrap-iife": "off",
"wrap-regex": "off",
"yoda": ["off", "never"]
},
"env": {
"node": true,
"es6": true
} }
]
} }

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ node_modules
coverage coverage
examples/*.png examples/*.png
browser\.js browser\.js
.nyc_output

2
.prettierignore Normal file
View file

@ -0,0 +1,2 @@
/browser.js
/test/imagediff.js

View file

@ -1,8 +1,6 @@
language: node_js language: node_js
after_success: after_success:
- if [ "$TRAVIS_NODE_VERSION" = "10" ]; then npm run coverage && npm i coveralls@2 && npm run coveralls; fi - if [ "$TRAVIS_NODE_VERSION" = "10" ]; then yarn coverage && yarn coveralls; fi
node_js: node_js:
- "8"
- "10" - "10"
- "11"
- "12" - "12"

298
README.md
View file

@ -1,63 +1,60 @@
[![Build Status](https://travis-ci.org/lukeapage/pngjs.svg?branch=master)](https://travis-ci.org/lukeapage/pngjs) [![Build status](https://ci.appveyor.com/api/projects/status/tb8418jql1trkntd/branch/master?svg=true)](https://ci.appveyor.com/project/lukeapage/pngjs2/branch/master) [![Coverage Status](https://coveralls.io/repos/lukeapage/pngjs2/badge.svg?branch=master&service=github)](https://coveralls.io/github/lukeapage/pngjs2?branch=master) [![npm version](https://badge.fury.io/js/pngjs.svg)](http://badge.fury.io/js/pngjs) [![Build Status](https://travis-ci.org/lukeapage/pngjs.svg?branch=master)](https://travis-ci.org/lukeapage/pngjs) [![Build status](https://ci.appveyor.com/api/projects/status/tb8418jql1trkntd/branch/master?svg=true)](https://ci.appveyor.com/project/lukeapage/pngjs2/branch/master) [![Coverage Status](https://coveralls.io/repos/lukeapage/pngjs2/badge.svg?branch=master&service=github)](https://coveralls.io/github/lukeapage/pngjs2?branch=master) [![npm version](https://badge.fury.io/js/pngjs.svg)](http://badge.fury.io/js/pngjs)
pngjs # pngjs
========
[![Greenkeeper badge](https://badges.greenkeeper.io/lukeapage/pngjs.svg)](https://greenkeeper.io/) [![Greenkeeper badge](https://badges.greenkeeper.io/lukeapage/pngjs.svg)](https://greenkeeper.io/)
Simple PNG encoder/decoder for Node.js with no dependencies. Simple PNG encoder/decoder for Node.js with no dependencies.
Based on the original [pngjs](https://github.com/niegowski/node-pngjs) with the follow enhancements. Based on the original [pngjs](https://github.com/niegowski/node-pngjs) with the follow enhancements.
* Support for reading 1,2,4 & 16 bit files - Support for reading 1,2,4 & 16 bit files
* Support for reading interlace files - Support for reading interlace files
* Support for reading `tTRNS` transparent colours - Support for reading `tTRNS` transparent colours
* Support for writing colortype 0 (grayscale), colortype 2 (RGB), colortype 4 (grayscale alpha) and colortype 6 (RGBA) - Support for writing colortype 0 (grayscale), colortype 2 (RGB), colortype 4 (grayscale alpha) and colortype 6 (RGBA)
* Sync interface as well as async - Sync interface as well as async
* API compatible with pngjs and node-pngjs - API compatible with pngjs and node-pngjs
Known lack of support for: Known lack of support for:
* Extended PNG e.g. Animation - Extended PNG e.g. Animation
* Writing in colortype 3 (indexed color) - Writing in colortype 3 (indexed color)
# Table of Contents # Table of Contents
* [Requirements](#requirements)
* [Comparison Table](#comparison-table)
* [Tests](#tests)
* [Installation](#installation)
* [Browser](#browser)
* [Example](#example)
* [Async API](#async-api)
* [Sync API](#sync-api)
* [Changelog](#changelog)
Requirements - [Requirements](#requirements)
============ - [Comparison Table](#comparison-table)
- [Tests](#tests)
- [Installation](#installation)
- [Browser](#browser)
- [Example](#example)
- [Async API](#async-api)
- [Sync API](#sync-api)
- [Changelog](#changelog)
* Node.js v4 (use older v2.3.0 for 0.10/0.12/iojs support) # Requirements
Comparison Table - Node.js v4 (use older v2.3.0 for 0.10/0.12/iojs support)
================
Name | Forked From | Sync | Async | 16 Bit | 1/2/4 Bit | Interlace | Gamma | Encodes | Tested # Comparison Table
---------|--------------|------|-------|--------|-----------|-----------|-------|---------|--------
pngjs | | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes
node-png | pngjs | No | Yes | No | No | No | Hidden| Yes | Manual
png-coder| pngjs | No | Yes | Yes | No | No | Hidden| Yes | Manual
pngparse | | No | Yes | No | Yes | No | No | No | Yes
pngparse-sync | pngparse| Yes | No | No | Yes | No | No | No | Yes
png-async| | No | Yes | No | No | No | No | Yes | Yes
png-js | | No | Yes | No | No | No | No | No | No
| Name | Forked From | Sync | Async | 16 Bit | 1/2/4 Bit | Interlace | Gamma | Encodes | Tested |
| ------------- | ----------- | ---- | ----- | ------ | --------- | --------- | ------ | ------- | ------ |
| pngjs | | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| node-png | pngjs | No | Yes | No | No | No | Hidden | Yes | Manual |
| png-coder | pngjs | No | Yes | Yes | No | No | Hidden | Yes | Manual |
| pngparse | | No | Yes | No | Yes | No | No | No | Yes |
| pngparse-sync | pngparse | Yes | No | No | Yes | No | No | No | Yes |
| png-async | | No | Yes | No | No | No | No | Yes | Yes |
| png-js | | No | Yes | No | No | No | No | No | No |
Native C++ node decoders: Native C++ node decoders:
* png
* png-sync (sync version of above)
* pixel-png
* png-img
Tests - png
===== - png-sync (sync version of above)
- pixel-png
- png-img
# Tests
Tested 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. Tested 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.
@ -67,65 +64,67 @@ The only thing not converted is gamma correction - this is because multiple vend
In addition we use a tolerance of 3 for 16 bit images in PhantomJS because PhantomJS seems to have non-compliant rules for downscaling 16 bit images. In addition we use a tolerance of 3 for 16 bit images in PhantomJS because PhantomJS seems to have non-compliant rules for downscaling 16 bit images.
Installation # Installation
===============
``` ```
$ npm install pngjs --save $ npm install pngjs --save
``` ```
Browser # Browser
===========
The 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: The 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:
``` ```
import { PNG } from 'pngjs/browser'; import { PNG } from 'pngjs/browser';
``` ```
Example # Example
==========
```js ```js
var fs = require('fs'), var fs = require("fs"),
PNG = require('pngjs').PNG; PNG = require("pngjs").PNG;
fs.createReadStream('in.png') fs.createReadStream("in.png")
.pipe(new PNG({ .pipe(
filterType: 4 new PNG({
})) filterType: 4,
.on('parsed', function() { })
)
.on("parsed", function () {
for (var y = 0; y < this.height; y++) {
for (var x = 0; x < this.width; x++) {
var idx = (this.width * y + x) << 2;
for (var y = 0; y < this.height; y++) { // invert color
for (var x = 0; x < this.width; x++) { this.data[idx] = 255 - this.data[idx];
var idx = (this.width * y + x) << 2; this.data[idx + 1] = 255 - this.data[idx + 1];
this.data[idx + 2] = 255 - this.data[idx + 2];
// invert color // and reduce opacity
this.data[idx] = 255 - this.data[idx]; this.data[idx + 3] = this.data[idx + 3] >> 1;
this.data[idx+1] = 255 - this.data[idx+1]; }
this.data[idx+2] = 255 - this.data[idx+2]; }
// and reduce opacity this.pack().pipe(fs.createWriteStream("out.png"));
this.data[idx+3] = this.data[idx+3] >> 1; });
}
}
this.pack().pipe(fs.createWriteStream('out.png'));
});
``` ```
For more examples see `examples` folder. For more examples see `examples` folder.
Async API # Async API
================
As 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. As 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.
## Class: PNG ## Class: PNG
`PNG` is readable and writable `Stream`. `PNG` is readable and writable `Stream`.
### Options ### Options
- `width` - use this with `height` if you want to create png from scratch - `width` - use this with `height` if you want to create png from scratch
- `height` - as above - `height` - as above
- `checkCRC` - whether parser should be strict about checksums in source stream (default: `true`) - `checkCRC` - whether parser should be strict about checksums in source stream (default: `true`)
- `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) - `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)
- `deflateLevel` - compression level for deflate (default: 9) - `deflateLevel` - compression level for deflate (default: 9)
- `deflateStrategy` - compression strategy for deflate (default: 3) - `deflateStrategy` - compression strategy for deflate (default: 3)
- `deflateFactory` - deflate stream factory (default: `zlib.createDeflate`) - `deflateFactory` - deflate stream factory (default: `zlib.createDeflate`)
@ -133,15 +132,16 @@ As input any color type is accepted (grayscale, rgb, palette, grayscale with alp
- `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. - `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.
- `inputColorType` - the input colorType - see constants. Default is 6 (RGBA) - `inputColorType` - the input colorType - see constants. Default is 6 (RGBA)
- `bitDepth` - the bitDepth of the output, 8 or 16 bits. Input data is expected to have this bit depth. - `bitDepth` - the bitDepth of the output, 8 or 16 bits. Input data is expected to have this bit depth.
16 bit data is expected in the system endianness (Default: 8) 16 bit data is expected in the system endianness (Default: 8)
- `inputHasAlpha` - whether the input bitmap has 4 bytes per pixel (rgb and alpha) or 3 (rgb - no alpha). - `inputHasAlpha` - whether the input bitmap has 4 bytes per pixel (rgb and alpha) or 3 (rgb - no alpha).
- `bgColor` - an object containing red, green, and blue values between 0 and 255 - `bgColor` - an object containing red, green, and blue values between 0 and 255
that is used when packing a PNG if alpha is not to be included (default: 255,255,255) that is used when packing a PNG if alpha is not to be included (default: 255,255,255)
### Event "metadata" ### Event "metadata"
`function(metadata) { }` `function(metadata) { }`
Image's header has been parsed, metadata contains this information: Image's header has been parsed, metadata contains this information:
- `width` image size in pixels - `width` image size in pixels
- `height` image size in pixels - `height` image size in pixels
- `palette` image is paletted - `palette` image is paletted
@ -149,17 +149,17 @@ Image's header has been parsed, metadata contains this information:
- `alpha` image contains alpha channel - `alpha` image contains alpha channel
- `interlace` image is interlaced - `interlace` image is interlaced
### Event: "parsed" ### Event: "parsed"
`function(data) { }` `function(data) { }`
Input image has been completely parsed, `data` is complete and ready for modification. Input image has been completely parsed, `data` is complete and ready for modification.
### Event: "error" ### Event: "error"
`function(error) { }` `function(error) { }`
### png.parse(data, [callback]) ### png.parse(data, [callback])
Parses PNG file data. Can be `String` or `Buffer`. Alternatively you can stream data to instance of PNG. Parses PNG file data. Can be `String` or `Buffer`. Alternatively you can stream data to instance of PNG.
Optional `callback` is once called on `error` or `parsed`. The callback gets Optional `callback` is once called on `error` or `parsed`. The callback gets
@ -168,36 +168,39 @@ two arguments `(err, data)`.
Returns `this` for method chaining. Returns `this` for method chaining.
#### Example #### Example
```js ```js
new PNG({ filterType:4 }).parse( imageData, function(error, data) new PNG({ filterType: 4 }).parse(imageData, function (error, data) {
{ console.log(error, data);
console.log(error, data)
}); });
``` ```
### png.pack() ### png.pack()
Starts converting data to PNG file Stream. Starts converting data to PNG file Stream.
Returns `this` for method chaining. Returns `this` for method chaining.
### png.bitblt(dst, sx, sy, w, h, dx, dy) ### png.bitblt(dst, sx, sy, w, h, dx, dy)
Helper 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`). Helper 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`).
Returns `this` for method chaining. Returns `this` for method chaining.
For example, the following code copies the top-left 100x50 px of `in.png` into dst and writes it to `out.png`: For example, the following code copies the top-left 100x50 px of `in.png` into dst and writes it to `out.png`:
```js ```js
var dst = new PNG({width: 100, height: 50}); var dst = new PNG({ width: 100, height: 50 });
fs.createReadStream('in.png') fs.createReadStream("in.png")
.pipe(new PNG()) .pipe(new PNG())
.on('parsed', function() { .on("parsed", function () {
this.bitblt(dst, 0, 0, 100, 50, 0, 0); this.bitblt(dst, 0, 0, 100, 50, 0, 0);
dst.pack().pipe(fs.createWriteStream('out.png')); dst.pack().pipe(fs.createWriteStream("out.png"));
}); });
``` ```
### Property: adjustGamma() ### Property: adjustGamma()
Helper 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. Helper 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.
In tests against PNG suite it compared 100% with chrome on all 8 bit and below images. On IE there were some differences. In tests against PNG suite it compared 100% with chrome on all 8 bit and below images. On IE there were some differences.
@ -205,27 +208,28 @@ In tests against PNG suite it compared 100% with chrome on all 8 bit and below i
The 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. The 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.
```js ```js
fs.createReadStream('in.png') fs.createReadStream("in.png")
.pipe(new PNG()) .pipe(new PNG())
.on('parsed', function() { .on("parsed", function () {
this.adjustGamma(); this.adjustGamma();
this.pack().pipe(fs.createWriteStream('out.png')); this.pack().pipe(fs.createWriteStream("out.png"));
}); });
``` ```
### Property: width ### Property: width
Width of image in pixels Width of image in pixels
### Property: height ### Property: height
Height of image in pixels Height of image in pixels
### Property: data ### Property: data
Buffer of image pixel data. Every pixel consists 4 bytes: R, G, B, A (opacity). Buffer of image pixel data. Every pixel consists 4 bytes: R, G, B, A (opacity).
### Property: gamma ### Property: gamma
Gamma of image (0 if not specified) Gamma of image (0 if not specified)
## Packing a PNG and removing alpha (RGBA to RGB) ## Packing a PNG and removing alpha (RGBA to RGB)
@ -235,21 +239,23 @@ convert each pixel's transparency to the appropriate RGB value. By default, pngj
the image against a white background. You can override this in the options: the image against a white background. You can override this in the options:
```js ```js
var fs = require('fs'), var fs = require("fs"),
PNG = require('pngjs').PNG; PNG = require("pngjs").PNG;
fs.createReadStream('in.png') fs.createReadStream("in.png")
.pipe(new PNG({ .pipe(
colorType: 2, new PNG({
bgColor: { colorType: 2,
red: 0, bgColor: {
green: 255, red: 0,
blue: 0 green: 255,
} blue: 0,
})) },
.on('parsed', function() { })
this.pack().pipe(fs.createWriteStream('out.png')); )
}); .on("parsed", function () {
this.pack().pipe(fs.createWriteStream("out.png"));
});
``` ```
# Sync API # Sync API
@ -287,9 +293,7 @@ var png = PNG.sync.read(data);
PNG.adjustGamma(png); PNG.adjustGamma(png);
``` ```
# Changelog
Changelog
============
### 4.0.0 - 09/04/2020 ### 4.0.0 - 09/04/2020
@ -325,62 +329,76 @@ Changelog
- Support for encoding 8-bit grayscale images - Support for encoding 8-bit grayscale images
### 3.1.0 - 30/04/2017 ### 3.1.0 - 30/04/2017
- Support for pngs with zlib chunks that are malformed after valid data
- Support for pngs with zlib chunks that are malformed after valid data
### 3.0.1 - 16/02/2017 ### 3.0.1 - 16/02/2017
- Fix single pixel pngs
- Fix single pixel pngs
### 3.0.0 - 03/08/2016 ### 3.0.0 - 03/08/2016
- Drop support for node below v4 and iojs. Pin to 2.3.0 to use with old, unsupported or patched node versions.
- Drop support for node below v4 and iojs. Pin to 2.3.0 to use with old, unsupported or patched node versions.
### 2.3.0 - 22/04/2016 ### 2.3.0 - 22/04/2016
- Support for sync in node 0.10
- Support for sync in node 0.10
### 2.2.0 - 04/12/2015 ### 2.2.0 - 04/12/2015
- Add sync write api
- Fix newfile example - Add sync write api
- Correct comparison table - Fix newfile example
- Correct comparison table
### 2.1.0 - 28/10/2015 ### 2.1.0 - 28/10/2015
- rename package to pngjs
- added 'bgColor' option - rename package to pngjs
- added 'bgColor' option
### 2.0.0 - 08/10/2015 ### 2.0.0 - 08/10/2015
- fixes to readme
- *breaking change* - bitblt on the png prototype now doesn't take a unused, unnecessary src first argument - fixes to readme
- _breaking change_ - bitblt on the png prototype now doesn't take a unused, unnecessary src first argument
### 1.2.0 - 13/09/2015 ### 1.2.0 - 13/09/2015
- support passing colorType to write PNG's and writing bitmaps without alpha information
- support passing colorType to write PNG's and writing bitmaps without alpha information
### 1.1.0 - 07/09/2015 ### 1.1.0 - 07/09/2015
- support passing a deflate factory for controlled compression
- support passing a deflate factory for controlled compression
### 1.0.2 - 22/08/2015 ### 1.0.2 - 22/08/2015
- Expose all PNG creation info
- Expose all PNG creation info
### 1.0.1 - 21/08/2015 ### 1.0.1 - 21/08/2015
- Fix non square interlaced files
- Fix non square interlaced files
### 1.0.0 - 08/08/2015 ### 1.0.0 - 08/08/2015
- More tests
- source linted - More tests
- maintainability refactorings - source linted
- async API - exceptions in reading now emit warnings - maintainability refactorings
- documentation improvement - sync api now documented, adjustGamma documented - async API - exceptions in reading now emit warnings
- breaking change - gamma chunk is now written. previously a read then write would destroy gamma information, now it is persisted. - documentation improvement - sync api now documented, adjustGamma documented
- breaking change - gamma chunk is now written. previously a read then write would destroy gamma information, now it is persisted.
### 0.0.3 - 03/08/2015 ### 0.0.3 - 03/08/2015
- Error handling fixes
- ignore files for smaller npm footprint - Error handling fixes
- ignore files for smaller npm footprint
### 0.0.2 - 02/08/2015 ### 0.0.2 - 02/08/2015
- Bugfixes to interlacing, support for transparent colours
- Bugfixes to interlacing, support for transparent colours
### 0.0.1 - 02/08/2015 ### 0.0.1 - 02/08/2015
- Initial release, see pngjs for older changelog.
License - Initial release, see pngjs for older changelog.
=========
# License
(The MIT License) (The MIT License)

View file

@ -4,8 +4,8 @@ clone_depth: 10
environment: environment:
matrix: matrix:
- nodejs_version: '4' - nodejs_version: "10"
- nodejs_version: '6' - nodejs_version: "12"
install: install:
- ps: Install-Product node $env:nodejs_version - ps: Install-Product node $env:nodejs_version
@ -18,7 +18,7 @@ test_script:
- npm test - npm test
cache: cache:
- node_modules # local npm modules - node_modules # local npm modules
matrix: matrix:
fast_finish: true fast_finish: true

View file

@ -1,51 +1,50 @@
#!/usr/bin/env node #!/usr/bin/env node
var fs = require('fs'); let fs = require("fs");
var PNG = require("../lib/png").PNG; let PNG = require("../lib/png").PNG;
var w = 32; let w = 32;
var h = 64; let h = 64;
/// RGBA input (color type 6) /// RGBA input (color type 6)
var buffer = Buffer.alloc(2 * w * h * 4); let buffer = Buffer.alloc(2 * w * h * 4);
var bitmap = new Uint16Array(buffer.buffer); let bitmap = new Uint16Array(buffer.buffer);
for (var i = 0; i < h; i++) { for (let i = 0; i < h; i++) {
for (var j = 0; j < w; j++) { for (let j = 0; j < w; j++) {
bitmap[i * 4 * w + 4*j] = i * 65535 / h; bitmap[i * 4 * w + 4 * j] = (i * 65535) / h;
bitmap[i * 4 * w + 4*j + 1] = j * 65535 / w; bitmap[i * 4 * w + 4 * j + 1] = (j * 65535) / w;
bitmap[i * 4 * w + 4*j + 2] = (h-i) * 65535 / h; bitmap[i * 4 * w + 4 * j + 2] = ((h - i) * 65535) / h;
bitmap[i * 4 * w + 4*j + 3] = 65535; bitmap[i * 4 * w + 4 * j + 3] = 65535;
} }
} }
var png = new PNG({ let png = new PNG({
width: w, width: w,
height:h, height: h,
bitDepth: 16, bitDepth: 16,
colorType: 6, colorType: 6,
inputColorType: 6, inputColorType: 6,
inputHasAlpha: true inputHasAlpha: true,
}); });
png.data = buffer; png.data = buffer;
png.pack().pipe(fs.createWriteStream('colortype6.png')); png.pack().pipe(fs.createWriteStream("colortype6.png"));
//////// Grayscale 16 bits/////// //////// Grayscale 16 bits///////
var buffer = Buffer.alloc(2 * w * h); buffer = Buffer.alloc(2 * w * h);
var bitmap = new Uint16Array(buffer.buffer); bitmap = new Uint16Array(buffer.buffer);
for (var i = 0; i < h; i++) { for (let i = 0; i < h; i++) {
for (var j = 0; j < w; j++) for (let j = 0; j < w; j++) bitmap[i * w + j] = (i * 65535) / h;
bitmap[i * w + j] = i * 65535 / h;
} }
png = new PNG({ png = new PNG({
width: w, width: w,
height:h, height: h,
bitDepth: 16, bitDepth: 16,
colorType: 0, colorType: 0,
inputColorType: 0, inputColorType: 0,
inputHasAlpha: false inputHasAlpha: false,
}); });
png.data = buffer; png.data = buffer;
png.pack().pipe(fs.createWriteStream('colortype0.png')); png.pack().pipe(fs.createWriteStream("colortype0.png"));

View file

@ -1,25 +1,22 @@
let fs = require("fs"),
PNG = require("../lib/png").PNG; // note require('pngjs') outside this project
var fs = require('fs'), fs.createReadStream("test/in/basi0g01.png")
PNG = require('../lib/png').PNG; // note require('pngjs') outside this project .pipe(new PNG({}))
.on("parsed", function () {
for (let y = 0; y < this.height; y++) {
for (let x = 0; x < this.width; x++) {
let idx = (this.width * y + x) << 2;
fs.createReadStream('test/in/basi0g01.png') // invert color
.pipe(new PNG({ this.data[idx] = 255 - this.data[idx];
})) this.data[idx + 1] = 255 - this.data[idx + 1];
.on('parsed', function() { this.data[idx + 2] = 255 - this.data[idx + 2];
for (var y = 0; y < this.height; y++) { // and reduce opacity
for (var x = 0; x < this.width; x++) { this.data[idx + 3] = this.data[idx + 3] >> 1;
var idx = (this.width * y + x) << 2; }
}
// invert color this.pack().pipe(fs.createWriteStream("out.png"));
this.data[idx] = 255 - this.data[idx]; });
this.data[idx+1] = 255 - this.data[idx+1];
this.data[idx+2] = 255 - this.data[idx+2];
// and reduce opacity
this.data[idx+3] = this.data[idx+3] >> 1;
}
}
this.pack().pipe(fs.createWriteStream('out.png'));
});

View file

@ -1,13 +1,14 @@
var PNG = require("../lib/png").PNG; let PNG = require("../lib/png").PNG;
var fs = require("fs"); let fs = require("fs");
var newfile = new PNG({width:10,height:10}); let newfile = new PNG({ width: 10, height: 10 });
for (var y = 0; y < newfile.height; y++) { for (let y = 0; y < newfile.height; y++) {
for (var x = 0; x < newfile.width; x++) { for (let x = 0; x < newfile.width; x++) {
var idx = (newfile.width * y + x) << 2; let idx = (newfile.width * y + x) << 2;
var col = x < (newfile.width >> 1) ^ y < (newfile.height >> 1) ? 0xe5 : 0xff; let col =
(x < newfile.width >> 1) ^ (y < newfile.height >> 1) ? 0xe5 : 0xff;
newfile.data[idx] = col; newfile.data[idx] = col;
newfile.data[idx + 1] = col; newfile.data[idx + 1] = col;
@ -16,8 +17,9 @@ for (var y = 0; y < newfile.height; y++) {
} }
} }
newfile.pack() newfile
.pipe(fs.createWriteStream(__dirname + '/newfile.png')) .pack()
.on('finish', function() { .pipe(fs.createWriteStream(__dirname + "/newfile.png"))
console.log('Written!'); .on("finish", function () {
console.log("Written!");
}); });

View file

@ -1,34 +1,34 @@
var fs = require('fs'); let fs = require("fs");
var PNG = require("../lib/png").PNG; let PNG = require("../lib/png").PNG;
var w = 320; let w = 320;
var h = 200; let h = 200;
var bitmapWithoutAlpha = Buffer.alloc(w * h * 3); let bitmapWithoutAlpha = Buffer.alloc(w * h * 3);
var ofs=0; let ofs = 0;
for (var i = 0; i < bitmapWithoutAlpha.length; i+=3) { for (let i = 0; i < bitmapWithoutAlpha.length; i += 3) {
bitmapWithoutAlpha[ofs++] = 0xff; bitmapWithoutAlpha[ofs++] = 0xff;
bitmapWithoutAlpha[ofs++] = i % 0xff; bitmapWithoutAlpha[ofs++] = i % 0xff;
bitmapWithoutAlpha[ofs++] = (i/3) % 0xff; bitmapWithoutAlpha[ofs++] = (i / 3) % 0xff;
} }
var png = new PNG({ let png = new PNG({
width: w, width: w,
height:h, height: h,
bitDepth: 8, bitDepth: 8,
colorType: 2, colorType: 2,
inputHasAlpha: false inputHasAlpha: false,
}); });
png.data = bitmapWithoutAlpha; png.data = bitmapWithoutAlpha;
png.pack().pipe(fs.createWriteStream('colortype2.png')); png.pack().pipe(fs.createWriteStream("colortype2.png"));
var png = new PNG({ png = new PNG({
width: w, width: w,
height:h, height: h,
bitDepth: 8, bitDepth: 8,
colorType: 6, colorType: 6,
inputHasAlpha: false inputHasAlpha: false,
}); });
png.data = bitmapWithoutAlpha; png.data = bitmapWithoutAlpha;
png.pack().pipe(fs.createWriteStream('colortype6.png')); png.pack().pipe(fs.createWriteStream("colortype6.png"));

View file

@ -1,30 +1,28 @@
#!/usr/bin/env node #!/usr/bin/env node
var fs = require('fs'), let fs = require("fs"),
PNG = require('../lib/png').PNG; PNG = require("../lib/png").PNG;
let png = new PNG({
filterType: -1,
}),
src = fs.createReadStream(process.argv[2]),
dst = fs.createWriteStream(process.argv[3] || "out.png");
var png = new PNG({ png.on("parsed", function () {
filterType: -1 for (let y = 0; y < png.height; y++) {
}), for (let x = 0; x < png.width; x++) {
src = fs.createReadStream(process.argv[2]), let idx = (png.width * y + x) << 2;
dst = fs.createWriteStream(process.argv[3] || 'out.png');
if (
png.on('parsed', function() { Math.abs(png.data[idx] - png.data[idx + 1]) <= 1 &&
Math.abs(png.data[idx + 1] - png.data[idx + 2]) <= 1
for (var y = 0; y < png.height; y++) { )
for (var x = 0; x < png.width; x++) { png.data[idx] = png.data[idx + 1] = png.data[idx + 2];
var idx = (png.width * y + x) << 2;
if (Math.abs(png.data[idx] - png.data[idx+1]) <= 1
&& Math.abs(png.data[idx+1] - png.data[idx+2]) <= 1)
png.data[idx] = png.data[idx+1] = png.data[idx+2];
}
} }
}
png.pack().pipe(dst); png.pack().pipe(dst);
}); });
src.pipe(png); src.pipe(png);

View file

@ -1,19 +1,18 @@
#!/usr/bin/env node #!/usr/bin/env node
var fs = require('fs'), let fs = require("fs"),
PNG = require('../lib/png').PNG; PNG = require("../lib/png").PNG;
let srcFname = process.argv[2],
var srcFname = process.argv[2], dstFname = process.argv[3] || "out.png";
dstFname = process.argv[3] || 'out.png';
// Read a PNG file // Read a PNG file
var data = fs.readFileSync(srcFname); let data = fs.readFileSync(srcFname);
// Parse it // Parse it
var png = PNG.sync.read(data, { let png = PNG.sync.read(data, {
filterType: -1 filterType: -1,
}); });
// Pack it back into a PNG data // Pack it back into a PNG data
var buff = PNG.sync.write(png); let buff = PNG.sync.write(png);
// Write a PNG file // Write a PNG file
fs.writeFileSync(dstFname, buff); fs.writeFileSync(dstFname, buff);

View file

@ -1,19 +1,19 @@
'use strict'; "use strict";
var interlaceUtils = require('./interlace'); let interlaceUtils = require("./interlace");
var pixelBppMapper = [ let pixelBppMapper = [
// 0 - dummy entry // 0 - dummy entry
function() {}, function () {},
// 1 - L // 1 - L
// 0: 0, 1: 0, 2: 0, 3: 0xff // 0: 0, 1: 0, 2: 0, 3: 0xff
function(pxData, data, pxPos, rawPos) { function (pxData, data, pxPos, rawPos) {
if (rawPos === data.length) { if (rawPos === data.length) {
throw new Error('Ran out of data'); throw new Error("Ran out of data");
} }
var pixel = data[rawPos]; let pixel = data[rawPos];
pxData[pxPos] = pixel; pxData[pxPos] = pixel;
pxData[pxPos + 1] = pixel; pxData[pxPos + 1] = pixel;
pxData[pxPos + 2] = pixel; pxData[pxPos + 2] = pixel;
@ -22,12 +22,12 @@ var pixelBppMapper = [
// 2 - LA // 2 - LA
// 0: 0, 1: 0, 2: 0, 3: 1 // 0: 0, 1: 0, 2: 0, 3: 1
function(pxData, data, pxPos, rawPos) { function (pxData, data, pxPos, rawPos) {
if (rawPos + 1 >= data.length) { if (rawPos + 1 >= data.length) {
throw new Error('Ran out of data'); throw new Error("Ran out of data");
} }
var pixel = data[rawPos]; let pixel = data[rawPos];
pxData[pxPos] = pixel; pxData[pxPos] = pixel;
pxData[pxPos + 1] = pixel; pxData[pxPos + 1] = pixel;
pxData[pxPos + 2] = pixel; pxData[pxPos + 2] = pixel;
@ -36,9 +36,9 @@ var pixelBppMapper = [
// 3 - RGB // 3 - RGB
// 0: 0, 1: 1, 2: 2, 3: 0xff // 0: 0, 1: 1, 2: 2, 3: 0xff
function(pxData, data, pxPos, rawPos) { function (pxData, data, pxPos, rawPos) {
if (rawPos + 2 >= data.length) { if (rawPos + 2 >= data.length) {
throw new Error('Ran out of data'); throw new Error("Ran out of data");
} }
pxData[pxPos] = data[rawPos]; pxData[pxPos] = data[rawPos];
@ -49,26 +49,26 @@ var pixelBppMapper = [
// 4 - RGBA // 4 - RGBA
// 0: 0, 1: 1, 2: 2, 3: 3 // 0: 0, 1: 1, 2: 2, 3: 3
function(pxData, data, pxPos, rawPos) { function (pxData, data, pxPos, rawPos) {
if (rawPos + 3 >= data.length) { if (rawPos + 3 >= data.length) {
throw new Error('Ran out of data'); throw new Error("Ran out of data");
} }
pxData[pxPos] = data[rawPos]; pxData[pxPos] = data[rawPos];
pxData[pxPos + 1] = data[rawPos + 1]; pxData[pxPos + 1] = data[rawPos + 1];
pxData[pxPos + 2] = data[rawPos + 2]; pxData[pxPos + 2] = data[rawPos + 2];
pxData[pxPos + 3] = data[rawPos + 3]; pxData[pxPos + 3] = data[rawPos + 3];
} },
]; ];
var pixelBppCustomMapper = [ let pixelBppCustomMapper = [
// 0 - dummy entry // 0 - dummy entry
function() {}, function () {},
// 1 - L // 1 - L
// 0: 0, 1: 0, 2: 0, 3: 0xff // 0: 0, 1: 0, 2: 0, 3: 0xff
function(pxData, pixelData, pxPos, maxBit) { function (pxData, pixelData, pxPos, maxBit) {
var pixel = pixelData[0]; let pixel = pixelData[0];
pxData[pxPos] = pixel; pxData[pxPos] = pixel;
pxData[pxPos + 1] = pixel; pxData[pxPos + 1] = pixel;
pxData[pxPos + 2] = pixel; pxData[pxPos + 2] = pixel;
@ -77,8 +77,8 @@ var pixelBppCustomMapper = [
// 2 - LA // 2 - LA
// 0: 0, 1: 0, 2: 0, 3: 1 // 0: 0, 1: 0, 2: 0, 3: 1
function(pxData, pixelData, pxPos) { function (pxData, pixelData, pxPos) {
var pixel = pixelData[0]; let pixel = pixelData[0];
pxData[pxPos] = pixel; pxData[pxPos] = pixel;
pxData[pxPos + 1] = pixel; pxData[pxPos + 1] = pixel;
pxData[pxPos + 2] = pixel; pxData[pxPos + 2] = pixel;
@ -87,7 +87,7 @@ var pixelBppCustomMapper = [
// 3 - RGB // 3 - RGB
// 0: 0, 1: 1, 2: 2, 3: 0xff // 0: 0, 1: 1, 2: 2, 3: 0xff
function(pxData, pixelData, pxPos, maxBit) { function (pxData, pixelData, pxPos, maxBit) {
pxData[pxPos] = pixelData[0]; pxData[pxPos] = pixelData[0];
pxData[pxPos + 1] = pixelData[1]; pxData[pxPos + 1] = pixelData[1];
pxData[pxPos + 2] = pixelData[2]; pxData[pxPos + 2] = pixelData[2];
@ -96,33 +96,32 @@ var pixelBppCustomMapper = [
// 4 - RGBA // 4 - RGBA
// 0: 0, 1: 1, 2: 2, 3: 3 // 0: 0, 1: 1, 2: 2, 3: 3
function(pxData, pixelData, pxPos) { function (pxData, pixelData, pxPos) {
pxData[pxPos] = pixelData[0]; pxData[pxPos] = pixelData[0];
pxData[pxPos + 1] = pixelData[1]; pxData[pxPos + 1] = pixelData[1];
pxData[pxPos + 2] = pixelData[2]; pxData[pxPos + 2] = pixelData[2];
pxData[pxPos + 3] = pixelData[3]; pxData[pxPos + 3] = pixelData[3];
} },
]; ];
function bitRetriever(data, depth) { function bitRetriever(data, depth) {
let leftOver = [];
var leftOver = []; let i = 0;
var i = 0;
function split() { function split() {
if (i === data.length) { if (i === data.length) {
throw new Error('Ran out of data'); throw new Error("Ran out of data");
} }
var byte = data[i]; let byte = data[i];
i++; i++;
var byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1; let byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
switch (depth) { switch (depth) {
default: default:
throw new Error('unrecognised depth'); throw new Error("unrecognised depth");
case 16: case 16:
byte2 = data[i]; byte2 = data[i];
i++; i++;
leftOver.push(((byte << 8) + byte2)); leftOver.push((byte << 8) + byte2);
break; break;
case 4: case 4:
byte2 = byte & 0x0f; byte2 = byte & 0x0f;
@ -131,52 +130,53 @@ function bitRetriever(data, depth) {
break; break;
case 2: case 2:
byte4 = byte & 3; byte4 = byte & 3;
byte3 = byte >> 2 & 3; byte3 = (byte >> 2) & 3;
byte2 = byte >> 4 & 3; byte2 = (byte >> 4) & 3;
byte1 = byte >> 6 & 3; byte1 = (byte >> 6) & 3;
leftOver.push(byte1, byte2, byte3, byte4); leftOver.push(byte1, byte2, byte3, byte4);
break; break;
case 1: case 1:
byte8 = byte & 1; byte8 = byte & 1;
byte7 = byte >> 1 & 1; byte7 = (byte >> 1) & 1;
byte6 = byte >> 2 & 1; byte6 = (byte >> 2) & 1;
byte5 = byte >> 3 & 1; byte5 = (byte >> 3) & 1;
byte4 = byte >> 4 & 1; byte4 = (byte >> 4) & 1;
byte3 = byte >> 5 & 1; byte3 = (byte >> 5) & 1;
byte2 = byte >> 6 & 1; byte2 = (byte >> 6) & 1;
byte1 = byte >> 7 & 1; byte1 = (byte >> 7) & 1;
leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8); leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
break; break;
} }
} }
return { return {
get: function(count) { get: function (count) {
while (leftOver.length < count) { while (leftOver.length < count) {
split(); split();
} }
var returner = leftOver.slice(0, count); let returner = leftOver.slice(0, count);
leftOver = leftOver.slice(count); leftOver = leftOver.slice(count);
return returner; return returner;
}, },
resetAfterLine: function() { resetAfterLine: function () {
leftOver.length = 0; leftOver.length = 0;
}, },
end: function() { end: function () {
if (i !== data.length) { if (i !== data.length) {
throw new Error('extra data found'); throw new Error("extra data found");
} }
} },
}; };
} }
function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) { // eslint-disable-line max-params function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) {
var imageWidth = image.width; // eslint-disable-line max-params
var imageHeight = image.height; let imageWidth = image.width;
var imagePass = image.index; let imageHeight = image.height;
for (var y = 0; y < imageHeight; y++) { let imagePass = image.index;
for (var x = 0; x < imageWidth; x++) { for (let y = 0; y < imageHeight; y++) {
var pxPos = getPxPos(x, y, imagePass); for (let x = 0; x < imageWidth; x++) {
let pxPos = getPxPos(x, y, imagePass);
pixelBppMapper[bpp](pxData, data, pxPos, rawPos); pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
rawPos += bpp; //eslint-disable-line no-param-reassign rawPos += bpp; //eslint-disable-line no-param-reassign
} }
@ -184,71 +184,82 @@ function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) { // eslint-di
return rawPos; return rawPos;
} }
function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) { // eslint-disable-line max-params function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) {
var imageWidth = image.width; // eslint-disable-line max-params
var imageHeight = image.height; let imageWidth = image.width;
var imagePass = image.index; let imageHeight = image.height;
for (var y = 0; y < imageHeight; y++) { let imagePass = image.index;
for (var x = 0; x < imageWidth; x++) { for (let y = 0; y < imageHeight; y++) {
var pixelData = bits.get(bpp); for (let x = 0; x < imageWidth; x++) {
var pxPos = getPxPos(x, y, imagePass); let pixelData = bits.get(bpp);
let pxPos = getPxPos(x, y, imagePass);
pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit); pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
} }
bits.resetAfterLine(); bits.resetAfterLine();
} }
} }
exports.dataToBitMap = function(data, bitmapInfo) { exports.dataToBitMap = function (data, bitmapInfo) {
let width = bitmapInfo.width;
var width = bitmapInfo.width; let height = bitmapInfo.height;
var height = bitmapInfo.height; let depth = bitmapInfo.depth;
var depth = bitmapInfo.depth; let bpp = bitmapInfo.bpp;
var bpp = bitmapInfo.bpp; let interlace = bitmapInfo.interlace;
var interlace = bitmapInfo.interlace; let bits;
if (depth !== 8) { if (depth !== 8) {
var bits = bitRetriever(data, depth); bits = bitRetriever(data, depth);
} }
var pxData; let pxData;
if (depth <= 8) { if (depth <= 8) {
pxData = Buffer.alloc(width * height * 4); pxData = Buffer.alloc(width * height * 4);
} } else {
else {
pxData = new Uint16Array(width * height * 4); pxData = new Uint16Array(width * height * 4);
} }
var maxBit = Math.pow(2, depth) - 1; let maxBit = Math.pow(2, depth) - 1;
var rawPos = 0; let rawPos = 0;
var images; let images;
var getPxPos; let getPxPos;
if (interlace) { if (interlace) {
images = interlaceUtils.getImagePasses(width, height); images = interlaceUtils.getImagePasses(width, height);
getPxPos = interlaceUtils.getInterlaceIterator(width, height); getPxPos = interlaceUtils.getInterlaceIterator(width, height);
} } else {
else { let nonInterlacedPxPos = 0;
var nonInterlacedPxPos = 0; getPxPos = function () {
getPxPos = function() { let returner = nonInterlacedPxPos;
var returner = nonInterlacedPxPos;
nonInterlacedPxPos += 4; nonInterlacedPxPos += 4;
return returner; return returner;
}; };
images = [{ width: width, height: height }]; images = [{ width: width, height: height }];
} }
for (var imageIndex = 0; imageIndex < images.length; imageIndex++) { for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
if (depth === 8) { if (depth === 8) {
rawPos = mapImage8Bit(images[imageIndex], pxData, getPxPos, bpp, data, rawPos); rawPos = mapImage8Bit(
} images[imageIndex],
else { pxData,
mapImageCustomBit(images[imageIndex], pxData, getPxPos, bpp, bits, maxBit); getPxPos,
bpp,
data,
rawPos
);
} else {
mapImageCustomBit(
images[imageIndex],
pxData,
getPxPos,
bpp,
bits,
maxBit
);
} }
} }
if (depth === 8) { if (depth === 8) {
if (rawPos !== data.length) { if (rawPos !== data.length) {
throw new Error('extra data found'); throw new Error("extra data found");
} }
} } else {
else {
bits.end(); bits.end();
} }

View file

@ -1,12 +1,15 @@
'use strict'; "use strict";
var constants = require('./constants'); let constants = require("./constants");
module.exports = function(dataIn, width, height, options) { module.exports = function (dataIn, width, height, options) {
var outHasAlpha = [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(options.colorType) !== -1; let outHasAlpha =
[constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(
options.colorType
) !== -1;
if (options.colorType === options.inputColorType) { if (options.colorType === options.inputColorType) {
var bigEndian = (function() { let bigEndian = (function () {
var buffer = new ArrayBuffer(2); let buffer = new ArrayBuffer(2);
new DataView(buffer).setInt16(0, 256, true /* littleEndian */); new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
// Int16Array uses the platform's endianness. // Int16Array uses the platform's endianness.
return new Int16Array(buffer)[0] !== 256; return new Int16Array(buffer)[0] !== 256;
@ -18,24 +21,24 @@ module.exports = function(dataIn, width, height, options) {
} }
// map to a UInt16 array if data is 16bit, fix endianness below // map to a UInt16 array if data is 16bit, fix endianness below
var data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer); let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
var maxValue = 255; let maxValue = 255;
var inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType]; let inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
if (inBpp === 4 && !options.inputHasAlpha) { if (inBpp === 4 && !options.inputHasAlpha) {
inBpp = 3; inBpp = 3;
} }
var outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType]; let outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
if (options.bitDepth === 16) { if (options.bitDepth === 16) {
maxValue = 65535; maxValue = 65535;
outBpp *= 2; outBpp *= 2;
} }
var outData = Buffer.alloc(width * height * outBpp); let outData = Buffer.alloc(width * height * outBpp);
var inIndex = 0; let inIndex = 0;
var outIndex = 0; let outIndex = 0;
var bgColor = options.bgColor || {}; let bgColor = options.bgColor || {};
if (bgColor.red === undefined) { if (bgColor.red === undefined) {
bgColor.red = maxValue; bgColor.red = maxValue;
} }
@ -47,10 +50,10 @@ module.exports = function(dataIn, width, height, options) {
} }
function getRGBA() { function getRGBA() {
var red; let red;
var green; let green;
var blue; let blue;
var alpha = maxValue; let alpha = maxValue;
switch (options.inputColorType) { switch (options.inputColorType) {
case constants.COLORTYPE_COLOR_ALPHA: case constants.COLORTYPE_COLOR_ALPHA:
alpha = data[inIndex + 3]; alpha = data[inIndex + 3];
@ -75,23 +78,36 @@ module.exports = function(dataIn, width, height, options) {
blue = red; blue = red;
break; break;
default: default:
throw new Error('input color type:' + options.inputColorType + ' is not supported at present'); throw new Error(
"input color type:" +
options.inputColorType +
" is not supported at present"
);
} }
if (options.inputHasAlpha) { if (options.inputHasAlpha) {
if (!outHasAlpha) { if (!outHasAlpha) {
alpha /= maxValue; alpha /= maxValue;
red = Math.min(Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0), maxValue); red = Math.min(
green = Math.min(Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0), maxValue); Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0),
blue = Math.min(Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0), maxValue); maxValue
);
green = Math.min(
Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0),
maxValue
);
blue = Math.min(
Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0),
maxValue
);
} }
} }
return { red: red, green: green, blue: blue, alpha: alpha }; return { red: red, green: green, blue: blue, alpha: alpha };
} }
for (var y = 0; y < height; y++) { for (let y = 0; y < height; y++) {
for (var x = 0; x < width; x++) { for (let x = 0; x < width; x++) {
var rgba = getRGBA(data, inIndex); let rgba = getRGBA(data, inIndex);
switch (options.colorType) { switch (options.colorType) {
case constants.COLORTYPE_COLOR_ALPHA: case constants.COLORTYPE_COLOR_ALPHA:
@ -103,8 +119,7 @@ module.exports = function(dataIn, width, height, options) {
if (outHasAlpha) { if (outHasAlpha) {
outData[outIndex + 3] = rgba.alpha; outData[outIndex + 3] = rgba.alpha;
} }
} } else {
else {
outData.writeUInt16BE(rgba.red, outIndex); outData.writeUInt16BE(rgba.red, outIndex);
outData.writeUInt16BE(rgba.green, outIndex + 2); outData.writeUInt16BE(rgba.green, outIndex + 2);
outData.writeUInt16BE(rgba.blue, outIndex + 4); outData.writeUInt16BE(rgba.blue, outIndex + 4);
@ -114,24 +129,24 @@ module.exports = function(dataIn, width, height, options) {
} }
break; break;
case constants.COLORTYPE_ALPHA: case constants.COLORTYPE_ALPHA:
case constants.COLORTYPE_GRAYSCALE: case constants.COLORTYPE_GRAYSCALE: {
// Convert to grayscale and alpha // Convert to grayscale and alpha
var grayscale = (rgba.red + rgba.green + rgba.blue) / 3; let grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
if (options.bitDepth === 8) { if (options.bitDepth === 8) {
outData[outIndex] = grayscale; outData[outIndex] = grayscale;
if (outHasAlpha) { if (outHasAlpha) {
outData[outIndex + 1] = rgba.alpha; outData[outIndex + 1] = rgba.alpha;
} }
} } else {
else {
outData.writeUInt16BE(grayscale, outIndex); outData.writeUInt16BE(grayscale, outIndex);
if (outHasAlpha) { if (outHasAlpha) {
outData.writeUInt16BE(rgba.alpha, outIndex + 2); outData.writeUInt16BE(rgba.alpha, outIndex + 2);
} }
} }
break; break;
}
default: default:
throw new Error('unrecognised color Type ' + options.colorType); throw new Error("unrecognised color Type " + options.colorType);
} }
inIndex += inBpp; inIndex += inBpp;

View file

@ -1,11 +1,9 @@
'use strict'; "use strict";
let util = require("util");
let Stream = require("stream");
var util = require('util'); let ChunkStream = (module.exports = function () {
var Stream = require('stream');
var ChunkStream = module.exports = function() {
Stream.call(this); Stream.call(this);
this._buffers = []; this._buffers = [];
@ -14,44 +12,42 @@ var ChunkStream = module.exports = function() {
this._reads = []; this._reads = [];
this._paused = false; this._paused = false;
this._encoding = 'utf8'; this._encoding = "utf8";
this.writable = true; this.writable = true;
}; });
util.inherits(ChunkStream, Stream); util.inherits(ChunkStream, Stream);
ChunkStream.prototype.read = function (length, callback) {
ChunkStream.prototype.read = function(length, callback) {
this._reads.push({ this._reads.push({
length: Math.abs(length), // if length < 0 then at most this length length: Math.abs(length), // if length < 0 then at most this length
allowLess: length < 0, allowLess: length < 0,
func: callback func: callback,
}); });
process.nextTick(function() { process.nextTick(
this._process(); function () {
this._process();
// its paused and there is not enought data then ask for more // its paused and there is not enought data then ask for more
if (this._paused && this._reads.length > 0) { if (this._paused && this._reads.length > 0) {
this._paused = false; this._paused = false;
this.emit('drain'); this.emit("drain");
} }
}.bind(this)); }.bind(this)
);
}; };
ChunkStream.prototype.write = function(data, encoding) { ChunkStream.prototype.write = function (data, encoding) {
if (!this.writable) { if (!this.writable) {
this.emit('error', new Error('Stream not writable')); this.emit("error", new Error("Stream not writable"));
return false; return false;
} }
var dataBuffer; let dataBuffer;
if (Buffer.isBuffer(data)) { if (Buffer.isBuffer(data)) {
dataBuffer = data; dataBuffer = data;
} } else {
else {
dataBuffer = Buffer.from(data, encoding || this._encoding); dataBuffer = Buffer.from(data, encoding || this._encoding);
} }
@ -68,8 +64,7 @@ ChunkStream.prototype.write = function(data, encoding) {
return this.writable && !this._paused; return this.writable && !this._paused;
}; };
ChunkStream.prototype.end = function(data, encoding) { ChunkStream.prototype.end = function (data, encoding) {
if (data) { if (data) {
this.write(data, encoding); this.write(data, encoding);
} }
@ -84,8 +79,7 @@ ChunkStream.prototype.end = function(data, encoding) {
// enqueue or handle end // enqueue or handle end
if (this._buffers.length === 0) { if (this._buffers.length === 0) {
this._end(); this._end();
} } else {
else {
this._buffers.push(null); this._buffers.push(null);
this._process(); this._process();
} }
@ -93,19 +87,15 @@ ChunkStream.prototype.end = function(data, encoding) {
ChunkStream.prototype.destroySoon = ChunkStream.prototype.end; ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
ChunkStream.prototype._end = function() { ChunkStream.prototype._end = function () {
if (this._reads.length > 0) { if (this._reads.length > 0) {
this.emit('error', this.emit("error", new Error("Unexpected end of input"));
new Error('Unexpected end of input')
);
} }
this.destroy(); this.destroy();
}; };
ChunkStream.prototype.destroy = function() { ChunkStream.prototype.destroy = function () {
if (!this._buffers) { if (!this._buffers) {
return; return;
} }
@ -114,26 +104,23 @@ ChunkStream.prototype.destroy = function() {
this._reads = null; this._reads = null;
this._buffers = null; this._buffers = null;
this.emit('close'); this.emit("close");
}; };
ChunkStream.prototype._processReadAllowingLess = function(read) { ChunkStream.prototype._processReadAllowingLess = function (read) {
// ok there is any data so that we can satisfy this request // ok there is any data so that we can satisfy this request
this._reads.shift(); // == read this._reads.shift(); // == read
// first we need to peek into first buffer // first we need to peek into first buffer
var smallerBuf = this._buffers[0]; let smallerBuf = this._buffers[0];
// ok there is more data than we need // ok there is more data than we need
if (smallerBuf.length > read.length) { if (smallerBuf.length > read.length) {
this._buffered -= read.length; this._buffered -= read.length;
this._buffers[0] = smallerBuf.slice(read.length); this._buffers[0] = smallerBuf.slice(read.length);
read.func.call(this, smallerBuf.slice(0, read.length)); read.func.call(this, smallerBuf.slice(0, read.length));
} else {
}
else {
// ok this is less than maximum length so use it all // ok this is less than maximum length so use it all
this._buffered -= smallerBuf.length; this._buffered -= smallerBuf.length;
this._buffers.shift(); // == smallerBuf this._buffers.shift(); // == smallerBuf
@ -142,18 +129,17 @@ ChunkStream.prototype._processReadAllowingLess = function(read) {
} }
}; };
ChunkStream.prototype._processRead = function(read) { ChunkStream.prototype._processRead = function (read) {
this._reads.shift(); // == read this._reads.shift(); // == read
var pos = 0; let pos = 0;
var count = 0; let count = 0;
var data = Buffer.alloc(read.length); let data = Buffer.alloc(read.length);
// create buffer for all data // create buffer for all data
while (pos < read.length) { while (pos < read.length) {
let buf = this._buffers[count++];
var buf = this._buffers[count++]; let len = Math.min(buf.length, read.length - pos);
var len = Math.min(buf.length, read.length - pos);
buf.copy(data, pos, 0, len); buf.copy(data, pos, 0, len);
pos += len; pos += len;
@ -174,25 +160,20 @@ ChunkStream.prototype._processRead = function(read) {
read.func.call(this, data); read.func.call(this, data);
}; };
ChunkStream.prototype._process = function() { ChunkStream.prototype._process = function () {
try { try {
// as long as there is any data and read requests // as long as there is any data and read requests
while (this._buffered > 0 && this._reads && this._reads.length > 0) { while (this._buffered > 0 && this._reads && this._reads.length > 0) {
let read = this._reads[0];
var read = this._reads[0];
// read any data (but no more than length) // read any data (but no more than length)
if (read.allowLess) { if (read.allowLess) {
this._processReadAllowingLess(read); this._processReadAllowingLess(read);
} else if (this._buffered >= read.length) {
}
else if (this._buffered >= read.length) {
// ok we can meet some expectations // ok we can meet some expectations
this._processRead(read); this._processRead(read);
} } else {
else {
// not enought data to satisfy first request in queue // not enought data to satisfy first request in queue
// so we need to wait for more // so we need to wait for more
break; break;
@ -202,8 +183,7 @@ ChunkStream.prototype._process = function() {
if (this._buffers && !this.writable) { if (this._buffers && !this.writable) {
this._end(); this._end();
} }
} } catch (ex) {
catch (ex) { this.emit("error", ex);
this.emit('error', ex);
} }
}; };

View file

@ -1,8 +1,6 @@
'use strict'; "use strict";
module.exports = { module.exports = {
PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
TYPE_IHDR: 0x49484452, TYPE_IHDR: 0x49484452,
@ -27,8 +25,8 @@ module.exports = {
2: 3, 2: 3,
3: 1, 3: 1,
4: 2, 4: 2,
6: 4 6: 4,
}, },
GAMMA_DIVISION: 100000 GAMMA_DIVISION: 100000,
}; };

View file

@ -1,43 +1,39 @@
'use strict'; "use strict";
var crcTable = []; let crcTable = [];
(function() { (function () {
for (var i = 0; i < 256; i++) { for (let i = 0; i < 256; i++) {
var currentCrc = i; let currentCrc = i;
for (var j = 0; j < 8; j++) { for (let j = 0; j < 8; j++) {
if (currentCrc & 1) { if (currentCrc & 1) {
currentCrc = 0xedb88320 ^ (currentCrc >>> 1); currentCrc = 0xedb88320 ^ (currentCrc >>> 1);
} } else {
else {
currentCrc = currentCrc >>> 1; currentCrc = currentCrc >>> 1;
} }
} }
crcTable[i] = currentCrc; crcTable[i] = currentCrc;
} }
}()); })();
var CrcCalculator = module.exports = function() { let CrcCalculator = (module.exports = function () {
this._crc = -1; this._crc = -1;
}; });
CrcCalculator.prototype.write = function(data) { CrcCalculator.prototype.write = function (data) {
for (let i = 0; i < data.length; i++) {
for (var i = 0; i < data.length; i++) {
this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8); this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
} }
return true; return true;
}; };
CrcCalculator.prototype.crc32 = function() { CrcCalculator.prototype.crc32 = function () {
return this._crc ^ -1; return this._crc ^ -1;
}; };
CrcCalculator.crc32 = function (buf) {
CrcCalculator.crc32 = function(buf) { let crc = -1;
for (let i = 0; i < buf.length; i++) {
var crc = -1;
for (var i = 0; i < buf.length; i++) {
crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8); crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
} }
return crc ^ -1; return crc ^ -1;

View file

@ -1,43 +1,37 @@
'use strict'; "use strict";
var paethPredictor = require('./paeth-predictor'); let paethPredictor = require("./paeth-predictor");
function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) { function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) {
for (let x = 0; x < byteWidth; x++) {
for (var x = 0; x < byteWidth; x++) {
rawData[rawPos + x] = pxData[pxPos + x]; rawData[rawPos + x] = pxData[pxPos + x];
} }
} }
function filterSumNone(pxData, pxPos, byteWidth) { function filterSumNone(pxData, pxPos, byteWidth) {
let sum = 0;
let length = pxPos + byteWidth;
var sum = 0; for (let i = pxPos; i < length; i++) {
var length = pxPos + byteWidth;
for (var i = pxPos; i < length; i++) {
sum += Math.abs(pxData[i]); sum += Math.abs(pxData[i]);
} }
return sum; return sum;
} }
function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) { function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
for (let x = 0; x < byteWidth; x++) {
for (var x = 0; x < byteWidth; x++) { let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
let val = pxData[pxPos + x] - left;
var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
var val = pxData[pxPos + x] - left;
rawData[rawPos + x] = val; rawData[rawPos + x] = val;
} }
} }
function filterSumSub(pxData, pxPos, byteWidth, bpp) { function filterSumSub(pxData, pxPos, byteWidth, bpp) {
let sum = 0;
var sum = 0; for (let x = 0; x < byteWidth; x++) {
for (var x = 0; x < byteWidth; x++) { let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
let val = pxData[pxPos + x] - left;
var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
var val = pxData[pxPos + x] - left;
sum += Math.abs(val); sum += Math.abs(val);
} }
@ -46,24 +40,20 @@ function filterSumSub(pxData, pxPos, byteWidth, bpp) {
} }
function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) { function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) {
for (let x = 0; x < byteWidth; x++) {
for (var x = 0; x < byteWidth; x++) { let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
let val = pxData[pxPos + x] - up;
var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
var val = pxData[pxPos + x] - up;
rawData[rawPos + x] = val; rawData[rawPos + x] = val;
} }
} }
function filterSumUp(pxData, pxPos, byteWidth) { function filterSumUp(pxData, pxPos, byteWidth) {
let sum = 0;
var sum = 0; let length = pxPos + byteWidth;
var length = pxPos + byteWidth; for (let x = pxPos; x < length; x++) {
for (var x = pxPos; x < length; x++) { let up = pxPos > 0 ? pxData[x - byteWidth] : 0;
let val = pxData[x] - up;
var up = pxPos > 0 ? pxData[x - byteWidth] : 0;
var val = pxData[x] - up;
sum += Math.abs(val); sum += Math.abs(val);
} }
@ -72,25 +62,21 @@ function filterSumUp(pxData, pxPos, byteWidth) {
} }
function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) { function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
for (let x = 0; x < byteWidth; x++) {
for (var x = 0; x < byteWidth; x++) { let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
var left = x >= bpp ? pxData[pxPos + x - bpp] : 0; let val = pxData[pxPos + x] - ((left + up) >> 1);
var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
var val = pxData[pxPos + x] - ((left + up) >> 1);
rawData[rawPos + x] = val; rawData[rawPos + x] = val;
} }
} }
function filterSumAvg(pxData, pxPos, byteWidth, bpp) { function filterSumAvg(pxData, pxPos, byteWidth, bpp) {
let sum = 0;
var sum = 0; for (let x = 0; x < byteWidth; x++) {
for (var x = 0; x < byteWidth; x++) { let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
var left = x >= bpp ? pxData[pxPos + x - bpp] : 0; let val = pxData[pxPos + x] - ((left + up) >> 1);
var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
var val = pxData[pxPos + x] - ((left + up) >> 1);
sum += Math.abs(val); sum += Math.abs(val);
} }
@ -99,26 +85,25 @@ function filterSumAvg(pxData, pxPos, byteWidth, bpp) {
} }
function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) { function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
for (let x = 0; x < byteWidth; x++) {
for (var x = 0; x < byteWidth; x++) { let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
var left = x >= bpp ? pxData[pxPos + x - bpp] : 0; let upleft =
var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
var upleft = pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0; let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
var val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
rawData[rawPos + x] = val; rawData[rawPos + x] = val;
} }
} }
function filterSumPaeth(pxData, pxPos, byteWidth, bpp) { function filterSumPaeth(pxData, pxPos, byteWidth, bpp) {
var sum = 0; let sum = 0;
for (var x = 0; x < byteWidth; x++) { for (let x = 0; x < byteWidth; x++) {
let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
var left = x >= bpp ? pxData[pxPos + x - bpp] : 0; let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0; let upleft =
var upleft = pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0; pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
var val = pxData[pxPos + x] - paethPredictor(left, up, upleft); let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
sum += Math.abs(val); sum += Math.abs(val);
} }
@ -126,53 +111,49 @@ function filterSumPaeth(pxData, pxPos, byteWidth, bpp) {
return sum; return sum;
} }
var filters = { let filters = {
0: filterNone, 0: filterNone,
1: filterSub, 1: filterSub,
2: filterUp, 2: filterUp,
3: filterAvg, 3: filterAvg,
4: filterPaeth 4: filterPaeth,
}; };
var filterSums = { let filterSums = {
0: filterSumNone, 0: filterSumNone,
1: filterSumSub, 1: filterSumSub,
2: filterSumUp, 2: filterSumUp,
3: filterSumAvg, 3: filterSumAvg,
4: filterSumPaeth 4: filterSumPaeth,
}; };
module.exports = function(pxData, width, height, options, bpp) { module.exports = function (pxData, width, height, options, bpp) {
let filterTypes;
var filterTypes; if (!("filterType" in options) || options.filterType === -1) {
if (!('filterType' in options) || options.filterType === -1) {
filterTypes = [0, 1, 2, 3, 4]; filterTypes = [0, 1, 2, 3, 4];
} } else if (typeof options.filterType === "number") {
else if (typeof options.filterType === 'number') {
filterTypes = [options.filterType]; filterTypes = [options.filterType];
} } else {
else { throw new Error("unrecognised filter types");
throw new Error('unrecognised filter types');
} }
if (options.bitDepth === 16) { if (options.bitDepth === 16) {
bpp *= 2; bpp *= 2;
} }
var byteWidth = width * bpp; let byteWidth = width * bpp;
var rawPos = 0; let rawPos = 0;
var pxPos = 0; let pxPos = 0;
var rawData = Buffer.alloc((byteWidth + 1) * height); let rawData = Buffer.alloc((byteWidth + 1) * height);
var sel = filterTypes[0]; let sel = filterTypes[0];
for (var y = 0; y < height; y++) {
for (let y = 0; y < height; y++) {
if (filterTypes.length > 1) { if (filterTypes.length > 1) {
// find best filter for this line (with lowest sum of values) // find best filter for this line (with lowest sum of values)
var min = Infinity; let min = Infinity;
for (var i = 0; i < filterTypes.length; i++) { for (let i = 0; i < filterTypes.length; i++) {
var sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp); let sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp);
if (sum < min) { if (sum < min) {
sel = filterTypes[i]; sel = filterTypes[i];
min = sum; min = sum;

View file

@ -1,25 +1,24 @@
'use strict'; "use strict";
var util = require('util'); let util = require("util");
var ChunkStream = require('./chunkstream'); let ChunkStream = require("./chunkstream");
var Filter = require('./filter-parse'); let Filter = require("./filter-parse");
let FilterAsync = (module.exports = function (bitmapInfo) {
var FilterAsync = module.exports = function(bitmapInfo) {
ChunkStream.call(this); ChunkStream.call(this);
var buffers = []; let buffers = [];
var that = this; let that = this;
this._filter = new Filter(bitmapInfo, { this._filter = new Filter(bitmapInfo, {
read: this.read.bind(this), read: this.read.bind(this),
write: function(buffer) { write: function (buffer) {
buffers.push(buffer); buffers.push(buffer);
}, },
complete: function() { complete: function () {
that.emit('complete', Buffer.concat(buffers)); that.emit("complete", Buffer.concat(buffers));
} },
}); });
this._filter.start(); this._filter.start();
}; });
util.inherits(FilterAsync, ChunkStream); util.inherits(FilterAsync, ChunkStream);

View file

@ -1,24 +1,21 @@
'use strict'; "use strict";
var SyncReader = require('./sync-reader'); let SyncReader = require("./sync-reader");
var Filter = require('./filter-parse'); let Filter = require("./filter-parse");
exports.process = function (inBuffer, bitmapInfo) {
exports.process = function(inBuffer, bitmapInfo) { let outBuffers = [];
let reader = new SyncReader(inBuffer);
var outBuffers = []; let filter = new Filter(bitmapInfo, {
var reader = new SyncReader(inBuffer);
var filter = new Filter(bitmapInfo, {
read: reader.read.bind(reader), read: reader.read.bind(reader),
write: function(bufferPart) { write: function (bufferPart) {
outBuffers.push(bufferPart); outBuffers.push(bufferPart);
}, },
complete: function() { complete: function () {},
}
}); });
filter.start(); filter.start();
reader.process(); reader.process();
return Buffer.concat(outBuffers); return Buffer.concat(outBuffers);
}; };

View file

@ -1,23 +1,22 @@
'use strict'; "use strict";
var interlaceUtils = require('./interlace'); let interlaceUtils = require("./interlace");
var paethPredictor = require('./paeth-predictor'); let paethPredictor = require("./paeth-predictor");
function getByteWidth(width, bpp, depth) { function getByteWidth(width, bpp, depth) {
var byteWidth = width * bpp; let byteWidth = width * bpp;
if (depth !== 8) { if (depth !== 8) {
byteWidth = Math.ceil(byteWidth / (8 / depth)); byteWidth = Math.ceil(byteWidth / (8 / depth));
} }
return byteWidth; return byteWidth;
} }
var Filter = module.exports = function(bitmapInfo, dependencies) { let Filter = (module.exports = function (bitmapInfo, dependencies) {
let width = bitmapInfo.width;
var width = bitmapInfo.width; let height = bitmapInfo.height;
var height = bitmapInfo.height; let interlace = bitmapInfo.interlace;
var interlace = bitmapInfo.interlace; let bpp = bitmapInfo.bpp;
var bpp = bitmapInfo.bpp; let depth = bitmapInfo.depth;
var depth = bitmapInfo.depth;
this.read = dependencies.read; this.read = dependencies.read;
this.write = dependencies.write; this.write = dependencies.write;
@ -26,20 +25,19 @@ var Filter = module.exports = function(bitmapInfo, dependencies) {
this._imageIndex = 0; this._imageIndex = 0;
this._images = []; this._images = [];
if (interlace) { if (interlace) {
var passes = interlaceUtils.getImagePasses(width, height); let passes = interlaceUtils.getImagePasses(width, height);
for (var i = 0; i < passes.length; i++) { for (let i = 0; i < passes.length; i++) {
this._images.push({ this._images.push({
byteWidth: getByteWidth(passes[i].width, bpp, depth), byteWidth: getByteWidth(passes[i].width, bpp, depth),
height: passes[i].height, height: passes[i].height,
lineIndex: 0 lineIndex: 0,
}); });
} }
} } else {
else {
this._images.push({ this._images.push({
byteWidth: getByteWidth(width, bpp, depth), byteWidth: getByteWidth(width, bpp, depth),
height: height, height: height,
lineIndex: 0 lineIndex: 0,
}); });
} }
@ -49,85 +47,95 @@ var Filter = module.exports = function(bitmapInfo, dependencies) {
// a pixel rather than just a different byte part. However if we are sub byte, we ignore. // a pixel rather than just a different byte part. However if we are sub byte, we ignore.
if (depth === 8) { if (depth === 8) {
this._xComparison = bpp; this._xComparison = bpp;
} } else if (depth === 16) {
else if (depth === 16) {
this._xComparison = bpp * 2; this._xComparison = bpp * 2;
} } else {
else {
this._xComparison = 1; this._xComparison = 1;
} }
});
Filter.prototype.start = function () {
this.read(
this._images[this._imageIndex].byteWidth + 1,
this._reverseFilterLine.bind(this)
);
}; };
Filter.prototype.start = function() { Filter.prototype._unFilterType1 = function (
this.read(this._images[this._imageIndex].byteWidth + 1, this._reverseFilterLine.bind(this)); rawData,
}; unfilteredLine,
byteWidth
) {
let xComparison = this._xComparison;
let xBiggerThan = xComparison - 1;
Filter.prototype._unFilterType1 = function(rawData, unfilteredLine, byteWidth) { for (let x = 0; x < byteWidth; x++) {
let rawByte = rawData[1 + x];
var xComparison = this._xComparison; let f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
var xBiggerThan = xComparison - 1;
for (var x = 0; x < byteWidth; x++) {
var rawByte = rawData[1 + x];
var f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
unfilteredLine[x] = rawByte + f1Left; unfilteredLine[x] = rawByte + f1Left;
} }
}; };
Filter.prototype._unFilterType2 = function(rawData, unfilteredLine, byteWidth) { Filter.prototype._unFilterType2 = function (
rawData,
unfilteredLine,
byteWidth
) {
let lastLine = this._lastLine;
var lastLine = this._lastLine; for (let x = 0; x < byteWidth; x++) {
let rawByte = rawData[1 + x];
for (var x = 0; x < byteWidth; x++) { let f2Up = lastLine ? lastLine[x] : 0;
var rawByte = rawData[1 + x];
var f2Up = lastLine ? lastLine[x] : 0;
unfilteredLine[x] = rawByte + f2Up; unfilteredLine[x] = rawByte + f2Up;
} }
}; };
Filter.prototype._unFilterType3 = function(rawData, unfilteredLine, byteWidth) { Filter.prototype._unFilterType3 = function (
rawData,
unfilteredLine,
byteWidth
) {
let xComparison = this._xComparison;
let xBiggerThan = xComparison - 1;
let lastLine = this._lastLine;
var xComparison = this._xComparison; for (let x = 0; x < byteWidth; x++) {
var xBiggerThan = xComparison - 1; let rawByte = rawData[1 + x];
var lastLine = this._lastLine; let f3Up = lastLine ? lastLine[x] : 0;
let f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
for (var x = 0; x < byteWidth; x++) { let f3Add = Math.floor((f3Left + f3Up) / 2);
var rawByte = rawData[1 + x];
var f3Up = lastLine ? lastLine[x] : 0;
var f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
var f3Add = Math.floor((f3Left + f3Up) / 2);
unfilteredLine[x] = rawByte + f3Add; unfilteredLine[x] = rawByte + f3Add;
} }
}; };
Filter.prototype._unFilterType4 = function(rawData, unfilteredLine, byteWidth) { Filter.prototype._unFilterType4 = function (
rawData,
unfilteredLine,
byteWidth
) {
let xComparison = this._xComparison;
let xBiggerThan = xComparison - 1;
let lastLine = this._lastLine;
var xComparison = this._xComparison; for (let x = 0; x < byteWidth; x++) {
var xBiggerThan = xComparison - 1; let rawByte = rawData[1 + x];
var lastLine = this._lastLine; let f4Up = lastLine ? lastLine[x] : 0;
let f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
for (var x = 0; x < byteWidth; x++) { let f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0;
var rawByte = rawData[1 + x]; let f4Add = paethPredictor(f4Left, f4Up, f4UpLeft);
var f4Up = lastLine ? lastLine[x] : 0;
var f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
var f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0;
var f4Add = paethPredictor(f4Left, f4Up, f4UpLeft);
unfilteredLine[x] = rawByte + f4Add; unfilteredLine[x] = rawByte + f4Add;
} }
}; };
Filter.prototype._reverseFilterLine = function(rawData) { Filter.prototype._reverseFilterLine = function (rawData) {
let filter = rawData[0];
var filter = rawData[0]; let unfilteredLine;
var unfilteredLine; let currentImage = this._images[this._imageIndex];
var currentImage = this._images[this._imageIndex]; let byteWidth = currentImage.byteWidth;
var byteWidth = currentImage.byteWidth;
if (filter === 0) { if (filter === 0) {
unfilteredLine = rawData.slice(1, byteWidth + 1); unfilteredLine = rawData.slice(1, byteWidth + 1);
} } else {
else {
unfilteredLine = Buffer.alloc(byteWidth); unfilteredLine = Buffer.alloc(byteWidth);
switch (filter) { switch (filter) {
@ -144,7 +152,7 @@ Filter.prototype._reverseFilterLine = function(rawData) {
this._unFilterType4(rawData, unfilteredLine, byteWidth); this._unFilterType4(rawData, unfilteredLine, byteWidth);
break; break;
default: default:
throw new Error('Unrecognised filter type - ' + filter); throw new Error("Unrecognised filter type - " + filter);
} }
} }
@ -155,16 +163,14 @@ Filter.prototype._reverseFilterLine = function(rawData) {
this._lastLine = null; this._lastLine = null;
this._imageIndex++; this._imageIndex++;
currentImage = this._images[this._imageIndex]; currentImage = this._images[this._imageIndex];
} } else {
else {
this._lastLine = unfilteredLine; this._lastLine = unfilteredLine;
} }
if (currentImage) { if (currentImage) {
// read, using the byte width that may be from the new current image // read, using the byte width that may be from the new current image
this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this)); this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
} } else {
else {
this._lastLine = null; this._lastLine = null;
this.complete(); this.complete();
} }

View file

@ -1,17 +1,17 @@
'use strict'; "use strict";
function dePalette(indata, outdata, width, height, palette) { function dePalette(indata, outdata, width, height, palette) {
var pxPos = 0; let pxPos = 0;
// use values from palette // use values from palette
for (var y = 0; y < height; y++) { for (let y = 0; y < height; y++) {
for (var x = 0; x < width; x++) { for (let x = 0; x < width; x++) {
var color = palette[indata[pxPos]]; let color = palette[indata[pxPos]];
if (!color) { if (!color) {
throw new Error('index ' + indata[pxPos] + ' not in palette'); throw new Error("index " + indata[pxPos] + " not in palette");
} }
for (var i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
outdata[pxPos + i] = color[i]; outdata[pxPos + i] = color[i];
} }
pxPos += 4; pxPos += 4;
@ -20,21 +20,24 @@ function dePalette(indata, outdata, width, height, palette) {
} }
function replaceTransparentColor(indata, outdata, width, height, transColor) { function replaceTransparentColor(indata, outdata, width, height, transColor) {
var pxPos = 0; let pxPos = 0;
for (var y = 0; y < height; y++) { for (let y = 0; y < height; y++) {
for (var x = 0; x < width; x++) { for (let x = 0; x < width; x++) {
var makeTrans = false; let makeTrans = false;
if (transColor.length === 1) { if (transColor.length === 1) {
if (transColor[0] === indata[pxPos]) { if (transColor[0] === indata[pxPos]) {
makeTrans = true; makeTrans = true;
} }
} } else if (
else if (transColor[0] === indata[pxPos] && transColor[1] === indata[pxPos + 1] && transColor[2] === indata[pxPos + 2]) { transColor[0] === indata[pxPos] &&
transColor[1] === indata[pxPos + 1] &&
transColor[2] === indata[pxPos + 2]
) {
makeTrans = true; makeTrans = true;
} }
if (makeTrans) { if (makeTrans) {
for (var i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
outdata[pxPos + i] = 0; outdata[pxPos + i] = 0;
} }
} }
@ -44,35 +47,36 @@ function replaceTransparentColor(indata, outdata, width, height, transColor) {
} }
function scaleDepth(indata, outdata, width, height, depth) { function scaleDepth(indata, outdata, width, height, depth) {
var maxOutSample = 255; let maxOutSample = 255;
var maxInSample = Math.pow(2, depth) - 1; let maxInSample = Math.pow(2, depth) - 1;
var pxPos = 0; let pxPos = 0;
for (var y = 0; y < height; y++) { for (let y = 0; y < height; y++) {
for (var x = 0; x < width; x++) { for (let x = 0; x < width; x++) {
for (var i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
outdata[pxPos + i] = Math.floor((indata[pxPos + i] * maxOutSample) / maxInSample + 0.5); outdata[pxPos + i] = Math.floor(
(indata[pxPos + i] * maxOutSample) / maxInSample + 0.5
);
} }
pxPos += 4; pxPos += 4;
} }
} }
} }
module.exports = function(indata, imageData) { module.exports = function (indata, imageData) {
let depth = imageData.depth;
let width = imageData.width;
let height = imageData.height;
let colorType = imageData.colorType;
let transColor = imageData.transColor;
let palette = imageData.palette;
var depth = imageData.depth; let outdata = indata; // only different for 16 bits
var width = imageData.width;
var height = imageData.height;
var colorType = imageData.colorType;
var transColor = imageData.transColor;
var palette = imageData.palette;
var outdata = indata; // only different for 16 bits if (colorType === 3) {
// paletted
if (colorType === 3) { // paletted
dePalette(indata, outdata, width, height, palette); dePalette(indata, outdata, width, height, palette);
} } else {
else {
if (transColor) { if (transColor) {
replaceTransparentColor(indata, outdata, width, height, transColor); replaceTransparentColor(indata, outdata, width, height, transColor);
} }

View file

@ -1,4 +1,4 @@
'use strict'; "use strict";
// Adam 7 // Adam 7
// 0 1 2 3 4 5 6 7 // 0 1 2 3 4 5 6 7
@ -11,61 +11,65 @@
// 6 5 6 5 6 5 6 5 6 // 6 5 6 5 6 5 6 5 6
// 7 7 7 7 7 7 7 7 7 // 7 7 7 7 7 7 7 7 7
let imagePasses = [
var imagePasses = [ {
{ // pass 1 - 1px // pass 1 - 1px
x: [0], x: [0],
y: [0] y: [0],
}, },
{ // pass 2 - 1px {
// pass 2 - 1px
x: [4], x: [4],
y: [0] y: [0],
}, },
{ // pass 3 - 2px {
// pass 3 - 2px
x: [0, 4], x: [0, 4],
y: [4] y: [4],
}, },
{ // pass 4 - 4px {
// pass 4 - 4px
x: [2, 6], x: [2, 6],
y: [0, 4] y: [0, 4],
}, },
{ // pass 5 - 8px {
// pass 5 - 8px
x: [0, 2, 4, 6], x: [0, 2, 4, 6],
y: [2, 6] y: [2, 6],
}, },
{ // pass 6 - 16px {
// pass 6 - 16px
x: [1, 3, 5, 7], x: [1, 3, 5, 7],
y: [0, 2, 4, 6] y: [0, 2, 4, 6],
}, },
{ // pass 7 - 32px {
// pass 7 - 32px
x: [0, 1, 2, 3, 4, 5, 6, 7], x: [0, 1, 2, 3, 4, 5, 6, 7],
y: [1, 3, 5, 7] y: [1, 3, 5, 7],
} },
]; ];
exports.getImagePasses = function(width, height) { exports.getImagePasses = function (width, height) {
var images = []; let images = [];
var xLeftOver = width % 8; let xLeftOver = width % 8;
var yLeftOver = height % 8; let yLeftOver = height % 8;
var xRepeats = (width - xLeftOver) / 8; let xRepeats = (width - xLeftOver) / 8;
var yRepeats = (height - yLeftOver) / 8; let yRepeats = (height - yLeftOver) / 8;
for (var i = 0; i < imagePasses.length; i++) { for (let i = 0; i < imagePasses.length; i++) {
var pass = imagePasses[i]; let pass = imagePasses[i];
var passWidth = xRepeats * pass.x.length; let passWidth = xRepeats * pass.x.length;
var passHeight = yRepeats * pass.y.length; let passHeight = yRepeats * pass.y.length;
for (var j = 0; j < pass.x.length; j++) { for (let j = 0; j < pass.x.length; j++) {
if (pass.x[j] < xLeftOver) { if (pass.x[j] < xLeftOver) {
passWidth++; passWidth++;
} } else {
else {
break; break;
} }
} }
for (j = 0; j < pass.y.length; j++) { for (let j = 0; j < pass.y.length; j++) {
if (pass.y[j] < yLeftOver) { if (pass.y[j] < yLeftOver) {
passHeight++; passHeight++;
} } else {
else {
break; break;
} }
} }
@ -76,12 +80,16 @@ exports.getImagePasses = function(width, height) {
return images; return images;
}; };
exports.getInterlaceIterator = function(width) { exports.getInterlaceIterator = function (width) {
return function(x, y, pass) { return function (x, y, pass) {
var outerXLeftOver = x % imagePasses[pass].x.length; let outerXLeftOver = x % imagePasses[pass].x.length;
var outerX = (((x - outerXLeftOver) / imagePasses[pass].x.length) * 8) + imagePasses[pass].x[outerXLeftOver]; let outerX =
var outerYLeftOver = y % imagePasses[pass].y.length; ((x - outerXLeftOver) / imagePasses[pass].x.length) * 8 +
var outerY = (((y - outerYLeftOver) / imagePasses[pass].y.length) * 8) + imagePasses[pass].y[outerYLeftOver]; imagePasses[pass].x[outerXLeftOver];
return (outerX * 4) + (outerY * width * 4); let outerYLeftOver = y % imagePasses[pass].y.length;
let outerY =
((y - outerYLeftOver) / imagePasses[pass].y.length) * 8 +
imagePasses[pass].y[outerYLeftOver];
return outerX * 4 + outerY * width * 4;
}; };
}; };

View file

@ -1,45 +1,50 @@
'use strict'; "use strict";
var util = require('util'); let util = require("util");
var Stream = require('stream'); let Stream = require("stream");
var constants = require('./constants'); let constants = require("./constants");
var Packer = require('./packer'); let Packer = require("./packer");
var PackerAsync = module.exports = function(opt) { let PackerAsync = (module.exports = function (opt) {
Stream.call(this); Stream.call(this);
var options = opt || {}; let options = opt || {};
this._packer = new Packer(options); this._packer = new Packer(options);
this._deflate = this._packer.createDeflate(); this._deflate = this._packer.createDeflate();
this.readable = true; this.readable = true;
}; });
util.inherits(PackerAsync, Stream); util.inherits(PackerAsync, Stream);
PackerAsync.prototype.pack = function (data, width, height, gamma) {
PackerAsync.prototype.pack = function(data, width, height, gamma) {
// Signature // Signature
this.emit('data', Buffer.from(constants.PNG_SIGNATURE)); this.emit("data", Buffer.from(constants.PNG_SIGNATURE));
this.emit('data', this._packer.packIHDR(width, height)); this.emit("data", this._packer.packIHDR(width, height));
if (gamma) { if (gamma) {
this.emit('data', this._packer.packGAMA(gamma)); this.emit("data", this._packer.packGAMA(gamma));
} }
var filteredData = this._packer.filterData(data, width, height); let filteredData = this._packer.filterData(data, width, height);
// compress it // compress it
this._deflate.on('error', this.emit.bind(this, 'error')); this._deflate.on("error", this.emit.bind(this, "error"));
this._deflate.on('data', function(compressedData) { this._deflate.on(
this.emit('data', this._packer.packIDAT(compressedData)); "data",
}.bind(this)); function (compressedData) {
this.emit("data", this._packer.packIDAT(compressedData));
}.bind(this)
);
this._deflate.on('end', function() { this._deflate.on(
this.emit('data', this._packer.packIEND()); "end",
this.emit('end'); function () {
}.bind(this)); this.emit("data", this._packer.packIEND());
this.emit("end");
}.bind(this)
);
this._deflate.end(filteredData); this._deflate.end(filteredData);
}; };

View file

@ -1,24 +1,25 @@
'use strict'; "use strict";
var hasSyncZlib = true; let hasSyncZlib = true;
var zlib = require('zlib'); let zlib = require("zlib");
if (!zlib.deflateSync) { if (!zlib.deflateSync) {
hasSyncZlib = false; hasSyncZlib = false;
} }
var constants = require('./constants'); let constants = require("./constants");
var Packer = require('./packer'); let Packer = require("./packer");
module.exports = function(metaData, opt) {
module.exports = function (metaData, opt) {
if (!hasSyncZlib) { if (!hasSyncZlib) {
throw new Error('To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0'); throw new Error(
"To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
);
} }
var options = opt || {}; let options = opt || {};
var packer = new Packer(options); let packer = new Packer(options);
var chunks = []; let chunks = [];
// Signature // Signature
chunks.push(Buffer.from(constants.PNG_SIGNATURE)); chunks.push(Buffer.from(constants.PNG_SIGNATURE));
@ -30,14 +31,21 @@ module.exports = function(metaData, opt) {
chunks.push(packer.packGAMA(metaData.gamma)); chunks.push(packer.packGAMA(metaData.gamma));
} }
var filteredData = packer.filterData(metaData.data, metaData.width, metaData.height); let filteredData = packer.filterData(
metaData.data,
metaData.width,
metaData.height
);
// compress it // compress it
var compressedData = zlib.deflateSync(filteredData, packer.getDeflateOptions()); let compressedData = zlib.deflateSync(
filteredData,
packer.getDeflateOptions()
);
filteredData = null; filteredData = null;
if (!compressedData || !compressedData.length) { if (!compressedData || !compressedData.length) {
throw new Error('bad png - invalid compressed data response'); throw new Error("bad png - invalid compressed data response");
} }
chunks.push(packer.packIDAT(compressedData)); chunks.push(packer.packIDAT(compressedData));

View file

@ -1,71 +1,91 @@
'use strict'; "use strict";
var constants = require('./constants'); let constants = require("./constants");
var CrcStream = require('./crc'); let CrcStream = require("./crc");
var bitPacker = require('./bitpacker'); let bitPacker = require("./bitpacker");
var filter = require('./filter-pack'); let filter = require("./filter-pack");
var zlib = require('zlib'); let zlib = require("zlib");
var Packer = module.exports = function(options) { let Packer = (module.exports = function (options) {
this._options = options; this._options = options;
options.deflateChunkSize = options.deflateChunkSize || 32 * 1024; options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9; options.deflateLevel =
options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3; options.deflateLevel != null ? options.deflateLevel : 9;
options.inputHasAlpha = options.inputHasAlpha != null ? options.inputHasAlpha : true; options.deflateStrategy =
options.deflateStrategy != null ? options.deflateStrategy : 3;
options.inputHasAlpha =
options.inputHasAlpha != null ? options.inputHasAlpha : true;
options.deflateFactory = options.deflateFactory || zlib.createDeflate; options.deflateFactory = options.deflateFactory || zlib.createDeflate;
options.bitDepth = options.bitDepth || 8; options.bitDepth = options.bitDepth || 8;
// This is outputColorType // This is outputColorType
options.colorType = (typeof options.colorType === 'number') ? options.colorType : constants.COLORTYPE_COLOR_ALPHA; options.colorType =
options.inputColorType = (typeof options.inputColorType === 'number') ? options.inputColorType : constants.COLORTYPE_COLOR_ALPHA; typeof options.colorType === "number"
? options.colorType
: constants.COLORTYPE_COLOR_ALPHA;
options.inputColorType =
typeof options.inputColorType === "number"
? options.inputColorType
: constants.COLORTYPE_COLOR_ALPHA;
if ([ if (
constants.COLORTYPE_GRAYSCALE, [
constants.COLORTYPE_COLOR, constants.COLORTYPE_GRAYSCALE,
constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_COLOR,
constants.COLORTYPE_ALPHA constants.COLORTYPE_COLOR_ALPHA,
].indexOf(options.colorType) === -1) { constants.COLORTYPE_ALPHA,
throw new Error('option color type:' + options.colorType + ' is not supported at present'); ].indexOf(options.colorType) === -1
) {
throw new Error(
"option color type:" + options.colorType + " is not supported at present"
);
} }
if ([ if (
constants.COLORTYPE_GRAYSCALE, [
constants.COLORTYPE_COLOR, constants.COLORTYPE_GRAYSCALE,
constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_COLOR,
constants.COLORTYPE_ALPHA constants.COLORTYPE_COLOR_ALPHA,
].indexOf(options.inputColorType) === -1) { constants.COLORTYPE_ALPHA,
throw new Error('option input color type:' + options.inputColorType + ' is not supported at present'); ].indexOf(options.inputColorType) === -1
) {
throw new Error(
"option input color type:" +
options.inputColorType +
" is not supported at present"
);
} }
if (options.bitDepth !== 8 && options.bitDepth !== 16) { if (options.bitDepth !== 8 && options.bitDepth !== 16) {
throw new Error('option bit depth:' + options.bitDepth + ' is not supported at present'); throw new Error(
"option bit depth:" + options.bitDepth + " is not supported at present"
);
} }
}; });
Packer.prototype.getDeflateOptions = function() { Packer.prototype.getDeflateOptions = function () {
return { return {
chunkSize: this._options.deflateChunkSize, chunkSize: this._options.deflateChunkSize,
level: this._options.deflateLevel, level: this._options.deflateLevel,
strategy: this._options.deflateStrategy strategy: this._options.deflateStrategy,
}; };
}; };
Packer.prototype.createDeflate = function() { Packer.prototype.createDeflate = function () {
return this._options.deflateFactory(this.getDeflateOptions()); return this._options.deflateFactory(this.getDeflateOptions());
}; };
Packer.prototype.filterData = function(data, width, height) { Packer.prototype.filterData = function (data, width, height) {
// convert to correct format for filtering (e.g. right bpp and bit depth) // convert to correct format for filtering (e.g. right bpp and bit depth)
var packedData = bitPacker(data, width, height, this._options); let packedData = bitPacker(data, width, height, this._options);
// filter pixel data // filter pixel data
var bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType]; let bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
var filteredData = filter(packedData, width, height, this._options, bpp); let filteredData = filter(packedData, width, height, this._options, bpp);
return filteredData; return filteredData;
}; };
Packer.prototype._packChunk = function(type, data) { Packer.prototype._packChunk = function (type, data) {
let len = data ? data.length : 0;
var len = (data ? data.length : 0); let buf = Buffer.alloc(len + 12);
var buf = Buffer.alloc(len + 12);
buf.writeUInt32BE(len, 0); buf.writeUInt32BE(len, 0);
buf.writeUInt32BE(type, 4); buf.writeUInt32BE(type, 4);
@ -74,19 +94,21 @@ Packer.prototype._packChunk = function(type, data) {
data.copy(buf, 8); data.copy(buf, 8);
} }
buf.writeInt32BE(CrcStream.crc32(buf.slice(4, buf.length - 4)), buf.length - 4); buf.writeInt32BE(
CrcStream.crc32(buf.slice(4, buf.length - 4)),
buf.length - 4
);
return buf; return buf;
}; };
Packer.prototype.packGAMA = function(gamma) { Packer.prototype.packGAMA = function (gamma) {
var buf = Buffer.alloc(4); let buf = Buffer.alloc(4);
buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0); buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
return this._packChunk(constants.TYPE_gAMA, buf); return this._packChunk(constants.TYPE_gAMA, buf);
}; };
Packer.prototype.packIHDR = function(width, height) { Packer.prototype.packIHDR = function (width, height) {
let buf = Buffer.alloc(13);
var buf = Buffer.alloc(13);
buf.writeUInt32BE(width, 0); buf.writeUInt32BE(width, 0);
buf.writeUInt32BE(height, 4); buf.writeUInt32BE(height, 4);
buf[8] = this._options.bitDepth; // Bit depth buf[8] = this._options.bitDepth; // Bit depth
@ -98,10 +120,10 @@ Packer.prototype.packIHDR = function(width, height) {
return this._packChunk(constants.TYPE_IHDR, buf); return this._packChunk(constants.TYPE_IHDR, buf);
}; };
Packer.prototype.packIDAT = function(data) { Packer.prototype.packIDAT = function (data) {
return this._packChunk(constants.TYPE_IDAT, data); return this._packChunk(constants.TYPE_IDAT, data);
}; };
Packer.prototype.packIEND = function() { Packer.prototype.packIEND = function () {
return this._packChunk(constants.TYPE_IEND, null); return this._packChunk(constants.TYPE_IEND, null);
}; };

View file

@ -1,17 +1,16 @@
'use strict'; "use strict";
module.exports = function paethPredictor(left, above, upLeft) { module.exports = function paethPredictor(left, above, upLeft) {
let paeth = left + above - upLeft;
var paeth = left + above - upLeft; let pLeft = Math.abs(paeth - left);
var pLeft = Math.abs(paeth - left); let pAbove = Math.abs(paeth - above);
var pAbove = Math.abs(paeth - above); let pUpLeft = Math.abs(paeth - upLeft);
var pUpLeft = Math.abs(paeth - upLeft);
if (pLeft <= pAbove && pLeft <= pUpLeft) {
if (pLeft <= pAbove && pLeft <= pUpLeft) { return left;
return left; }
} if (pAbove <= pUpLeft) {
if (pAbove <= pUpLeft) { return above;
return above; }
} return upLeft;
return upLeft; };
};

View file

@ -1,39 +1,37 @@
'use strict'; "use strict";
var util = require('util'); let util = require("util");
var zlib = require('zlib'); let zlib = require("zlib");
var ChunkStream = require('./chunkstream'); let ChunkStream = require("./chunkstream");
var FilterAsync = require('./filter-parse-async'); let FilterAsync = require("./filter-parse-async");
var Parser = require('./parser'); let Parser = require("./parser");
var bitmapper = require('./bitmapper'); let bitmapper = require("./bitmapper");
var formatNormaliser = require('./format-normaliser'); let formatNormaliser = require("./format-normaliser");
var ParserAsync = module.exports = function(options) { let ParserAsync = (module.exports = function (options) {
ChunkStream.call(this); ChunkStream.call(this);
this._parser = new Parser(options, { this._parser = new Parser(options, {
read: this.read.bind(this), read: this.read.bind(this),
error: this._handleError.bind(this), error: this._handleError.bind(this),
metadata: this._handleMetaData.bind(this), metadata: this._handleMetaData.bind(this),
gamma: this.emit.bind(this, 'gamma'), gamma: this.emit.bind(this, "gamma"),
palette: this._handlePalette.bind(this), palette: this._handlePalette.bind(this),
transColor: this._handleTransColor.bind(this), transColor: this._handleTransColor.bind(this),
finished: this._finished.bind(this), finished: this._finished.bind(this),
inflateData: this._inflateData.bind(this), inflateData: this._inflateData.bind(this),
simpleTransparency: this._simpleTransparency.bind(this), simpleTransparency: this._simpleTransparency.bind(this),
headersFinished: this._headersFinished.bind(this) headersFinished: this._headersFinished.bind(this),
}); });
this._options = options; this._options = options;
this.writable = true; this.writable = true;
this._parser.start(); this._parser.start();
}; });
util.inherits(ParserAsync, ChunkStream); util.inherits(ParserAsync, ChunkStream);
ParserAsync.prototype._handleError = function (err) {
ParserAsync.prototype._handleError = function(err) { this.emit("error", err);
this.emit('error', err);
this.writable = false; this.writable = false;
@ -48,42 +46,47 @@ ParserAsync.prototype._handleError = function(err) {
// For backward compatibility with Node 7 and below. // For backward compatibility with Node 7 and below.
// Suppress errors due to _inflate calling write() even after // Suppress errors due to _inflate calling write() even after
// it's destroy()'ed. // it's destroy()'ed.
this._filter.on('error', function() {}); this._filter.on("error", function () {});
} }
this.errord = true; this.errord = true;
}; };
ParserAsync.prototype._inflateData = function(data) { ParserAsync.prototype._inflateData = function (data) {
if (!this._inflate) { if (!this._inflate) {
if (this._bitmapInfo.interlace) { if (this._bitmapInfo.interlace) {
this._inflate = zlib.createInflate(); this._inflate = zlib.createInflate();
this._inflate.on('error', this.emit.bind(this, 'error')); this._inflate.on("error", this.emit.bind(this, "error"));
this._filter.on('complete', this._complete.bind(this)); this._filter.on("complete", this._complete.bind(this));
this._inflate.pipe(this._filter); this._inflate.pipe(this._filter);
} } else {
else { let rowSize =
var rowSize = ((this._bitmapInfo.width * this._bitmapInfo.bpp * this._bitmapInfo.depth + 7) >> 3) + 1; ((this._bitmapInfo.width *
var imageSize = rowSize * this._bitmapInfo.height; this._bitmapInfo.bpp *
var chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK); this._bitmapInfo.depth +
7) >>
3) +
1;
let imageSize = rowSize * this._bitmapInfo.height;
let chunkSize = Math.max(imageSize, zlib.Z_MIN_CHUNK);
this._inflate = zlib.createInflate({ chunkSize: chunkSize }); this._inflate = zlib.createInflate({ chunkSize: chunkSize });
var leftToInflate = imageSize; let leftToInflate = imageSize;
var emitError = this.emit.bind(this, 'error'); let emitError = this.emit.bind(this, "error");
this._inflate.on('error', function(err) { this._inflate.on("error", function (err) {
if (!leftToInflate) { if (!leftToInflate) {
return; return;
} }
emitError(err); emitError(err);
}); });
this._filter.on('complete', this._complete.bind(this)); this._filter.on("complete", this._complete.bind(this));
var filterWrite = this._filter.write.bind(this._filter); let filterWrite = this._filter.write.bind(this._filter);
this._inflate.on('data', function(chunk) { this._inflate.on("data", function (chunk) {
if (!leftToInflate) { if (!leftToInflate) {
return; return;
} }
@ -97,67 +100,66 @@ ParserAsync.prototype._inflateData = function(data) {
filterWrite(chunk); filterWrite(chunk);
}); });
this._inflate.on('end', this._filter.end.bind(this._filter)); this._inflate.on("end", this._filter.end.bind(this._filter));
} }
} }
this._inflate.write(data); this._inflate.write(data);
}; };
ParserAsync.prototype._handleMetaData = function(metaData) { ParserAsync.prototype._handleMetaData = function (metaData) {
this._metaData = metaData; this._metaData = metaData;
this._bitmapInfo = Object.create(metaData); this._bitmapInfo = Object.create(metaData);
this._filter = new FilterAsync(this._bitmapInfo); this._filter = new FilterAsync(this._bitmapInfo);
}; };
ParserAsync.prototype._handleTransColor = function(transColor) { ParserAsync.prototype._handleTransColor = function (transColor) {
this._bitmapInfo.transColor = transColor; this._bitmapInfo.transColor = transColor;
}; };
ParserAsync.prototype._handlePalette = function(palette) { ParserAsync.prototype._handlePalette = function (palette) {
this._bitmapInfo.palette = palette; this._bitmapInfo.palette = palette;
}; };
ParserAsync.prototype._simpleTransparency = function() { ParserAsync.prototype._simpleTransparency = function () {
this._metaData.alpha = true; this._metaData.alpha = true;
}; };
ParserAsync.prototype._headersFinished = function() { ParserAsync.prototype._headersFinished = function () {
// Up until this point, we don't know if we have a tRNS chunk (alpha) // Up until this point, we don't know if we have a tRNS chunk (alpha)
// so we can't emit metadata any earlier // so we can't emit metadata any earlier
this.emit('metadata', this._metaData); this.emit("metadata", this._metaData);
}; };
ParserAsync.prototype._finished = function() { ParserAsync.prototype._finished = function () {
if (this.errord) { if (this.errord) {
return; return;
} }
if (!this._inflate) { if (!this._inflate) {
this.emit('error', 'No Inflate block'); this.emit("error", "No Inflate block");
} } else {
else {
// no more data to inflate // no more data to inflate
this._inflate.end(); this._inflate.end();
} }
}; };
ParserAsync.prototype._complete = function(filteredData) { ParserAsync.prototype._complete = function (filteredData) {
if (this.errord) { if (this.errord) {
return; return;
} }
try { let normalisedBitmapData;
var bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
var normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo); try {
let bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo);
bitmapData = null; bitmapData = null;
} } catch (ex) {
catch (ex) {
this._handleError(ex); this._handleError(ex);
return; return;
} }
this.emit('parsed', normalisedBitmapData); this.emit("parsed", normalisedBitmapData);
}; };

View file

@ -1,30 +1,30 @@
'use strict'; "use strict";
var hasSyncZlib = true; let hasSyncZlib = true;
var zlib = require('zlib'); let zlib = require("zlib");
var inflateSync = require('./sync-inflate'); let inflateSync = require("./sync-inflate");
if (!zlib.deflateSync) { if (!zlib.deflateSync) {
hasSyncZlib = false; hasSyncZlib = false;
} }
var SyncReader = require('./sync-reader'); let SyncReader = require("./sync-reader");
var FilterSync = require('./filter-parse-sync'); let FilterSync = require("./filter-parse-sync");
var Parser = require('./parser'); let Parser = require("./parser");
var bitmapper = require('./bitmapper'); let bitmapper = require("./bitmapper");
var formatNormaliser = require('./format-normaliser'); let formatNormaliser = require("./format-normaliser");
module.exports = function(buffer, options) {
module.exports = function (buffer, options) {
if (!hasSyncZlib) { if (!hasSyncZlib) {
throw new Error('To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0'); throw new Error(
"To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
);
} }
var err; let err;
function handleError(_err_) { function handleError(_err_) {
err = _err_; err = _err_;
} }
var metaData; let metaData;
function handleMetaData(_metaData_) { function handleMetaData(_metaData_) {
metaData = _metaData_; metaData = _metaData_;
} }
@ -41,19 +41,19 @@ module.exports = function(buffer, options) {
metaData.alpha = true; metaData.alpha = true;
} }
var gamma; let gamma;
function handleGamma(_gamma_) { function handleGamma(_gamma_) {
gamma = _gamma_; gamma = _gamma_;
} }
var inflateDataList = []; let inflateDataList = [];
function handleInflateData(inflatedData) { function handleInflateData(inflatedData) {
inflateDataList.push(inflatedData); inflateDataList.push(inflatedData);
} }
var reader = new SyncReader(buffer); let reader = new SyncReader(buffer);
var parser = new Parser(options, { let parser = new Parser(options, {
read: reader.read.bind(reader), read: reader.read.bind(reader),
error: handleError, error: handleError,
metadata: handleMetaData, metadata: handleMetaData,
@ -61,7 +61,7 @@ module.exports = function(buffer, options) {
palette: handlePalette, palette: handlePalette,
transColor: handleTransColor, transColor: handleTransColor,
inflateData: handleInflateData, inflateData: handleInflateData,
simpleTransparency: handleSimpleTransparency simpleTransparency: handleSimpleTransparency,
}); });
parser.start(); parser.start();
@ -72,31 +72,34 @@ module.exports = function(buffer, options) {
} }
//join together the inflate datas //join together the inflate datas
var inflateData = Buffer.concat(inflateDataList); let inflateData = Buffer.concat(inflateDataList);
inflateDataList.length = 0; inflateDataList.length = 0;
var inflatedData; let inflatedData;
if (metaData.interlace) { if (metaData.interlace) {
inflatedData = zlib.inflateSync(inflateData); inflatedData = zlib.inflateSync(inflateData);
} } else {
else { let rowSize =
var rowSize = ((metaData.width * metaData.bpp * metaData.depth + 7) >> 3) + 1; ((metaData.width * metaData.bpp * metaData.depth + 7) >> 3) + 1;
var imageSize = rowSize * metaData.height; let imageSize = rowSize * metaData.height;
inflatedData = inflateSync(inflateData, { chunkSize: imageSize, maxLength: imageSize }); inflatedData = inflateSync(inflateData, {
chunkSize: imageSize,
maxLength: imageSize,
});
} }
inflateData = null; inflateData = null;
if (!inflatedData || !inflatedData.length) { if (!inflatedData || !inflatedData.length) {
throw new Error('bad png - invalid inflate data response'); throw new Error("bad png - invalid inflate data response");
} }
var unfilteredData = FilterSync.process(inflatedData, metaData); let unfilteredData = FilterSync.process(inflatedData, metaData);
inflateData = null; inflateData = null;
var bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData); let bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData);
unfilteredData = null; unfilteredData = null;
var normalisedBitmapData = formatNormaliser(bitmapData, metaData); let normalisedBitmapData = formatNormaliser(bitmapData, metaData);
metaData.data = normalisedBitmapData; metaData.data = normalisedBitmapData;
metaData.gamma = gamma || 0; metaData.gamma = gamma || 0;

View file

@ -1,11 +1,9 @@
'use strict'; "use strict";
var constants = require('./constants'); let constants = require("./constants");
var CrcCalculator = require('./crc'); let CrcCalculator = require("./crc");
var Parser = module.exports = function(options, dependencies) {
let Parser = (module.exports = function (options, dependencies) {
this._options = options; this._options = options;
options.checkCRC = options.checkCRC !== false; options.checkCRC = options.checkCRC !== false;
@ -35,49 +33,45 @@ var Parser = module.exports = function(options, dependencies) {
this.inflateData = dependencies.inflateData; this.inflateData = dependencies.inflateData;
this.finished = dependencies.finished; this.finished = dependencies.finished;
this.simpleTransparency = dependencies.simpleTransparency; this.simpleTransparency = dependencies.simpleTransparency;
this.headersFinished = dependencies.headersFinished || function() {}; this.headersFinished = dependencies.headersFinished || function () {};
});
Parser.prototype.start = function () {
this.read(constants.PNG_SIGNATURE.length, this._parseSignature.bind(this));
}; };
Parser.prototype.start = function() { Parser.prototype._parseSignature = function (data) {
this.read(constants.PNG_SIGNATURE.length, let signature = constants.PNG_SIGNATURE;
this._parseSignature.bind(this)
);
};
Parser.prototype._parseSignature = function(data) { for (let i = 0; i < signature.length; i++) {
var signature = constants.PNG_SIGNATURE;
for (var i = 0; i < signature.length; i++) {
if (data[i] !== signature[i]) { if (data[i] !== signature[i]) {
this.error(new Error('Invalid file signature')); this.error(new Error("Invalid file signature"));
return; return;
} }
} }
this.read(8, this._parseChunkBegin.bind(this)); this.read(8, this._parseChunkBegin.bind(this));
}; };
Parser.prototype._parseChunkBegin = function(data) { Parser.prototype._parseChunkBegin = function (data) {
// chunk content length // chunk content length
var length = data.readUInt32BE(0); let length = data.readUInt32BE(0);
// chunk type // chunk type
var type = data.readUInt32BE(4); let type = data.readUInt32BE(4);
var name = ''; let name = "";
for (var i = 4; i < 8; i++) { for (let i = 4; i < 8; i++) {
name += String.fromCharCode(data[i]); name += String.fromCharCode(data[i]);
} }
//console.log('chunk ', name, length); //console.log('chunk ', name, length);
// chunk flags // chunk flags
var ancillary = Boolean(data[4] & 0x20); // or critical let ancillary = Boolean(data[4] & 0x20); // or critical
// priv = Boolean(data[5] & 0x20), // or public // priv = Boolean(data[5] & 0x20), // or public
// safeToCopy = Boolean(data[7] & 0x20); // or unsafe // safeToCopy = Boolean(data[7] & 0x20); // or unsafe
if (!this._hasIHDR && type !== constants.TYPE_IHDR) { if (!this._hasIHDR && type !== constants.TYPE_IHDR) {
this.error(new Error('Expected IHDR on beggining')); this.error(new Error("Expected IHDR on beggining"));
return; return;
} }
@ -89,29 +83,28 @@ Parser.prototype._parseChunkBegin = function(data) {
} }
if (!ancillary) { if (!ancillary) {
this.error(new Error('Unsupported critical chunk type ' + name)); this.error(new Error("Unsupported critical chunk type " + name));
return; return;
} }
this.read(length + 4, this._skipChunk.bind(this)); this.read(length + 4, this._skipChunk.bind(this));
}; };
Parser.prototype._skipChunk = function(/*data*/) { Parser.prototype._skipChunk = function (/*data*/) {
this.read(8, this._parseChunkBegin.bind(this)); this.read(8, this._parseChunkBegin.bind(this));
}; };
Parser.prototype._handleChunkEnd = function() { Parser.prototype._handleChunkEnd = function () {
this.read(4, this._parseChunkEnd.bind(this)); this.read(4, this._parseChunkEnd.bind(this));
}; };
Parser.prototype._parseChunkEnd = function(data) { Parser.prototype._parseChunkEnd = function (data) {
let fileCrc = data.readInt32BE(0);
var fileCrc = data.readInt32BE(0); let calcCrc = this._crc.crc32();
var calcCrc = this._crc.crc32();
// check CRC // check CRC
if (this._options.checkCRC && calcCrc !== fileCrc) { if (this._options.checkCRC && calcCrc !== fileCrc) {
this.error(new Error('Crc error - ' + fileCrc + ' - ' + calcCrc)); this.error(new Error("Crc error - " + fileCrc + " - " + calcCrc));
return; return;
} }
@ -120,50 +113,55 @@ Parser.prototype._parseChunkEnd = function(data) {
} }
}; };
Parser.prototype._handleIHDR = function(length) { Parser.prototype._handleIHDR = function (length) {
this.read(length, this._parseIHDR.bind(this)); this.read(length, this._parseIHDR.bind(this));
}; };
Parser.prototype._parseIHDR = function(data) { Parser.prototype._parseIHDR = function (data) {
this._crc.write(data); this._crc.write(data);
var width = data.readUInt32BE(0); let width = data.readUInt32BE(0);
var height = data.readUInt32BE(4); let height = data.readUInt32BE(4);
var depth = data[8]; let depth = data[8];
var colorType = data[9]; // bits: 1 palette, 2 color, 4 alpha let colorType = data[9]; // bits: 1 palette, 2 color, 4 alpha
var compr = data[10]; let compr = data[10];
var filter = data[11]; let filter = data[11];
var interlace = data[12]; let interlace = data[12];
// console.log(' width', width, 'height', height, // console.log(' width', width, 'height', height,
// 'depth', depth, 'colorType', colorType, // 'depth', depth, 'colorType', colorType,
// 'compr', compr, 'filter', filter, 'interlace', interlace // 'compr', compr, 'filter', filter, 'interlace', interlace
// ); // );
if (depth !== 8 && depth !== 4 && depth !== 2 && depth !== 1 && depth !== 16) { if (
this.error(new Error('Unsupported bit depth ' + depth)); depth !== 8 &&
depth !== 4 &&
depth !== 2 &&
depth !== 1 &&
depth !== 16
) {
this.error(new Error("Unsupported bit depth " + depth));
return; return;
} }
if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) { if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) {
this.error(new Error('Unsupported color type')); this.error(new Error("Unsupported color type"));
return; return;
} }
if (compr !== 0) { if (compr !== 0) {
this.error(new Error('Unsupported compression method')); this.error(new Error("Unsupported compression method"));
return; return;
} }
if (filter !== 0) { if (filter !== 0) {
this.error(new Error('Unsupported filter method')); this.error(new Error("Unsupported filter method"));
return; return;
} }
if (interlace !== 0 && interlace !== 1) { if (interlace !== 0 && interlace !== 1) {
this.error(new Error('Unsupported interlace method')); this.error(new Error("Unsupported interlace method"));
return; return;
} }
this._colorType = colorType; this._colorType = colorType;
var bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType]; let bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType];
this._hasIHDR = true; this._hasIHDR = true;
@ -176,30 +174,23 @@ Parser.prototype._parseIHDR = function(data) {
color: Boolean(colorType & constants.COLORTYPE_COLOR), color: Boolean(colorType & constants.COLORTYPE_COLOR),
alpha: Boolean(colorType & constants.COLORTYPE_ALPHA), alpha: Boolean(colorType & constants.COLORTYPE_ALPHA),
bpp: bpp, bpp: bpp,
colorType: colorType colorType: colorType,
}); });
this._handleChunkEnd(); this._handleChunkEnd();
}; };
Parser.prototype._handlePLTE = function (length) {
Parser.prototype._handlePLTE = function(length) {
this.read(length, this._parsePLTE.bind(this)); this.read(length, this._parsePLTE.bind(this));
}; };
Parser.prototype._parsePLTE = function(data) { Parser.prototype._parsePLTE = function (data) {
this._crc.write(data); this._crc.write(data);
var entries = Math.floor(data.length / 3); let entries = Math.floor(data.length / 3);
// console.log('Palette:', entries); // console.log('Palette:', entries);
for (var i = 0; i < entries; i++) { for (let i = 0; i < entries; i++) {
this._palette.push([ this._palette.push([data[i * 3], data[i * 3 + 1], data[i * 3 + 2], 0xff]);
data[i * 3],
data[i * 3 + 1],
data[i * 3 + 2],
0xff
]);
} }
this.palette(this._palette); this.palette(this._palette);
@ -207,25 +198,24 @@ Parser.prototype._parsePLTE = function(data) {
this._handleChunkEnd(); this._handleChunkEnd();
}; };
Parser.prototype._handleTRNS = function(length) { Parser.prototype._handleTRNS = function (length) {
this.simpleTransparency(); this.simpleTransparency();
this.read(length, this._parseTRNS.bind(this)); this.read(length, this._parseTRNS.bind(this));
}; };
Parser.prototype._parseTRNS = function(data) { Parser.prototype._parseTRNS = function (data) {
this._crc.write(data); this._crc.write(data);
// palette // palette
if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) { if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) {
if (this._palette.length === 0) { if (this._palette.length === 0) {
this.error(new Error('Transparency chunk must be after palette')); this.error(new Error("Transparency chunk must be after palette"));
return; return;
} }
if (data.length > this._palette.length) { if (data.length > this._palette.length) {
this.error(new Error('More transparent colors than palette size')); this.error(new Error("More transparent colors than palette size"));
return; return;
} }
for (var i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
this._palette[i][3] = data[i]; this._palette[i][3] = data[i];
} }
this.palette(this._palette); this.palette(this._palette);
@ -238,54 +228,57 @@ Parser.prototype._parseTRNS = function(data) {
this.transColor([data.readUInt16BE(0)]); this.transColor([data.readUInt16BE(0)]);
} }
if (this._colorType === constants.COLORTYPE_COLOR) { if (this._colorType === constants.COLORTYPE_COLOR) {
this.transColor([data.readUInt16BE(0), data.readUInt16BE(2), data.readUInt16BE(4)]); this.transColor([
data.readUInt16BE(0),
data.readUInt16BE(2),
data.readUInt16BE(4),
]);
} }
this._handleChunkEnd(); this._handleChunkEnd();
}; };
Parser.prototype._handleGAMA = function(length) { Parser.prototype._handleGAMA = function (length) {
this.read(length, this._parseGAMA.bind(this)); this.read(length, this._parseGAMA.bind(this));
}; };
Parser.prototype._parseGAMA = function(data) { Parser.prototype._parseGAMA = function (data) {
this._crc.write(data); this._crc.write(data);
this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION); this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION);
this._handleChunkEnd(); this._handleChunkEnd();
}; };
Parser.prototype._handleIDAT = function(length) { Parser.prototype._handleIDAT = function (length) {
if (!this._emittedHeadersFinished) { if (!this._emittedHeadersFinished) {
this._emittedHeadersFinished = true; this._emittedHeadersFinished = true;
this.headersFinished(); this.headersFinished();
} }
this.read(-length, this._parseIDAT.bind(this, length)); this.read(-length, this._parseIDAT.bind(this, length));
}; };
Parser.prototype._parseIDAT = function(length, data) { Parser.prototype._parseIDAT = function (length, data) {
this._crc.write(data); this._crc.write(data);
if (this._colorType === constants.COLORTYPE_PALETTE_COLOR && this._palette.length === 0) { if (
throw new Error('Expected palette not found'); this._colorType === constants.COLORTYPE_PALETTE_COLOR &&
this._palette.length === 0
) {
throw new Error("Expected palette not found");
} }
this.inflateData(data); this.inflateData(data);
var leftOverLength = length - data.length; let leftOverLength = length - data.length;
if (leftOverLength > 0) { if (leftOverLength > 0) {
this._handleIDAT(leftOverLength); this._handleIDAT(leftOverLength);
} } else {
else {
this._handleChunkEnd(); this._handleChunkEnd();
} }
}; };
Parser.prototype._handleIEND = function(length) { Parser.prototype._handleIEND = function (length) {
this.read(length, this._parseIEND.bind(this)); this.read(length, this._parseIEND.bind(this));
}; };
Parser.prototype._parseIEND = function(data) { Parser.prototype._parseIEND = function (data) {
this._crc.write(data); this._crc.write(data);
this._hasIEND = true; this._hasIEND = true;

View file

@ -1,16 +1,12 @@
'use strict'; "use strict";
let parse = require("./parser-sync");
let pack = require("./packer-sync");
var parse = require('./parser-sync'); exports.read = function (buffer, options) {
var pack = require('./packer-sync');
exports.read = function(buffer, options) {
return parse(buffer, options || {}); return parse(buffer, options || {});
}; };
exports.write = function(png, options) { exports.write = function (png, options) {
return pack(png, options); return pack(png, options);
}; };

View file

@ -1,13 +1,12 @@
'use strict'; "use strict";
var util = require('util'); let util = require("util");
var Stream = require('stream'); let Stream = require("stream");
var Parser = require('./parser-async'); let Parser = require("./parser-async");
var Packer = require('./packer-async'); let Packer = require("./packer-async");
var PNGSync = require('./png-sync'); let PNGSync = require("./png-sync");
let PNG = (exports.PNG = function (options) {
var PNG = exports.PNG = function(options) {
Stream.call(this); Stream.call(this);
options = options || {}; // eslint-disable-line no-param-reassign options = options || {}; // eslint-disable-line no-param-reassign
@ -16,8 +15,10 @@ var PNG = exports.PNG = function(options) {
this.width = options.width | 0; this.width = options.width | 0;
this.height = options.height | 0; this.height = options.height | 0;
this.data = this.width > 0 && this.height > 0 ? this.data =
Buffer.alloc(4 * this.width * this.height) : null; this.width > 0 && this.height > 0
? Buffer.alloc(4 * this.width * this.height)
: null;
if (options.fill && this.data) { if (options.fill && this.data) {
this.data.fill(0); this.data.fill(0);
@ -28,95 +29,96 @@ var PNG = exports.PNG = function(options) {
this._parser = new Parser(options); this._parser = new Parser(options);
this._parser.on('error', this.emit.bind(this, 'error')); this._parser.on("error", this.emit.bind(this, "error"));
this._parser.on('close', this._handleClose.bind(this)); this._parser.on("close", this._handleClose.bind(this));
this._parser.on('metadata', this._metadata.bind(this)); this._parser.on("metadata", this._metadata.bind(this));
this._parser.on('gamma', this._gamma.bind(this)); this._parser.on("gamma", this._gamma.bind(this));
this._parser.on('parsed', function(data) { this._parser.on(
this.data = data; "parsed",
this.emit('parsed', data); function (data) {
}.bind(this)); this.data = data;
this.emit("parsed", data);
}.bind(this)
);
this._packer = new Packer(options); this._packer = new Packer(options);
this._packer.on('data', this.emit.bind(this, 'data')); this._packer.on("data", this.emit.bind(this, "data"));
this._packer.on('end', this.emit.bind(this, 'end')); this._packer.on("end", this.emit.bind(this, "end"));
this._parser.on('close', this._handleClose.bind(this)); this._parser.on("close", this._handleClose.bind(this));
this._packer.on('error', this.emit.bind(this, 'error')); this._packer.on("error", this.emit.bind(this, "error"));
});
};
util.inherits(PNG, Stream); util.inherits(PNG, Stream);
PNG.sync = PNGSync; PNG.sync = PNGSync;
PNG.prototype.pack = function() { PNG.prototype.pack = function () {
if (!this.data || !this.data.length) { if (!this.data || !this.data.length) {
this.emit('error', 'No data provided'); this.emit("error", "No data provided");
return this; return this;
} }
process.nextTick(function() { process.nextTick(
this._packer.pack(this.data, this.width, this.height, this.gamma); function () {
}.bind(this)); this._packer.pack(this.data, this.width, this.height, this.gamma);
}.bind(this)
);
return this; return this;
}; };
PNG.prototype.parse = function (data, callback) {
PNG.prototype.parse = function(data, callback) {
if (callback) { if (callback) {
var onParsed, onError; let onParsed, onError;
onParsed = function(parsedData) { onParsed = function (parsedData) {
this.removeListener('error', onError); this.removeListener("error", onError);
this.data = parsedData; this.data = parsedData;
callback(null, this); callback(null, this);
}.bind(this); }.bind(this);
onError = function(err) { onError = function (err) {
this.removeListener('parsed', onParsed); this.removeListener("parsed", onParsed);
callback(err, null); callback(err, null);
}.bind(this); }.bind(this);
this.once('parsed', onParsed); this.once("parsed", onParsed);
this.once('error', onError); this.once("error", onError);
} }
this.end(data); this.end(data);
return this; return this;
}; };
PNG.prototype.write = function(data) { PNG.prototype.write = function (data) {
this._parser.write(data); this._parser.write(data);
return true; return true;
}; };
PNG.prototype.end = function(data) { PNG.prototype.end = function (data) {
this._parser.end(data); this._parser.end(data);
}; };
PNG.prototype._metadata = function(metadata) { PNG.prototype._metadata = function (metadata) {
this.width = metadata.width; this.width = metadata.width;
this.height = metadata.height; this.height = metadata.height;
this.emit('metadata', metadata); this.emit("metadata", metadata);
}; };
PNG.prototype._gamma = function(gamma) { PNG.prototype._gamma = function (gamma) {
this.gamma = gamma; this.gamma = gamma;
}; };
PNG.prototype._handleClose = function() { PNG.prototype._handleClose = function () {
if (!this._parser.writable && !this._packer.readable) { if (!this._parser.writable && !this._packer.readable) {
this.emit('close'); this.emit("close");
} }
}; };
PNG.bitblt = function (src, dst, srcX, srcY, width, height, deltaX, deltaY) {
PNG.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) { // eslint-disable-line max-params // eslint-disable-line max-params
// coerce pixel dimensions to integers (also coerces undefined -> 0): // coerce pixel dimensions to integers (also coerces undefined -> 0):
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
srcX |= 0; srcX |= 0;
@ -127,16 +129,27 @@ PNG.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) { //
deltaY |= 0; deltaY |= 0;
/* eslint-enable no-param-reassign */ /* eslint-enable no-param-reassign */
if (srcX > src.width || srcY > src.height || srcX + width > src.width || srcY + height > src.height) { if (
throw new Error('bitblt reading outside image'); srcX > src.width ||
srcY > src.height ||
srcX + width > src.width ||
srcY + height > src.height
) {
throw new Error("bitblt reading outside image");
} }
if (deltaX > dst.width || deltaY > dst.height || deltaX + width > dst.width || deltaY + height > dst.height) { if (
throw new Error('bitblt writing outside image'); deltaX > dst.width ||
deltaY > dst.height ||
deltaX + width > dst.width ||
deltaY + height > dst.height
) {
throw new Error("bitblt writing outside image");
} }
for (var y = 0; y < height; y++) { for (let y = 0; y < height; y++) {
src.data.copy(dst.data, src.data.copy(
dst.data,
((deltaY + y) * dst.width + deltaX) << 2, ((deltaY + y) * dst.width + deltaX) << 2,
((srcY + y) * src.width + srcX) << 2, ((srcY + y) * src.width + srcX) << 2,
((srcY + y) * src.width + srcX + width) << 2 ((srcY + y) * src.width + srcX + width) << 2
@ -144,21 +157,29 @@ PNG.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) { //
} }
}; };
PNG.prototype.bitblt = function (
PNG.prototype.bitblt = function(dst, srcX, srcY, width, height, deltaX, deltaY) { // eslint-disable-line max-params dst,
srcX,
srcY,
width,
height,
deltaX,
deltaY
) {
// eslint-disable-line max-params
PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY); PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
return this; return this;
}; };
PNG.adjustGamma = function(src) { PNG.adjustGamma = function (src) {
if (src.gamma) { if (src.gamma) {
for (var y = 0; y < src.height; y++) { for (let y = 0; y < src.height; y++) {
for (var x = 0; x < src.width; x++) { for (let x = 0; x < src.width; x++) {
var idx = (src.width * y + x) << 2; let idx = (src.width * y + x) << 2;
for (var i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
var sample = src.data[idx + i] / 255; let sample = src.data[idx + i] / 255;
sample = Math.pow(sample, 1 / 2.2 / src.gamma); sample = Math.pow(sample, 1 / 2.2 / src.gamma);
src.data[idx + i] = Math.round(sample * 255); src.data[idx + i] = Math.round(sample * 255);
} }
@ -168,6 +189,6 @@ PNG.adjustGamma = function(src) {
} }
}; };
PNG.prototype.adjustGamma = function() { PNG.prototype.adjustGamma = function () {
PNG.adjustGamma(this); PNG.adjustGamma(this);
}; };

View file

@ -1,10 +1,10 @@
'use strict'; "use strict";
var assert = require('assert').ok; let assert = require("assert").ok;
var zlib = require('zlib'); let zlib = require("zlib");
var util = require('util'); let util = require("util");
var kMaxLength = require('buffer').kMaxLength; let kMaxLength = require("buffer").kMaxLength;
function Inflate(opts) { function Inflate(opts) {
if (!(this instanceof Inflate)) { if (!(this instanceof Inflate)) {
@ -44,23 +44,23 @@ function _close(engine, callback) {
engine._handle = null; engine._handle = null;
} }
Inflate.prototype._processChunk = function(chunk, flushFlag, asyncCb) { Inflate.prototype._processChunk = function (chunk, flushFlag, asyncCb) {
if (typeof asyncCb === 'function') { if (typeof asyncCb === "function") {
return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb); return zlib.Inflate._processChunk.call(this, chunk, flushFlag, asyncCb);
} }
var self = this; let self = this;
var availInBefore = chunk && chunk.length; let availInBefore = chunk && chunk.length;
var availOutBefore = this._chunkSize - this._offset; let availOutBefore = this._chunkSize - this._offset;
var leftToInflate = this._maxLength; let leftToInflate = this._maxLength;
var inOff = 0; let inOff = 0;
var buffers = []; let buffers = [];
var nread = 0; let nread = 0;
var error; let error;
this.on('error', function(err) { this.on("error", function (err) {
error = err; error = err;
}); });
@ -69,11 +69,11 @@ Inflate.prototype._processChunk = function(chunk, flushFlag, asyncCb) {
return; return;
} }
var have = availOutBefore - availOutAfter; let have = availOutBefore - availOutAfter;
assert(have >= 0, 'have should not go down'); assert(have >= 0, "have should not go down");
if (have > 0) { if (have > 0) {
var out = self._buffer.slice(self._offset, self._offset + have); let out = self._buffer.slice(self._offset, self._offset + have);
self._offset += have; self._offset += have;
if (out.length > leftToInflate) { if (out.length > leftToInflate) {
@ -96,7 +96,7 @@ Inflate.prototype._processChunk = function(chunk, flushFlag, asyncCb) {
} }
if (availOutAfter === 0) { if (availOutAfter === 0) {
inOff += (availInBefore - availInAfter); inOff += availInBefore - availInAfter;
availInBefore = availInAfter; availInBefore = availInAfter;
return true; return true;
@ -105,15 +105,18 @@ Inflate.prototype._processChunk = function(chunk, flushFlag, asyncCb) {
return false; return false;
} }
assert(this._handle, 'zlib binding closed'); assert(this._handle, "zlib binding closed");
let res;
do { do {
var res = this._handle.writeSync(flushFlag, res = this._handle.writeSync(
flushFlag,
chunk, // in chunk, // in
inOff, // in_off inOff, // in_off
availInBefore, // in_len availInBefore, // in_len
this._buffer, // out this._buffer, // out
this._offset, //out_off this._offset, //out_off
availOutBefore); // out_len availOutBefore
); // out_len
// Node 8 --> 9 compatibility check // Node 8 --> 9 compatibility check
res = res || this._writeState; res = res || this._writeState;
} while (!this._hadError && handleChunk(res[0], res[1])); } while (!this._hadError && handleChunk(res[0], res[1]));
@ -124,10 +127,14 @@ Inflate.prototype._processChunk = function(chunk, flushFlag, asyncCb) {
if (nread >= kMaxLength) { if (nread >= kMaxLength) {
_close(this); _close(this);
throw new RangeError('Cannot create final Buffer. It would be larger than 0x' + kMaxLength.toString(16) + ' bytes'); throw new RangeError(
"Cannot create final Buffer. It would be larger than 0x" +
kMaxLength.toString(16) +
" bytes"
);
} }
var buf = Buffer.concat(buffers, nread); let buf = Buffer.concat(buffers, nread);
_close(this); _close(this);
return buf; return buf;
@ -136,14 +143,14 @@ Inflate.prototype._processChunk = function(chunk, flushFlag, asyncCb) {
util.inherits(Inflate, zlib.Inflate); util.inherits(Inflate, zlib.Inflate);
function zlibBufferSync(engine, buffer) { function zlibBufferSync(engine, buffer) {
if (typeof buffer === 'string') { if (typeof buffer === "string") {
buffer = Buffer.from(buffer); buffer = Buffer.from(buffer);
} }
if (!(buffer instanceof Buffer)) { if (!(buffer instanceof Buffer)) {
throw new TypeError('Not a string or buffer'); throw new TypeError("Not a string or buffer");
} }
var flushFlag = engine._finishFlushFlag; let flushFlag = engine._finishFlushFlag;
if (flushFlag == null) { if (flushFlag == null) {
flushFlag = zlib.Z_FINISH; flushFlag = zlib.Z_FINISH;
} }

View file

@ -1,51 +1,45 @@
'use strict'; "use strict";
var SyncReader = module.exports = function(buffer) {
let SyncReader = (module.exports = function (buffer) {
this._buffer = buffer; this._buffer = buffer;
this._reads = []; this._reads = [];
}; });
SyncReader.prototype.read = function(length, callback) {
SyncReader.prototype.read = function (length, callback) {
this._reads.push({ this._reads.push({
length: Math.abs(length), // if length < 0 then at most this length length: Math.abs(length), // if length < 0 then at most this length
allowLess: length < 0, allowLess: length < 0,
func: callback func: callback,
}); });
}; };
SyncReader.prototype.process = function() { SyncReader.prototype.process = function () {
// as long as there is any data and read requests // as long as there is any data and read requests
while (this._reads.length > 0 && this._buffer.length) { while (this._reads.length > 0 && this._buffer.length) {
let read = this._reads[0];
var read = this._reads[0]; if (
this._buffer.length &&
if (this._buffer.length && (this._buffer.length >= read.length || read.allowLess)) { (this._buffer.length >= read.length || read.allowLess)
) {
// ok there is any data so that we can satisfy this request // ok there is any data so that we can satisfy this request
this._reads.shift(); // == read this._reads.shift(); // == read
var buf = this._buffer; let buf = this._buffer;
this._buffer = buf.slice(read.length); this._buffer = buf.slice(read.length);
read.func.call(this, buf.slice(0, read.length)); read.func.call(this, buf.slice(0, read.length));
} else {
}
else {
break; break;
} }
} }
if (this._reads.length > 0) { if (this._reads.length > 0) {
return new Error('There are some read requests waitng on finished stream'); return new Error("There are some read requests waitng on finished stream");
} }
if (this._buffer.length > 0) { if (this._buffer.length > 0) {
return new Error('unrecognised content at end of stream'); return new Error("unrecognised content at end of stream");
} }
}; };

View file

@ -30,7 +30,7 @@
"pngjs" "pngjs"
], ],
"engines": { "engines": {
"node": ">=8.0.0" "node": ">=10.13.0"
}, },
"main": "./lib/png.js", "main": "./lib/png.js",
"directories": { "directories": {
@ -39,14 +39,15 @@
"test": "test" "test": "test"
}, },
"scripts": { "scripts": {
"build": "npm run prepublish", "build": "yarn prepublish",
"prepublish": "npm run browserify", "prepublish": "yarn browserify",
"browserify": "browserify lib/png.js --standalone png > browser.js", "browserify": "browserify lib/png.js --standalone png > browser.js",
"coverage": "istanbul -- cover node_modules/tape/bin/tape test/*-spec.js nolarge", "coverage": "nyc tape test/*-spec.js nolarge",
"coverage-report": "npm run coverage && istanbul report html",
"coveralls": "cat ./coverage/lcov.info | coveralls", "coveralls": "cat ./coverage/lcov.info | coveralls",
"test": "npm run lint && tape test/*-spec.js | tap-dot && node test/run-compare", "test": "yarn lint && yarn prettier:check && tape test/*-spec.js | tap-dot && node test/run-compare",
"lint": "eslint lib" "lint": "eslint .",
"prettier:write": "prettier --write .",
"prettier:check": "prettier --check ."
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -57,14 +58,18 @@
"url": "https://github.com/lukeapage/pngjs2/issues" "url": "https://github.com/lukeapage/pngjs2/issues"
}, },
"devDependencies": { "devDependencies": {
"browserify": "^14.5.0", "browserify": "16.5.1",
"buffer-equal": "1.0.0", "buffer-equal": "1.0.0",
"connect": "^3.4.0", "connect": "3.4.0",
"eslint": "^5.15.2", "coveralls": "3.0.11",
"istanbul": "^0.4.4", "eslint": "5.15.2",
"eslint-config-prettier": "6.10.1",
"istanbul": "0.4.4",
"nyc": "15.0.1",
"prettier": "2.0.4",
"puppeteer": "1.20.0", "puppeteer": "1.20.0",
"serve-static": "^1.10.0", "serve-static": "1.10.0",
"tap-dot": "^2.0.0", "tap-dot": "2.0.0",
"tape": "^4.0.2" "tape": "4.0.2"
} }
} }

View file

@ -1,26 +1,24 @@
#!/usr/bin/env node #!/usr/bin/env node
var fs = require('fs'); let fs = require("fs");
var PNG = require('../lib/png').PNG; let PNG = require("../lib/png").PNG;
var test = require('tape'); let test = require("tape");
var bufferEqual = require('buffer-equal'); let bufferEqual = require("buffer-equal");
test('outputs background, created from scratch', function (t) {
test("outputs background, created from scratch", function (t) {
t.timeoutAfter(1000 * 60 * 5); t.timeoutAfter(1000 * 60 * 5);
var png = new PNG({ let png = new PNG({
width: 10, width: 10,
height: 10, height: 10,
filterType: -1 filterType: -1,
}); });
for (let y = 0; y < png.height; y++) {
for (let x = 0; x < png.width; x++) {
let idx = (png.width * y + x) << 2;
for (var y = 0; y < png.height; y++) { let col = (x < png.width >> 1) ^ (y < png.height >> 1) ? 0xe5 : 0xff;
for (var x = 0; x < png.width; x++) {
var idx = (png.width * y + x) << 2;
var col = x < (png.width >> 1) ^ y < (png.height >> 1) ? 0xe5 : 0xff;
png.data[idx] = col; png.data[idx] = col;
png.data[idx + 1] = col; png.data[idx + 1] = col;
@ -29,13 +27,14 @@ test('outputs background, created from scratch', function (t) {
} }
} }
png.pack().pipe(fs.createWriteStream(__dirname + '/bg.png')) png
.pack()
.pipe(fs.createWriteStream(__dirname + "/bg.png"))
.on("finish", function () { .on("finish", function () {
let out = fs.readFileSync(__dirname + "/bg.png");
let ref = fs.readFileSync(__dirname + "/bg-ref.png");
var out = fs.readFileSync(__dirname + '/bg.png'); let isBufferEqual = bufferEqual(out, ref);
var ref = fs.readFileSync(__dirname + '/bg-ref.png');
var isBufferEqual = bufferEqual(out, ref);
t.ok(isBufferEqual, "compares with working file ok"); t.ok(isBufferEqual, "compares with working file ok");
if (!isBufferEqual) { if (!isBufferEqual) {

View file

@ -1,35 +1,44 @@
var fs = require('fs'); let fs = require("fs");
var PNG = require('../lib/png').PNG; let PNG = require("../lib/png").PNG;
var test = require('tape'); let test = require("tape");
var noLargeOption = process.argv.indexOf("nolarge") >= 0; let noLargeOption = process.argv.indexOf("nolarge") >= 0;
fs.readdir(__dirname + '/in/', function (err, files) { fs.readdir(__dirname + "/in/", function (err, files) {
if (err) throw err; if (err) throw err;
files = files.filter(function (file) { files = files.filter(function (file) {
return (!noLargeOption || !file.match(/large/i)) && Boolean(file.match(/\.png$/i)); return (
(!noLargeOption || !file.match(/large/i)) &&
Boolean(file.match(/\.png$/i))
);
}); });
console.log("Converting images"); console.log("Converting images");
files.forEach(function (file) { files.forEach(function (file) {
let expectedError = false;
var expectedError = false;
if (file.match(/^x/)) { if (file.match(/^x/)) {
expectedError = true; expectedError = true;
} }
test('convert sync - ' + file, function (t) { test("convert sync - " + file, function (t) {
t.timeoutAfter(1000 * 60 * 5); t.timeoutAfter(1000 * 60 * 5);
var data = fs.readFileSync(__dirname + '/in/' + file); let data = fs.readFileSync(__dirname + "/in/" + file);
let png;
try { try {
var png = PNG.sync.read(data); png = PNG.sync.read(data);
} catch (e) { } catch (e) {
if (!expectedError) { if (!expectedError) {
t.fail('Unexpected error parsing..' + file + '\n' + e.message + "\n" + e.stack); t.fail(
"Unexpected error parsing.." +
file +
"\n" +
e.message +
"\n" +
e.stack
);
} else { } else {
t.pass("completed"); t.pass("completed");
} }
@ -41,47 +50,55 @@ fs.readdir(__dirname + '/in/', function (err, files) {
return t.end(); return t.end();
} }
var outpng = new PNG(); let outpng = new PNG();
outpng.gamma = png.gamma; outpng.gamma = png.gamma;
outpng.data = png.data; outpng.data = png.data;
outpng.width = png.width; outpng.width = png.width;
outpng.height = png.height; outpng.height = png.height;
outpng.pack() outpng.pack().pipe(
.pipe(fs.createWriteStream(__dirname + '/outsync/' + file) fs
.createWriteStream(__dirname + "/outsync/" + file)
.on("finish", function () { .on("finish", function () {
t.pass("completed"); t.pass("completed");
t.end(); t.end();
})); })
);
}); });
test('convert async - ' + file, function (t) { test("convert async - " + file, function (t) {
t.timeoutAfter(1000 * 60 * 5); t.timeoutAfter(1000 * 60 * 5);
fs.createReadStream(__dirname + '/in/' + file) fs.createReadStream(__dirname + "/in/" + file)
.pipe(new PNG()) .pipe(new PNG())
.on('error', function (err) { .on("error", function (err) {
if (!expectedError) { if (!expectedError) {
t.fail("Async: Unexpected error parsing.." + file + '\n' + err.message + '\n' + err.stack); t.fail(
"Async: Unexpected error parsing.." +
file +
"\n" +
err.message +
"\n" +
err.stack
);
} else { } else {
t.pass("completed"); t.pass("completed");
} }
t.end(); t.end();
}) })
.on('parsed', function () { .on("parsed", function () {
if (expectedError) { if (expectedError) {
t.fail("Async: Error expected, parsed fine .." + file); t.fail("Async: Error expected, parsed fine .." + file);
return t.end(); return t.end();
} }
this.pack() this.pack().pipe(
.pipe( fs
fs.createWriteStream(__dirname + '/out/' + file) .createWriteStream(__dirname + "/out/" + file)
.on("finish", function () { .on("finish", function () {
t.pass("completed"); t.pass("completed");
t.end(); t.end();
})); })
);
}); });
}); });
}); });

View file

@ -1,14 +1,16 @@
var serveStatic = require('serve-static'); let serveStatic = require("serve-static");
//var serveIndex = require('serve-index'); let http = require("http");
var http = require('http'); let connect = require("connect");
var connect = require('connect');
var app = connect(); let app = connect();
server = http.createServer(app); let server = http.createServer(app);
app.use(serveStatic('test')); app.use(serveStatic("test"));
//app.use(serveIndex('test'));
server.listen(8000); server.listen(8000);
module.exports = () => {
server.close();
};
console.log("Tests available at http://localhost:8000/"); console.log("Tests available at http://localhost:8000/");

File diff suppressed because it is too large Load diff

View file

@ -1,38 +1,37 @@
var test = require('tape'); let test = require("tape");
var fs = require('fs'); let fs = require("fs");
var path = require('path'); let path = require("path");
var PNG = require('../lib/png').PNG; let PNG = require("../lib/png").PNG;
var stream = require('stream'); let stream = require("stream");
function parseFile(filename, cb) { function parseFile(filename, cb) {
fs.createReadStream(path.join(__dirname, "png-parse-data", filename)) fs.createReadStream(path.join(__dirname, "png-parse-data", filename))
.pipe(new PNG()) .pipe(new PNG())
.on('error', function (e) { .on("error", function (e) {
console.log("error"); console.log("error");
cb(e); cb(e);
}) })
.on('parsed', function () { .on("parsed", function () {
cb(null, this); cb(null, this);
}); });
} }
function parseBuffer(buffer, cb) { function parseBuffer(buffer, cb) {
let bufferStream = new stream.PassThrough();
var bufferStream = new stream.PassThrough();
bufferStream.end(buffer); bufferStream.end(buffer);
bufferStream bufferStream
.pipe(new PNG({})) .pipe(new PNG({}))
.on('error', function (e) { .on("error", function (e) {
cb(e); cb(e);
}) })
.on('parse', function () { .on("parse", function () {
cb(null, this); cb(null, this);
}); });
} }
function getPixel(png, x, y) { function getPixel(png, x, y) {
return png.data.readUInt32BE((x + (y * png.width)) * 4); return png.data.readUInt32BE((x + y * png.width) * 4);
} }
test("should correctly parse an 1-bit colormap png", function (t) { test("should correctly parse an 1-bit colormap png", function (t) {
@ -45,15 +44,17 @@ test("should correctly parse an 1-bit colormap png", function (t) {
t.equal(png.data.length, 1024 * 1024 * 4); t.equal(png.data.length, 1024 * 1024 * 4);
//t.equal(png.trailer.length, 0); //t.equal(png.trailer.length, 0);
var y = 1024, let y = 1024,
x; x;
var isOk = true; let isOk = true;
while (y--) { while (y--) {
x = 1024; x = 1024;
while (x--) while (x--)
if (getPixel(png, x, y) !== 0x000000FF) { if (getPixel(png, x, y) !== 0x000000ff) {
t.fail("pixel does not match - " + getPixel(png, x, y) + " !== 0x000000FF"); t.fail(
"pixel does not match - " + getPixel(png, x, y) + " !== 0x000000FF"
);
isOk = false; isOk = false;
break; break;
} }
@ -73,15 +74,20 @@ test("should correctly parse an 8-bit grayscale png", function (t) {
t.equal(png.data.length, 16 * 16 * 4); t.equal(png.data.length, 16 * 16 * 4);
//t.equal(png.trailer.toString(), "Hello, world!\n"); //t.equal(png.trailer.toString(), "Hello, world!\n");
var y = 16, let y = 16,
x; x;
var isOk = true; let isOk = true;
while (y--) { while (y--) {
x = 16; x = 16;
while (x--) { while (x--) {
if (getPixel(png, x, y) !== (x ^ y) * 286331136 + 255) { if (getPixel(png, x, y) !== (x ^ y) * 286331136 + 255) {
t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + ((x ^ y) * 286331136 + 255)); t.fail(
"pixel does not match - " +
getPixel(png, x, y) +
" !== " +
((x ^ y) * 286331136 + 255)
);
isOk = false; isOk = false;
break; break;
} }
@ -90,7 +96,7 @@ test("should correctly parse an 8-bit grayscale png", function (t) {
t.ok(isOk, "The pixels should match"); t.ok(isOk, "The pixels should match");
t.end(); t.end();
}) });
}); });
test("should correctly parse an 8-bit truecolor png", function (t) { test("should correctly parse an 8-bit truecolor png", function (t) {
@ -102,15 +108,23 @@ test("should correctly parse an 8-bit truecolor png", function (t) {
t.equal(png.data.length, 16 * 16 * 4); t.equal(png.data.length, 16 * 16 * 4);
//t.equal(png.trailer.length, 0); //t.equal(png.trailer.length, 0);
var y = 16, let y = 16,
x; x;
var isOk = true; let isOk = true;
while (y--) { while (y--) {
x = 16; x = 16;
while (x--) { while (x--) {
if (getPixel(png, x, y) !== x * 285212672 + y * 1114112 + (x ^ y) * 4352 + 255) { if (
t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + (x * 285212672 + y * 1114112 + (x ^ y) * 4352 + 255)); getPixel(png, x, y) !==
x * 285212672 + y * 1114112 + (x ^ y) * 4352 + 255
) {
t.fail(
"pixel does not match - " +
getPixel(png, x, y) +
" !== " +
(x * 285212672 + y * 1114112 + (x ^ y) * 4352 + 255)
);
isOk = false; isOk = false;
break; break;
} }
@ -119,8 +133,8 @@ test("should correctly parse an 8-bit truecolor png", function (t) {
t.ok(isOk, "The pixels should match"); t.ok(isOk, "The pixels should match");
t.end(); t.end();
}) });
}) });
test("should correctly parse an 8-bit truecolor png with alpha", function (t) { test("should correctly parse an 8-bit truecolor png with alpha", function (t) {
parseFile("truecoloralpha.png", function (err, png) { parseFile("truecoloralpha.png", function (err, png) {
@ -131,15 +145,23 @@ test("should correctly parse an 8-bit truecolor png with alpha", function (t) {
t.equal(png.data.length, 16 * 16 * 4); t.equal(png.data.length, 16 * 16 * 4);
//t.equal(png.trailer.length, 0); //t.equal(png.trailer.length, 0);
var y = 16, let y = 16,
x; x;
var isOk = true; let isOk = true;
while (y--) { while (y--) {
x = 16; x = 16;
while (x--) { while (x--) {
if (getPixel(png, x, y) !== x * 285212672 + y * 1114112 + (x ^ y) * 17) { if (
t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + (x * 285212672 + y * 1114112 + (x ^ y) * 17)); getPixel(png, x, y) !==
x * 285212672 + y * 1114112 + (x ^ y) * 17
) {
t.fail(
"pixel does not match - " +
getPixel(png, x, y) +
" !== " +
(x * 285212672 + y * 1114112 + (x ^ y) * 17)
);
isOk = false; isOk = false;
break; break;
} }
@ -148,8 +170,8 @@ test("should correctly parse an 8-bit truecolor png with alpha", function (t) {
t.ok(isOk, "The pixels should match"); t.ok(isOk, "The pixels should match");
t.end(); t.end();
}) });
}) });
test("should correctly read image with scanline filter", function (t) { test("should correctly read image with scanline filter", function (t) {
parseFile("accum.png", function (err, png) { parseFile("accum.png", function (err, png) {
@ -160,16 +182,16 @@ test("should correctly read image with scanline filter", function (t) {
t.equal(png.data.length, 1024 * 1024 * 4); t.equal(png.data.length, 1024 * 1024 * 4);
//t.equal(png.trailer.length, 0); //t.equal(png.trailer.length, 0);
t.equal(getPixel(png, 0, 0), 0xFF0000FF); t.equal(getPixel(png, 0, 0), 0xff0000ff);
t.equal(getPixel(png, 1, 0), 0xFF0000FF); t.equal(getPixel(png, 1, 0), 0xff0000ff);
t.equal(getPixel(png, 420, 308), 0xFF0029FF); t.equal(getPixel(png, 420, 308), 0xff0029ff);
t.equal(getPixel(png, 433, 308), 0x0A299DFF); t.equal(getPixel(png, 433, 308), 0x0a299dff);
t.equal(getPixel(png, 513, 308), 0x0066FFFF); t.equal(getPixel(png, 513, 308), 0x0066ffff);
t.equal(getPixel(png, 728, 552), 0xFF0047FF); t.equal(getPixel(png, 728, 552), 0xff0047ff);
t.end(); t.end();
}) });
}) });
test("should correctly read an indexed color image", function (t) { test("should correctly read an indexed color image", function (t) {
parseFile("indexed.png", function (err, png) { parseFile("indexed.png", function (err, png) {
@ -180,29 +202,28 @@ test("should correctly read an indexed color image", function (t) {
t.equal(png.data.length, 16 * 16 * 4); t.equal(png.data.length, 16 * 16 * 4);
//t.equal(png.trailer.length, 0); //t.equal(png.trailer.length, 0);
var y = 16, let y = 16,
x; x;
var isOk = true; let isOk = true;
while (y--) { while (y--) {
x = 16; x = 16;
while (x--) { while (x--) {
var expected; let expected;
if (x + y < 8) { if (x + y < 8) {
expected = 0xFF0000FF; expected = 0xff0000ff;
} else if (x + y < 16) { } else if (x + y < 16) {
expected = 0x00FF00FF; expected = 0x00ff00ff;
} else if (x + y < 24) { } else if (x + y < 24) {
expected = 0x0000FFFF; expected = 0x0000ffff;
} else { } else {
expected = 0x000000FF; expected = 0x000000ff;
} }
if (getPixel(png, x, y) !== expected) { if (getPixel(png, x, y) !== expected) {
t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + expected); t.fail(
"pixel does not match - " + getPixel(png, x, y) + " !== " + expected
);
isOk = false; isOk = false;
break; break;
} }
@ -222,32 +243,30 @@ test("should correctly read an indexed color image with alpha", function (t) {
t.equal(png.data.length, 16 * 16 * 4); t.equal(png.data.length, 16 * 16 * 4);
//t.equal(png.trailer.length, 0); //t.equal(png.trailer.length, 0);
var y = 16, let y = 16,
x; x;
var isOk = true; let isOk = true;
while (y--) { while (y--) {
x = 16; x = 16;
while (x--) { while (x--) {
var expected; let expected;
if (x >= 4 && x < 12) { if (x >= 4 && x < 12) {
expected = 0x00000000; expected = 0x00000000;
} else if (x + y < 8) { } else if (x + y < 8) {
expected = 0xFF0000FF; expected = 0xff0000ff;
} else if (x + y < 16) { } else if (x + y < 16) {
expected = 0x00FF00FF; expected = 0x00ff00ff;
} else if (x + y < 24) { } else if (x + y < 24) {
expected = 0x0000FFFF; expected = 0x0000ffff;
} else { } else {
expected = 0x000000FF; expected = 0x000000ff;
} }
if (getPixel(png, x, y) !== expected) { if (getPixel(png, x, y) !== expected) {
t.fail("pixel does not match - " + getPixel(png, x, y) + " !== " + expected); t.fail(
"pixel does not match - " + getPixel(png, x, y) + " !== " + expected
);
isOk = false; isOk = false;
break; break;
} }
@ -267,70 +286,73 @@ test("should correctly support crazily-filtered images", function (t) {
//t.equal(png.bpp, 4); //t.equal(png.bpp, 4);
t.equal(png.data.length, 512 * 512 * 4); t.equal(png.data.length, 512 * 512 * 4);
t.equal(getPixel(png, 0, 0), 0xFF000000) t.equal(getPixel(png, 0, 0), 0xff000000);
t.equal(getPixel(png, 1, 0), 0xFF000000) t.equal(getPixel(png, 1, 0), 0xff000000);
t.equal(getPixel(png, 0, 1), 0xFF000000) t.equal(getPixel(png, 0, 1), 0xff000000);
t.equal(getPixel(png, 2, 2), 0xFF000000) t.equal(getPixel(png, 2, 2), 0xff000000);
t.equal(getPixel(png, 0, 50), 0xFF000000) t.equal(getPixel(png, 0, 50), 0xff000000);
t.equal(getPixel(png, 219, 248), 0xFF000D00) t.equal(getPixel(png, 219, 248), 0xff000d00);
t.equal(getPixel(png, 220, 248), 0xFF000D00) t.equal(getPixel(png, 220, 248), 0xff000d00);
t.equal(getPixel(png, 215, 249), 0xFF000C00) t.equal(getPixel(png, 215, 249), 0xff000c00);
t.equal(getPixel(png, 216, 249), 0xFF000C00) t.equal(getPixel(png, 216, 249), 0xff000c00);
t.equal(getPixel(png, 217, 249), 0xFF000D00) t.equal(getPixel(png, 217, 249), 0xff000d00);
t.equal(getPixel(png, 218, 249), 0xFF000D00) t.equal(getPixel(png, 218, 249), 0xff000d00);
t.equal(getPixel(png, 219, 249), 0xFF000E00) t.equal(getPixel(png, 219, 249), 0xff000e00);
t.equal(getPixel(png, 220, 249), 0xFF000E00) t.equal(getPixel(png, 220, 249), 0xff000e00);
t.equal(getPixel(png, 263, 319), 0xFF002100) t.equal(getPixel(png, 263, 319), 0xff002100);
t.equal(getPixel(png, 145, 318), 0x05535A00) t.equal(getPixel(png, 145, 318), 0x05535a00);
t.equal(getPixel(png, 395, 286), 0x0007FF00) t.equal(getPixel(png, 395, 286), 0x0007ff00);
t.equal(getPixel(png, 152, 167), 0x052C3500) t.equal(getPixel(png, 152, 167), 0x052c3500);
t.equal(getPixel(png, 153, 167), 0x04303600) t.equal(getPixel(png, 153, 167), 0x04303600);
t.equal(getPixel(png, 154, 167), 0x042F3700) t.equal(getPixel(png, 154, 167), 0x042f3700);
t.equal(getPixel(png, 100, 168), 0xFF000400) t.equal(getPixel(png, 100, 168), 0xff000400);
t.equal(getPixel(png, 120, 168), 0xFF000900) t.equal(getPixel(png, 120, 168), 0xff000900);
t.equal(getPixel(png, 140, 168), 0xFF001B00) t.equal(getPixel(png, 140, 168), 0xff001b00);
t.equal(getPixel(png, 150, 168), 0x05313600) t.equal(getPixel(png, 150, 168), 0x05313600);
t.equal(getPixel(png, 152, 168), 0x04343C00) t.equal(getPixel(png, 152, 168), 0x04343c00);
t.equal(getPixel(png, 153, 168), 0x03343F00) t.equal(getPixel(png, 153, 168), 0x03343f00);
t.equal(getPixel(png, 154, 168), 0x03344100) t.equal(getPixel(png, 154, 168), 0x03344100);
t.equal(getPixel(png, 155, 168), 0x02344300) t.equal(getPixel(png, 155, 168), 0x02344300);
t.equal(getPixel(png, 156, 168), 0x02314400) t.equal(getPixel(png, 156, 168), 0x02314400);
t.equal(getPixel(png, 157, 168), 0x02323F00) t.equal(getPixel(png, 157, 168), 0x02323f00);
t.equal(getPixel(png, 158, 168), 0x03313900) t.equal(getPixel(png, 158, 168), 0x03313900);
t.end(); t.end();
}); });
}); });
test("should bail with an error given an invalid PNG", function (t) { test("should bail with an error given an invalid PNG", function (t) {
var buf = Buffer.from("I AM NOT ACTUALLY A PNG", "utf8") let buf = Buffer.from("I AM NOT ACTUALLY A PNG", "utf8");
return parseBuffer(buf, function (err) { return parseBuffer(buf, function (err) {
t.ok(err instanceof Error, "Error should be received"); t.ok(err instanceof Error, "Error should be received");
t.end(); t.end();
}) });
}) });
test("should bail with an error given an empty file", function (t) { test("should bail with an error given an empty file", function (t) {
var buf = Buffer.from("") let buf = Buffer.from("");
return parseBuffer(buf, function (err) { return parseBuffer(buf, function (err) {
t.ok(err instanceof Error, "Error should be received"); t.ok(err instanceof Error, "Error should be received");
t.end(); t.end();
}) });
}) });
test("should bail with an error given a truncated PNG", function (t) { test("should bail with an error given a truncated PNG", function (t) {
var buf = Buffer.from("89504e470d0a1a0a000000", "hex") let buf = Buffer.from("89504e470d0a1a0a000000", "hex");
return parseBuffer(buf, function (err) { return parseBuffer(buf, function (err) {
t.ok(err instanceof Error, "Error should be received"); t.ok(err instanceof Error, "Error should be received");
t.end(); t.end();
}) });
}) });
test("should return an error if a PNG is normal except for a missing IEND", function (t) { test("should return an error if a PNG is normal except for a missing IEND", function (t) {
var buf = Buffer.from("89504e470d0a1a0a0000000d49484452000000100000001008000000003a98a0bd000000017352474200aece1ce90000002174455874536f6674776172650047726170686963436f6e7665727465722028496e74656c297787fa190000008849444154789c448e4111c020100363010b58c00216b080052c60010b58c0c259c00216ae4d3b69df99dd0d1062caa5b63ee6b27d1c012996dceae86b6ef38398106acb65ae3e8edbbef780564b5e73743fdb409e1ef2f4803c3de4e901797ac8d3f3f0f490a7077ffffd03f5f507eaeb0fd4d71fa8af3f505f7fa0befe7c7dfdb9000000ffff0300c0fd7f8179301408", "hex") let buf = Buffer.from(
"89504e470d0a1a0a0000000d49484452000000100000001008000000003a98a0bd000000017352474200aece1ce90000002174455874536f6674776172650047726170686963436f6e7665727465722028496e74656c297787fa190000008849444154789c448e4111c020100363010b58c00216b080052c60010b58c0c259c00216ae4d3b69df99dd0d1062caa5b63ee6b27d1c012996dceae86b6ef38398106acb65ae3e8edbbef780564b5e73743fdb409e1ef2f4803c3de4e901797ac8d3f3f0f490a7077ffffd03f5f507eaeb0fd4d71fa8af3f505f7fa0befe7c7dfdb9000000ffff0300c0fd7f8179301408",
"hex"
);
return parseBuffer(buf, function (err) { return parseBuffer(buf, function (err) {
t.ok(err instanceof Error, "Error should be received"); t.ok(err instanceof Error, "Error should be received");
@ -341,20 +363,22 @@ test("should return an error if a PNG is normal except for a missing IEND", func
test("should set alpha=true in metadata for images with tRNS chunk", function (t) { test("should set alpha=true in metadata for images with tRNS chunk", function (t) {
fs.createReadStream(path.join(__dirname, "in", "tbbn0g04.png")) fs.createReadStream(path.join(__dirname, "in", "tbbn0g04.png"))
.pipe(new PNG()) .pipe(new PNG())
.on('metadata', function (metadata) { .on("metadata", function (metadata) {
t.ok(metadata.alpha, "Image should have alpha=true"); t.ok(metadata.alpha, "Image should have alpha=true");
t.end(); t.end();
}); });
}); });
test("Should parse with low highWaterMark", function (t) { test("Should parse with low highWaterMark", function (t) {
fs.createReadStream(path.join(__dirname, "in", "tbbn0g04.png"), { highWaterMark: 2 }) fs.createReadStream(path.join(__dirname, "in", "tbbn0g04.png"), {
highWaterMark: 2,
})
.pipe(new PNG()) .pipe(new PNG())
.on('parsed', function () { .on("parsed", function () {
t.pass("Image should have parsed"); t.pass("Image should have parsed");
t.end(); t.end();
}) })
.on('error', function (e) { .on("error", function (e) {
t.error(e, "Should not error"); t.error(e, "Should not error");
}); });
}); });

View file

@ -1,17 +1,22 @@
require('./http-server') const closeServer = require("./http-server");
const puppeteer = require('puppeteer'); const puppeteer = require("puppeteer");
const URL = 'http://localhost:8000'; const URL = "http://localhost:8000";
puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }).then(async browser => { puppeteer
.launch({
headless: true,
args: ["--no-sandbox", "--disable-setuid-sandbox"],
})
.then(async (browser) => {
const page = await browser.newPage(); const page = await browser.newPage();
await page.goto(URL, {waitUntil: 'networkidle0'}); await page.goto(URL, { waitUntil: "networkidle0" });
const results = await page.evaluate(() => { const results = await page.evaluate(() => {
/* global window:false */
try { try {
if (window.isFinished && window.isFinished()) { if (window.isFinished && window.isFinished()) {
return window.results; return window.results;
} }
} catch(err) { } catch (err) {
reject(err.toString());
console.log("Failed", err); console.log("Failed", err);
} }
}); });
@ -19,24 +24,34 @@ puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sand
console.log("Comparison Test Results:"); console.log("Comparison Test Results:");
await browser.close(); await browser.close();
if (results) { if (results) {
var success = true; let success = true;
var successes = [],failures = []; let successes = [],
for (var i = 0; i < results.length; i++) { failures = [];
var result = results[i]; for (let i = 0; i < results.length; i++) {
if (result.success) { let result = results[i];
successes.push(result.name); if (result.success) {
} else { successes.push(result.name);
failures.push(result.name); } else {
} failures.push(result.name);
success = success && result.success; }
success = success && result.success;
} }
console.log("Success:", successes.join(", ")); console.log("Success:", successes.join(", "));
if (failures.length) { if (failures.length) {
console.log("Failure:", failures.join(", ")); console.log("Failure:", failures.join(", "));
if (failures.length > 10) {
console.error("failures higher than expected");
process.exitCode = 1;
}
} }
} else {
process.exitCode = 1;
} }
process.exit(); })
}).catch(function(error) { .catch((error) => {
console.error(error); console.error(error);
process.exit(); process.exitCode = 1;
}); })
.finally(() => {
closeServer();
});

1676
yarn.lock

File diff suppressed because it is too large Load diff