Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0feb4156c | ||
|
|
0d1278dade | ||
|
|
1b401b1195 | ||
|
|
11daa3b4d1 | ||
|
|
88a3919ce0 | ||
|
|
c41b87303d | ||
|
|
833aaead56 | ||
|
|
ff98d2e44a | ||
|
|
fcf05f608a | ||
|
|
9baf38db44 | ||
|
|
69050ef1c8 | ||
|
|
b35b9f7850 | ||
|
|
500ae97cac | ||
|
|
d5b7040557 | ||
|
|
ca52894651 | ||
|
|
4009acdd30 | ||
|
|
147c93ecd3 | ||
|
|
8e04e4b07f | ||
|
|
e7413ea1e5 | ||
|
|
220bb03a32 | ||
|
|
20f512fe5f | ||
|
|
efb3523eaa | ||
|
|
2f2276e091 | ||
|
|
08a6597626 | ||
|
|
d82a6ee4fc | ||
|
|
e627f6d68d | ||
|
|
e650f58bd8 | ||
|
|
5a9b6c8afd | ||
|
|
075771d1e9 | ||
|
|
4fcf091fef | ||
|
|
0e66454fe4 | ||
|
|
aa3ce760bb | ||
|
|
ba46ad1fd9 | ||
|
|
11214bab5d | ||
|
|
d87c289b4a | ||
|
|
af45c03b6f | ||
|
|
7d6fadce6b | ||
|
|
6b560f7a85 | ||
|
|
5d4221460d | ||
|
|
d42c383992 | ||
|
|
9c7f6fcb2b | ||
|
|
14af0bda61 | ||
|
|
fb5c393fbd | ||
|
|
69fe21a7ec | ||
|
|
da4e05c118 | ||
|
|
e4333ff6b0 | ||
|
|
4ae8999f62 | ||
|
|
3fa91bb4ce | ||
|
|
23b2e541ab | ||
|
|
5bfcf61a6f | ||
|
|
0778c112a9 | ||
|
|
2c300754a7 |
13
.cirrus.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-0
|
||||
|
||||
task:
|
||||
prerequisites_script:
|
||||
- sed -i '' 's/quarterly/latest/g' /etc/pkg/FreeBSD.conf
|
||||
- pkg update -f
|
||||
- pkg upgrade -y
|
||||
- pkg install -y pkgconf vips libnghttp2 node npm
|
||||
install_script:
|
||||
- npm install --unsafe-perm
|
||||
test_script:
|
||||
- npm test
|
||||
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
open_collective: libvips
|
||||
14
.github/ISSUE_TEMPLATE/installation.md
vendored
@@ -1,16 +1,18 @@
|
||||
---
|
||||
name: Installation
|
||||
about: For help if something went wrong installing sharp
|
||||
about: Something went wrong **installing** sharp
|
||||
title: ''
|
||||
labels: ''
|
||||
labels: installation
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
What is the output of running `npm install --verbose sharp`?
|
||||
|
||||
What is the output of running `npx envinfo --binaries --languages --system --utilities`?
|
||||
Did you see the [documentation relating to installation](https://sharp.pixelplumbing.com/en/stable/install/)?
|
||||
|
||||
Have you ensured the platform and version of Node.js used for `npm install` is the same as the platform and version of Node.js used at runtime?
|
||||
|
||||
If you're using `sudo npm install` have you tried with the `sudo npm install --unsafe-perm` flag?
|
||||
If you are installing as a `root` or `sudo` user, have you tried with the `npm install --unsafe-perm` flag?
|
||||
|
||||
What is the complete output of running `npm install --verbose sharp`? Have you checked this output for useful error messages?
|
||||
|
||||
What is the output of running `npx envinfo --binaries --languages --system --utilities`?
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/possible-bug.md
vendored
@@ -1,12 +1,14 @@
|
||||
---
|
||||
name: Possible bug
|
||||
about: Please provide steps to reproduce
|
||||
about: Something unexpected occurred **using** sharp
|
||||
title: ''
|
||||
labels: ''
|
||||
labels: triage
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- If this issue relates to installation, please use https://github.com/lovell/sharp/issues/new?labels=installation&template=installation.md instead. -->
|
||||
|
||||
What is the output of running `npx envinfo --binaries --languages --system --utilities`?
|
||||
|
||||
What are the steps to reproduce?
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -1,12 +1,14 @@
|
||||
---
|
||||
name: Question
|
||||
about: For help with an existing feature
|
||||
about: For help understanding an existing feature
|
||||
title: ''
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- If this issue relates to installation, please use https://github.com/lovell/sharp/issues/new?labels=installation&template=installation.md instead. -->
|
||||
|
||||
What are you trying to achieve?
|
||||
|
||||
Have you searched for similar questions?
|
||||
|
||||
1
.gitignore
vendored
@@ -14,3 +14,4 @@ vendor
|
||||
.nyc_output
|
||||
.vscode/
|
||||
package-lock.json
|
||||
.idea
|
||||
|
||||
16
.npmignore
@@ -1,16 +0,0 @@
|
||||
build
|
||||
node_modules
|
||||
coverage
|
||||
.editorconfig
|
||||
.gitattributes
|
||||
.gitignore
|
||||
test
|
||||
.travis.yml
|
||||
appveyor.yml
|
||||
mkdocs.yml
|
||||
docs/css/
|
||||
vendor
|
||||
.prebuildrc
|
||||
.nyc_output
|
||||
.github/
|
||||
.vscode/
|
||||
23
.travis.yml
@@ -18,6 +18,12 @@ matrix:
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js: "12"
|
||||
- name: "Linux (glibc) - Node 13"
|
||||
os: linux
|
||||
dist: trusty
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js: "13"
|
||||
after_success:
|
||||
- npm install coveralls
|
||||
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
|
||||
@@ -51,6 +57,16 @@ matrix:
|
||||
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
||||
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
||||
script: sudo docker exec sharp sh -c "npm test"
|
||||
- name: "Linux (musl) - Node 13"
|
||||
os: linux
|
||||
dist: trusty
|
||||
sudo: true
|
||||
language: minimal
|
||||
before_install:
|
||||
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp node:13.0-alpine
|
||||
- sudo docker exec sharp apk add build-base git python2 --update-cache
|
||||
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
|
||||
script: sudo docker exec sharp sh -c "npm test"
|
||||
- name: "OS X - Node 8"
|
||||
os: osx
|
||||
osx_image: xcode9.2
|
||||
@@ -66,3 +82,10 @@ matrix:
|
||||
osx_image: xcode9.2
|
||||
language: node_js
|
||||
node_js: "12"
|
||||
- name: "OS X - Node 13"
|
||||
os: osx
|
||||
osx_image: xcode10
|
||||
language: node_js
|
||||
node_js: "13"
|
||||
cache:
|
||||
npm: false
|
||||
|
||||
@@ -11,7 +11,8 @@ is to convert large images in common formats to
|
||||
smaller, web-friendly JPEG, PNG and WebP images of varying dimensions.
|
||||
|
||||
Resizing an image is typically 4x-5x faster than using the
|
||||
quickest ImageMagick and GraphicsMagick settings.
|
||||
quickest ImageMagick and GraphicsMagick settings
|
||||
due to its use of [libvips](https://github.com/libvips/libvips).
|
||||
|
||||
Colour spaces, embedded ICC profiles and alpha transparency channels are all handled correctly.
|
||||
Lanczos resampling ensures quality is not sacrificed for speed.
|
||||
@@ -20,7 +21,7 @@ As well as image resizing, operations such as
|
||||
rotation, extraction, compositing and gamma correction are available.
|
||||
|
||||
Most modern 64-bit OS X, Windows and Linux systems running
|
||||
Node versions 8, 10 and 12
|
||||
Node versions 8, 10, 12 and 13
|
||||
do not require any additional install or runtime dependencies.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -7,6 +7,7 @@ environment:
|
||||
- nodejs_version: "8"
|
||||
- nodejs_version: "10"
|
||||
- nodejs_version: "12"
|
||||
- nodejs_version: "13"
|
||||
install:
|
||||
- ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) x64
|
||||
- npm install -g npm@6
|
||||
|
||||
26
binding.gyp
@@ -183,16 +183,22 @@
|
||||
},
|
||||
'configurations': {
|
||||
'Release': {
|
||||
'cflags_cc': [
|
||||
'-Wno-cast-function-type'
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'ExceptionHandling': 1
|
||||
}
|
||||
},
|
||||
'msvs_disabled_warnings': [
|
||||
4275
|
||||
'conditions': [
|
||||
['OS == "linux"', {
|
||||
'cflags_cc': [
|
||||
'-Wno-cast-function-type'
|
||||
]
|
||||
}],
|
||||
['OS == "win"', {
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'ExceptionHandling': 1
|
||||
}
|
||||
},
|
||||
'msvs_disabled_warnings': [
|
||||
4275
|
||||
]
|
||||
}]
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -31,6 +31,7 @@ and [https://www.cairographics.org/operators/][2]
|
||||
- `images[].top` **[Number][7]?** the pixel offset from the top edge.
|
||||
- `images[].left` **[Number][7]?** the pixel offset from the left edge.
|
||||
- `images[].tile` **[Boolean][9]** set to true to repeat the overlay image across the entire image with the given `gravity`. (optional, default `false`)
|
||||
- `images[].premultiplied` **[Boolean][9]** set to true to avoid premultipling the image below. Equivalent to the `--premultiplied` vips option. (optional, default `false`)
|
||||
- `images[].density` **[Number][7]** number representing the DPI for vector overlay image. (optional, default `72`)
|
||||
- `images[].raw` **[Object][4]?** describes overlay when using raw pixel data.
|
||||
- `images[].raw.width` **[Number][7]?**
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
- `input` **([Buffer][1] \| [String][2])?** if present, can be
|
||||
a Buffer containing JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data, or
|
||||
a String containing the path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.
|
||||
a String containing the filesystem path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.
|
||||
JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
|
||||
- `options` **[Object][3]?** if present, is an Object with optional attributes.
|
||||
- `options.failOnError` **[Boolean][4]** by default halt processing and raise an error when loading invalid images.
|
||||
|
||||
@@ -8,12 +8,15 @@ If an explicit output format is not selected, it will be inferred from the exten
|
||||
with JPEG, PNG, WebP, TIFF, DZI, and libvips' V format supported.
|
||||
Note that raw pixel data is only supported for buffer output.
|
||||
|
||||
By default all metadata will be removed, which includes EXIF-based orientation.
|
||||
See [withMetadata][1] for control over this.
|
||||
|
||||
A `Promise` is returned when `callback` is not provided.
|
||||
|
||||
### Parameters
|
||||
|
||||
- `fileOut` **[String][1]** the path to write the image data to.
|
||||
- `callback` **[Function][2]?** called on completion with two arguments `(err, info)`.
|
||||
- `fileOut` **[String][2]** the path to write the image data to.
|
||||
- `callback` **[Function][3]?** called on completion with two arguments `(err, info)`.
|
||||
`info` contains the output image `format`, `size` (bytes), `width`, `height`,
|
||||
`channels` and `premultiplied` (indicating if premultiplication was used).
|
||||
When using a crop strategy also contains `cropOffsetLeft` and `cropOffsetTop`.
|
||||
@@ -32,15 +35,19 @@ sharp(input)
|
||||
.catch(err => { ... });
|
||||
```
|
||||
|
||||
- Throws **[Error][3]** Invalid parameters
|
||||
- Throws **[Error][4]** Invalid parameters
|
||||
|
||||
Returns **[Promise][4]<[Object][5]>** when no callback is provided
|
||||
Returns **[Promise][5]<[Object][6]>** when no callback is provided
|
||||
|
||||
## toBuffer
|
||||
|
||||
Write output to a Buffer.
|
||||
JPEG, PNG, WebP, TIFF and RAW output are supported.
|
||||
By default, the format will match the input image, except GIF and SVG input which become PNG output.
|
||||
|
||||
If no explicit format is set, the output format will match the input image, except GIF and SVG input which become PNG output.
|
||||
|
||||
By default all metadata will be removed, which includes EXIF-based orientation.
|
||||
See [withMetadata][1] for control over this.
|
||||
|
||||
`callback`, if present, gets three arguments `(err, data, info)` where:
|
||||
|
||||
@@ -54,9 +61,9 @@ A `Promise` is returned when `callback` is not provided.
|
||||
|
||||
### Parameters
|
||||
|
||||
- `options` **[Object][5]?**
|
||||
- `options.resolveWithObject` **[Boolean][6]?** Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
|
||||
- `callback` **[Function][2]?**
|
||||
- `options` **[Object][6]?**
|
||||
- `options.resolveWithObject` **[Boolean][7]?** Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
|
||||
- `callback` **[Function][3]?**
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -79,7 +86,7 @@ sharp(input)
|
||||
.catch(err => { ... });
|
||||
```
|
||||
|
||||
Returns **[Promise][4]<[Buffer][7]>** when no callback is provided
|
||||
Returns **[Promise][5]<[Buffer][8]>** when no callback is provided
|
||||
|
||||
## withMetadata
|
||||
|
||||
@@ -89,8 +96,8 @@ This will also convert to and add a web-friendly sRGB ICC profile.
|
||||
|
||||
### Parameters
|
||||
|
||||
- `options` **[Object][5]?**
|
||||
- `options.orientation` **[Number][8]?** value between 1 and 8, used to update the EXIF `Orientation` tag.
|
||||
- `options` **[Object][6]?**
|
||||
- `options.orientation` **[Number][9]?** value between 1 and 8, used to update the EXIF `Orientation` tag.
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -101,7 +108,7 @@ sharp('input.jpg')
|
||||
.then(info => { ... });
|
||||
```
|
||||
|
||||
- Throws **[Error][3]** Invalid parameters
|
||||
- Throws **[Error][4]** Invalid parameters
|
||||
|
||||
Returns **Sharp**
|
||||
|
||||
@@ -111,19 +118,19 @@ Use these JPEG options for output image.
|
||||
|
||||
### Parameters
|
||||
|
||||
- `options` **[Object][5]?** output options
|
||||
- `options.quality` **[Number][8]** quality, integer 1-100 (optional, default `80`)
|
||||
- `options.progressive` **[Boolean][6]** use progressive (interlace) scan (optional, default `false`)
|
||||
- `options.chromaSubsampling` **[String][1]** set to '4:4:4' to prevent chroma subsampling when quality <= 90 (optional, default `'4:2:0'`)
|
||||
- `options.trellisQuantisation` **[Boolean][6]** apply trellis quantisation, requires libvips compiled with support for mozjpeg (optional, default `false`)
|
||||
- `options.overshootDeringing` **[Boolean][6]** apply overshoot deringing, requires libvips compiled with support for mozjpeg (optional, default `false`)
|
||||
- `options.optimiseScans` **[Boolean][6]** optimise progressive scans, forces progressive, requires libvips compiled with support for mozjpeg (optional, default `false`)
|
||||
- `options.optimizeScans` **[Boolean][6]** alternative spelling of optimiseScans (optional, default `false`)
|
||||
- `options.optimiseCoding` **[Boolean][6]** optimise Huffman coding tables (optional, default `true`)
|
||||
- `options.optimizeCoding` **[Boolean][6]** alternative spelling of optimiseCoding (optional, default `true`)
|
||||
- `options.quantisationTable` **[Number][8]** quantization table to use, integer 0-8, requires libvips compiled with support for mozjpeg (optional, default `0`)
|
||||
- `options.quantizationTable` **[Number][8]** alternative spelling of quantisationTable (optional, default `0`)
|
||||
- `options.force` **[Boolean][6]** force JPEG output, otherwise attempt to use input format (optional, default `true`)
|
||||
- `options` **[Object][6]?** output options
|
||||
- `options.quality` **[Number][9]** quality, integer 1-100 (optional, default `80`)
|
||||
- `options.progressive` **[Boolean][7]** use progressive (interlace) scan (optional, default `false`)
|
||||
- `options.chromaSubsampling` **[String][2]** set to '4:4:4' to prevent chroma subsampling when quality <= 90 (optional, default `'4:2:0'`)
|
||||
- `options.trellisQuantisation` **[Boolean][7]** apply trellis quantisation, requires libvips compiled with support for mozjpeg (optional, default `false`)
|
||||
- `options.overshootDeringing` **[Boolean][7]** apply overshoot deringing, requires libvips compiled with support for mozjpeg (optional, default `false`)
|
||||
- `options.optimiseScans` **[Boolean][7]** optimise progressive scans, forces progressive, requires libvips compiled with support for mozjpeg (optional, default `false`)
|
||||
- `options.optimizeScans` **[Boolean][7]** alternative spelling of optimiseScans (optional, default `false`)
|
||||
- `options.optimiseCoding` **[Boolean][7]** optimise Huffman coding tables (optional, default `true`)
|
||||
- `options.optimizeCoding` **[Boolean][7]** alternative spelling of optimiseCoding (optional, default `true`)
|
||||
- `options.quantisationTable` **[Number][9]** quantization table to use, integer 0-8, requires libvips compiled with support for mozjpeg (optional, default `0`)
|
||||
- `options.quantizationTable` **[Number][9]** alternative spelling of quantisationTable (optional, default `0`)
|
||||
- `options.force` **[Boolean][7]** force JPEG output, otherwise attempt to use input format (optional, default `true`)
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -137,7 +144,7 @@ const data = await sharp(input)
|
||||
.toBuffer();
|
||||
```
|
||||
|
||||
- Throws **[Error][3]** Invalid options
|
||||
- Throws **[Error][4]** Invalid options
|
||||
|
||||
Returns **Sharp**
|
||||
|
||||
@@ -150,16 +157,16 @@ Indexed PNG input at 1, 2 or 4 bits per pixel is converted to 8 bits per pixel.
|
||||
|
||||
### Parameters
|
||||
|
||||
- `options` **[Object][5]?**
|
||||
- `options.progressive` **[Boolean][6]** use progressive (interlace) scan (optional, default `false`)
|
||||
- `options.compressionLevel` **[Number][8]** zlib compression level, 0-9 (optional, default `9`)
|
||||
- `options.adaptiveFiltering` **[Boolean][6]** use adaptive row filtering (optional, default `false`)
|
||||
- `options.palette` **[Boolean][6]** quantise to a palette-based image with alpha transparency support, requires libvips compiled with support for libimagequant (optional, default `false`)
|
||||
- `options.quality` **[Number][8]** use the lowest number of colours needed to achieve given quality, requires libvips compiled with support for libimagequant (optional, default `100`)
|
||||
- `options.colours` **[Number][8]** maximum number of palette entries, requires libvips compiled with support for libimagequant (optional, default `256`)
|
||||
- `options.colors` **[Number][8]** alternative spelling of `options.colours`, requires libvips compiled with support for libimagequant (optional, default `256`)
|
||||
- `options.dither` **[Number][8]** level of Floyd-Steinberg error diffusion, requires libvips compiled with support for libimagequant (optional, default `1.0`)
|
||||
- `options.force` **[Boolean][6]** force PNG output, otherwise attempt to use input format (optional, default `true`)
|
||||
- `options` **[Object][6]?**
|
||||
- `options.progressive` **[Boolean][7]** use progressive (interlace) scan (optional, default `false`)
|
||||
- `options.compressionLevel` **[Number][9]** zlib compression level, 0-9 (optional, default `9`)
|
||||
- `options.adaptiveFiltering` **[Boolean][7]** use adaptive row filtering (optional, default `false`)
|
||||
- `options.palette` **[Boolean][7]** quantise to a palette-based image with alpha transparency support, requires libvips compiled with support for libimagequant (optional, default `false`)
|
||||
- `options.quality` **[Number][9]** use the lowest number of colours needed to achieve given quality, requires libvips compiled with support for libimagequant (optional, default `100`)
|
||||
- `options.colours` **[Number][9]** maximum number of palette entries, requires libvips compiled with support for libimagequant (optional, default `256`)
|
||||
- `options.colors` **[Number][9]** alternative spelling of `options.colours`, requires libvips compiled with support for libimagequant (optional, default `256`)
|
||||
- `options.dither` **[Number][9]** level of Floyd-Steinberg error diffusion, requires libvips compiled with support for libimagequant (optional, default `1.0`)
|
||||
- `options.force` **[Boolean][7]** force PNG output, otherwise attempt to use input format (optional, default `true`)
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -170,7 +177,7 @@ const data = await sharp(input)
|
||||
.toBuffer();
|
||||
```
|
||||
|
||||
- Throws **[Error][3]** Invalid options
|
||||
- Throws **[Error][4]** Invalid options
|
||||
|
||||
Returns **Sharp**
|
||||
|
||||
@@ -180,14 +187,14 @@ Use these WebP options for output image.
|
||||
|
||||
### Parameters
|
||||
|
||||
- `options` **[Object][5]?** output options
|
||||
- `options.quality` **[Number][8]** quality, integer 1-100 (optional, default `80`)
|
||||
- `options.alphaQuality` **[Number][8]** quality of alpha layer, integer 0-100 (optional, default `100`)
|
||||
- `options.lossless` **[Boolean][6]** use lossless compression mode (optional, default `false`)
|
||||
- `options.nearLossless` **[Boolean][6]** use near_lossless compression mode (optional, default `false`)
|
||||
- `options.smartSubsample` **[Boolean][6]** use high quality chroma subsampling (optional, default `false`)
|
||||
- `options.reductionEffort` **[Number][8]** level of CPU effort to reduce file size, integer 0-6 (optional, default `4`)
|
||||
- `options.force` **[Boolean][6]** force WebP output, otherwise attempt to use input format (optional, default `true`)
|
||||
- `options` **[Object][6]?** output options
|
||||
- `options.quality` **[Number][9]** quality, integer 1-100 (optional, default `80`)
|
||||
- `options.alphaQuality` **[Number][9]** quality of alpha layer, integer 0-100 (optional, default `100`)
|
||||
- `options.lossless` **[Boolean][7]** use lossless compression mode (optional, default `false`)
|
||||
- `options.nearLossless` **[Boolean][7]** use near_lossless compression mode (optional, default `false`)
|
||||
- `options.smartSubsample` **[Boolean][7]** use high quality chroma subsampling (optional, default `false`)
|
||||
- `options.reductionEffort` **[Number][9]** level of CPU effort to reduce file size, integer 0-6 (optional, default `4`)
|
||||
- `options.force` **[Boolean][7]** force WebP output, otherwise attempt to use input format (optional, default `true`)
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -198,7 +205,7 @@ const data = await sharp(input)
|
||||
.toBuffer();
|
||||
```
|
||||
|
||||
- Throws **[Error][3]** Invalid options
|
||||
- Throws **[Error][4]** Invalid options
|
||||
|
||||
Returns **Sharp**
|
||||
|
||||
@@ -208,18 +215,18 @@ Use these TIFF options for output image.
|
||||
|
||||
### Parameters
|
||||
|
||||
- `options` **[Object][5]?** output options
|
||||
- `options.quality` **[Number][8]** quality, integer 1-100 (optional, default `80`)
|
||||
- `options.force` **[Boolean][6]** force TIFF output, otherwise attempt to use input format (optional, default `true`)
|
||||
- `options.compression` **[Boolean][6]** compression options: lzw, deflate, jpeg, ccittfax4 (optional, default `'jpeg'`)
|
||||
- `options.predictor` **[Boolean][6]** compression predictor options: none, horizontal, float (optional, default `'horizontal'`)
|
||||
- `options.pyramid` **[Boolean][6]** write an image pyramid (optional, default `false`)
|
||||
- `options.tile` **[Boolean][6]** write a tiled tiff (optional, default `false`)
|
||||
- `options.tileWidth` **[Boolean][6]** horizontal tile size (optional, default `256`)
|
||||
- `options.tileHeight` **[Boolean][6]** vertical tile size (optional, default `256`)
|
||||
- `options.xres` **[Number][8]** horizontal resolution in pixels/mm (optional, default `1.0`)
|
||||
- `options.yres` **[Number][8]** vertical resolution in pixels/mm (optional, default `1.0`)
|
||||
- `options.squash` **[Boolean][6]** squash 8-bit images down to 1 bit (optional, default `false`)
|
||||
- `options` **[Object][6]?** output options
|
||||
- `options.quality` **[Number][9]** quality, integer 1-100 (optional, default `80`)
|
||||
- `options.force` **[Boolean][7]** force TIFF output, otherwise attempt to use input format (optional, default `true`)
|
||||
- `options.compression` **[Boolean][7]** compression options: lzw, deflate, jpeg, ccittfax4 (optional, default `'jpeg'`)
|
||||
- `options.predictor` **[Boolean][7]** compression predictor options: none, horizontal, float (optional, default `'horizontal'`)
|
||||
- `options.pyramid` **[Boolean][7]** write an image pyramid (optional, default `false`)
|
||||
- `options.tile` **[Boolean][7]** write a tiled tiff (optional, default `false`)
|
||||
- `options.tileWidth` **[Boolean][7]** horizontal tile size (optional, default `256`)
|
||||
- `options.tileHeight` **[Boolean][7]** vertical tile size (optional, default `256`)
|
||||
- `options.xres` **[Number][9]** horizontal resolution in pixels/mm (optional, default `1.0`)
|
||||
- `options.yres` **[Number][9]** vertical resolution in pixels/mm (optional, default `1.0`)
|
||||
- `options.squash` **[Boolean][7]** squash 8-bit images down to 1 bit (optional, default `false`)
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -234,7 +241,7 @@ sharp('input.svg')
|
||||
.then(info => { ... });
|
||||
```
|
||||
|
||||
- Throws **[Error][3]** Invalid options
|
||||
- Throws **[Error][4]** Invalid options
|
||||
|
||||
Returns **Sharp**
|
||||
|
||||
@@ -251,13 +258,13 @@ Most versions of libheif support only the patent-encumbered HEVC compression for
|
||||
|
||||
### Parameters
|
||||
|
||||
- `options` **[Object][5]?** output options
|
||||
- `options.quality` **[Number][8]** quality, integer 1-100 (optional, default `80`)
|
||||
- `options.compression` **[Boolean][6]** compression format: hevc, avc, jpeg, av1 (optional, default `'hevc'`)
|
||||
- `options.lossless` **[Boolean][6]** use lossless compression (optional, default `false`)
|
||||
- `options` **[Object][6]?** output options
|
||||
- `options.quality` **[Number][9]** quality, integer 1-100 (optional, default `80`)
|
||||
- `options.compression` **[Boolean][7]** compression format: hevc, avc, jpeg, av1 (optional, default `'hevc'`)
|
||||
- `options.lossless` **[Boolean][7]** use lossless compression (optional, default `false`)
|
||||
|
||||
|
||||
- Throws **[Error][3]** Invalid options
|
||||
- Throws **[Error][4]** Invalid options
|
||||
|
||||
Returns **Sharp**
|
||||
|
||||
@@ -282,8 +289,8 @@ Force output to a given format.
|
||||
|
||||
### Parameters
|
||||
|
||||
- `format` **([String][1] \| [Object][5])** as a String or an Object with an 'id' attribute
|
||||
- `options` **[Object][5]** output options
|
||||
- `format` **([String][2] \| [Object][6])** as a String or an Object with an 'id' attribute
|
||||
- `options` **[Object][6]** output options
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -294,7 +301,7 @@ const data = await sharp(input)
|
||||
.toBuffer();
|
||||
```
|
||||
|
||||
- Throws **[Error][3]** unsupported format or options
|
||||
- Throws **[Error][4]** unsupported format or options
|
||||
|
||||
Returns **Sharp**
|
||||
|
||||
@@ -308,14 +315,15 @@ Warning: multiple sharp instances concurrently producing tile output can expose
|
||||
|
||||
### Parameters
|
||||
|
||||
- `options` **[Object][5]?**
|
||||
- `options.size` **[Number][8]** tile size in pixels, a value between 1 and 8192. (optional, default `256`)
|
||||
- `options.overlap` **[Number][8]** tile overlap in pixels, a value between 0 and 8192. (optional, default `0`)
|
||||
- `options.angle` **[Number][8]** tile angle of rotation, must be a multiple of 90. (optional, default `0`)
|
||||
- `options.depth` **[String][1]?** how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
|
||||
- `options.skipBlanks` **[Number][8]** threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images (optional, default `-1`)
|
||||
- `options.container` **[String][1]** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`)
|
||||
- `options.layout` **[String][1]** filesystem layout, possible values are `dz`, `zoomify` or `google`. (optional, default `'dz'`)
|
||||
- `options` **[Object][6]?**
|
||||
- `options.size` **[Number][9]** tile size in pixels, a value between 1 and 8192. (optional, default `256`)
|
||||
- `options.overlap` **[Number][9]** tile overlap in pixels, a value between 0 and 8192. (optional, default `0`)
|
||||
- `options.angle` **[Number][9]** tile angle of rotation, must be a multiple of 90. (optional, default `0`)
|
||||
- `options.background` **([String][2] \| [Object][6])** background colour, parsed by the [color][10] module, defaults to white without transparency. (optional, default `{r:255,g:255,b:255,alpha:1}`)
|
||||
- `options.depth` **[String][2]?** how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
|
||||
- `options.skipBlanks` **[Number][9]** threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images (optional, default `-1`)
|
||||
- `options.container` **[String][2]** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`)
|
||||
- `options.layout` **[String][2]** filesystem layout, possible values are `dz`, `zoomify` or `google`. (optional, default `'dz'`)
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -331,22 +339,26 @@ sharp('input.tiff')
|
||||
});
|
||||
```
|
||||
|
||||
- Throws **[Error][3]** Invalid parameters
|
||||
- Throws **[Error][4]** Invalid parameters
|
||||
|
||||
Returns **Sharp**
|
||||
|
||||
[1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
||||
[1]: #withmetadata
|
||||
|
||||
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
|
||||
[2]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
||||
|
||||
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
|
||||
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
|
||||
|
||||
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
||||
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
|
||||
|
||||
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
|
||||
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
||||
|
||||
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
|
||||
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
|
||||
|
||||
[7]: https://nodejs.org/api/buffer.html
|
||||
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
|
||||
|
||||
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
|
||||
[8]: https://nodejs.org/api/buffer.html
|
||||
|
||||
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
|
||||
|
||||
[10]: https://www.npmjs.org/package/color
|
||||
|
||||
@@ -196,6 +196,8 @@ Returns **Sharp**
|
||||
## trim
|
||||
|
||||
Trim "boring" pixels from all edges that contain values similar to the top-left pixel.
|
||||
Images consisting entirely of a single colour will calculate "boring" using the alpha channel, if any.
|
||||
|
||||
The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` properties.
|
||||
|
||||
### Parameters
|
||||
|
||||
@@ -4,6 +4,54 @@
|
||||
|
||||
Requires libvips v8.8.1.
|
||||
|
||||
#### v0.23.3 - 17<sup>th</sup> November 2019
|
||||
|
||||
* Ensure `trim` operation supports images contained in the alpha channel.
|
||||
[#1597](https://github.com/lovell/sharp/issues/1597)
|
||||
|
||||
* Ensure tile `overlap` option works as expected.
|
||||
[#1921](https://github.com/lovell/sharp/pull/1921)
|
||||
[@rustyguts](https://github.com/rustyguts)
|
||||
|
||||
* Allow compilation on FreeBSD and variants (broken since v0.23.0)
|
||||
[#1952](https://github.com/lovell/sharp/pull/1952)
|
||||
[@pouya-eghbali](https://github.com/pouya-eghbali)
|
||||
|
||||
* Ensure `modulate` and other colour-based operations can co-exist.
|
||||
[#1958](https://github.com/lovell/sharp/issues/1958)
|
||||
|
||||
#### v0.23.2 - 28<sup>th</sup> October 2019
|
||||
|
||||
* Add `background` option to tile output operation.
|
||||
[#1924](https://github.com/lovell/sharp/pull/1924)
|
||||
[@neave](https://github.com/neave)
|
||||
|
||||
* Add support for Node.js 13.
|
||||
[#1932](https://github.com/lovell/sharp/pull/1932)
|
||||
[@MayhemYDG](https://github.com/MayhemYDG)
|
||||
|
||||
#### v0.23.1 - 26<sup>th</sup> September 2019
|
||||
|
||||
* Ensure `sharp.format.vips` is present and correct (filesystem only).
|
||||
[#1813](https://github.com/lovell/sharp/issues/1813)
|
||||
|
||||
* Ensure invalid `width` and `height` provided as options to `resize` throw.
|
||||
[#1817](https://github.com/lovell/sharp/issues/1817)
|
||||
|
||||
* Allow use of 'heic' and 'heif' identifiers with `toFormat`.
|
||||
[#1834](https://github.com/lovell/sharp/pull/1834)
|
||||
[@jaubourg](https://github.com/jaubourg)
|
||||
|
||||
* Add `premultiplied` option to `composite` operation.
|
||||
[#1835](https://github.com/lovell/sharp/pull/1835)
|
||||
[@Andargor](https://github.com/Andargor)
|
||||
|
||||
* Allow instance reuse with differing `toBuffer` options.
|
||||
[#1860](https://github.com/lovell/sharp/pull/1860)
|
||||
[@RaboliotTheGrey](https://github.com/RaboliotTheGrey)
|
||||
|
||||
* Ensure image is at least 3x3 pixels before attempting trim operation.
|
||||
|
||||
#### v0.23.0 - 29<sup>th</sup> July 2019
|
||||
|
||||
* Remove `overlayWith` previously deprecated in v0.22.0.
|
||||
|
||||
@@ -7,7 +7,8 @@ is to convert large images in common formats to
|
||||
smaller, web-friendly JPEG, PNG and WebP images of varying dimensions.
|
||||
|
||||
Resizing an image is typically 4x-5x faster than using the
|
||||
quickest ImageMagick and GraphicsMagick settings.
|
||||
quickest ImageMagick and GraphicsMagick settings
|
||||
due to its use of [libvips](https://github.com/libvips/libvips).
|
||||
|
||||
Colour spaces, embedded ICC profiles and alpha transparency channels are all handled correctly.
|
||||
Lanczos resampling ensures quality is not sacrificed for speed.
|
||||
@@ -16,7 +17,7 @@ As well as image resizing, operations such as
|
||||
rotation, extraction, compositing and gamma correction are available.
|
||||
|
||||
Most modern 64-bit OS X, Windows and Linux systems running
|
||||
Node versions 8, 10 and 12
|
||||
Node versions 8, 10, 12 and 13
|
||||
do not require any additional install or runtime dependencies.
|
||||
|
||||
[](https://coveralls.io/r/lovell/sharp?branch=master)
|
||||
@@ -126,6 +127,10 @@ the help and code contributions of the following people:
|
||||
* [Michael B. Klein](https://github.com/mbklein)
|
||||
* [Jakub Michálek](https://github.com/Goues)
|
||||
* [Ilya Ovdin](https://github.com/iovdin)
|
||||
* [Andargor](https://github.com/Andargor)
|
||||
* [Nicolas Stepien](https://github.com/MayhemYDG)
|
||||
* [Paul Neave](https://github.com/neave)
|
||||
* [Brendan Kennedy](https://github.com/rustyguts)
|
||||
|
||||
Thank you!
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ yarn add sharp
|
||||
### Building from source
|
||||
|
||||
Pre-compiled binaries for sharp are provided for use with
|
||||
Node versions 8, 10 and 12 on
|
||||
Node versions 8, 10, 12 and 13 on
|
||||
64-bit Windows, OS X and Linux platforms.
|
||||
|
||||
Sharp will be built from source at install time when:
|
||||
@@ -74,9 +74,8 @@ libvips is available in the
|
||||
[community repository](https://pkgs.alpinelinux.org/packages?name=vips-dev):
|
||||
|
||||
```sh
|
||||
apk add vips-dev fftw-dev build-base --update-cache \
|
||||
--repository https://alpine.global.ssl.fastly.net/alpine/edge/community/ \
|
||||
--repository https://alpine.global.ssl.fastly.net/alpine/edge/main
|
||||
apk add --upgrade --no-cache vips-dev build-base \
|
||||
--repository https://alpine.global.ssl.fastly.net/alpine/v3.10/community/
|
||||
```
|
||||
|
||||
The smaller stack size of musl libc means
|
||||
@@ -247,6 +246,9 @@ SHARP_DIST_BASE_URL="https://hostname/path/" npm install sharp
|
||||
|
||||
to use `https://hostname/path/libvips-x.y.z-platform.tar.gz`.
|
||||
|
||||
To install the prebuilt sharp binaries from a custom URL, please see
|
||||
[https://github.com/prebuild/prebuild-install#custom-binaries](https://github.com/prebuild/prebuild-install#custom-binaries)
|
||||
|
||||
### Licences
|
||||
|
||||
This module is licensed under the terms of the
|
||||
|
||||
@@ -4,16 +4,15 @@
|
||||
|
||||
* AWS EC2 eu-west-1 [c5.large](https://aws.amazon.com/ec2/instance-types/c5/) (2x Xeon Platinum 8124M CPU @ 3.00GHz)
|
||||
* Ubuntu 18.04 (hvm-ssd/ubuntu-bionic-18.04-amd64-server-20180912 ami-00035f41c82244dab)
|
||||
* Node.js v10.11.0
|
||||
* Node.js v12.10.0
|
||||
|
||||
### The contenders
|
||||
|
||||
* [jimp](https://www.npmjs.com/package/jimp) v0.5.3 - Image processing in pure JavaScript. Provides bicubic interpolation.
|
||||
* [mapnik](https://www.npmjs.org/package/mapnik) v4.0.1 - Whilst primarily a map renderer, Mapnik contains bitmap image utilities.
|
||||
* [imagemagick-native](https://www.npmjs.com/package/imagemagick-native) v1.9.3 - Wrapper around libmagick++, supports Buffers only.
|
||||
* [jimp](https://www.npmjs.com/package/jimp) v0.8.4 - Image processing in pure JavaScript. Provides bicubic interpolation.
|
||||
* [mapnik](https://www.npmjs.org/package/mapnik) v4.3.1 - Whilst primarily a map renderer, Mapnik contains bitmap image utilities.
|
||||
* [imagemagick](https://www.npmjs.com/package/imagemagick) v0.1.3 - Supports filesystem only and "*has been unmaintained for a long time*".
|
||||
* [gm](https://www.npmjs.com/package/gm) v1.23.1 - Fully featured wrapper around GraphicsMagick's `gm` command line utility.
|
||||
* sharp v0.21.0 / libvips v8.7.0 - Caching within libvips disabled to ensure a fair comparison.
|
||||
* sharp v0.23.1 / libvips v8.8.1 - Caching within libvips disabled to ensure a fair comparison.
|
||||
|
||||
### The task
|
||||
|
||||
@@ -25,14 +24,14 @@ then compress to JPEG at a "quality" setting of 80.
|
||||
|
||||
| Module | Input | Output | Ops/sec | Speed-up |
|
||||
| :----------------- | :----- | :----- | ------: | -------: |
|
||||
| jimp | buffer | buffer | 0.71 | 1.0 |
|
||||
| mapnik | buffer | buffer | 3.32 | 4.7 |
|
||||
| gm | buffer | buffer | 3.97 | 5.6 |
|
||||
| imagemagick-native | buffer | buffer | 4.06 | 5.7 |
|
||||
| imagemagick | file | file | 4.24 | 6.0 |
|
||||
| sharp | stream | stream | 25.30 | 35.6 |
|
||||
| sharp | file | file | 26.17 | 36.9 |
|
||||
| sharp | buffer | buffer | 26.45 | 37.3 |
|
||||
| jimp | buffer | buffer | 0.66 | 1.0 |
|
||||
| mapnik | buffer | buffer | 3.31 | 5.0 |
|
||||
| gm | buffer | buffer | 3.79 | 5.7 |
|
||||
| gm | file | file | 3.82 | 5.8 |
|
||||
| imagemagick | file | file | 4.17 | 6.3 |
|
||||
| sharp | stream | stream | 25.81 | 39.1 |
|
||||
| sharp | file | file | 26.76 | 40.5 |
|
||||
| sharp | buffer | buffer | 28.06 | 42.5 |
|
||||
|
||||
Greater libvips performance can be expected with caching enabled (default)
|
||||
and using 8+ core machines, especially those with larger L1/L2 CPU caches.
|
||||
|
||||
@@ -19,6 +19,9 @@ const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SH
|
||||
|
||||
const fail = function (err) {
|
||||
npmLog.error('sharp', err.message);
|
||||
if (err.code === 'EACCES') {
|
||||
npmLog.info('sharp', 'Are you trying to install as a root or sudo user? Try again with the --unsafe-perm flag');
|
||||
}
|
||||
npmLog.info('sharp', 'Attempting to build from source via node-gyp but this may fail due to the above error');
|
||||
npmLog.info('sharp', 'Please see https://sharp.pixelplumbing.com/page/install for required dependencies');
|
||||
process.exit(1);
|
||||
@@ -79,14 +82,16 @@ try {
|
||||
npmLog.info('sharp', `Downloading ${url}`);
|
||||
simpleGet({ url: url, agent: agent() }, function (err, response) {
|
||||
if (err) {
|
||||
throw err;
|
||||
fail(err);
|
||||
} else if (response.statusCode === 404) {
|
||||
fail(new Error(`Prebuilt libvips binaries are not yet available for ${platformAndArch}`));
|
||||
} else if (response.statusCode !== 200) {
|
||||
fail(new Error(`Status ${response.statusCode} ${response.statusMessage}`));
|
||||
} else {
|
||||
response
|
||||
.on('error', fail)
|
||||
.pipe(tmpFile);
|
||||
}
|
||||
if (response.statusCode !== 200) {
|
||||
throw new Error(`Status ${response.statusCode}`);
|
||||
}
|
||||
response
|
||||
.on('error', fail)
|
||||
.pipe(tmpFile);
|
||||
});
|
||||
tmpFile
|
||||
.on('error', fail)
|
||||
|
||||
@@ -20,15 +20,18 @@ function env (key) {
|
||||
|
||||
module.exports = function () {
|
||||
try {
|
||||
const proxy = url.parse(proxies.map(env).find(is.string));
|
||||
const proxy = new url.URL(proxies.map(env).find(is.string));
|
||||
const tunnel = proxy.protocol === 'https:'
|
||||
? tunnelAgent.httpsOverHttps
|
||||
: tunnelAgent.httpsOverHttp;
|
||||
const proxyAuth = proxy.username && proxy.password
|
||||
? `${proxy.username}:${proxy.password}`
|
||||
: null;
|
||||
return tunnel({
|
||||
proxy: {
|
||||
port: Number(proxy.port),
|
||||
host: proxy.hostname,
|
||||
proxyAuth: proxy.auth
|
||||
proxyAuth
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@@ -83,18 +83,22 @@ function toColorspace (colorspace) {
|
||||
* Update a colour attribute of the this.options Object.
|
||||
* @private
|
||||
* @param {String} key
|
||||
* @param {String|Object} val
|
||||
* @throws {Error} Invalid key
|
||||
* @param {String|Object} value
|
||||
* @throws {Error} Invalid value
|
||||
*/
|
||||
function _setColourOption (key, val) {
|
||||
if (is.object(val) || is.string(val)) {
|
||||
const colour = color(val);
|
||||
this.options[key] = [
|
||||
colour.red(),
|
||||
colour.green(),
|
||||
colour.blue(),
|
||||
Math.round(colour.alpha() * 255)
|
||||
];
|
||||
function _setBackgroundColourOption (key, value) {
|
||||
if (is.defined(value)) {
|
||||
if (is.object(value) || is.string(value)) {
|
||||
const colour = color(value);
|
||||
this.options[key] = [
|
||||
colour.red(),
|
||||
colour.green(),
|
||||
colour.blue(),
|
||||
Math.round(colour.alpha() * 255)
|
||||
];
|
||||
} else {
|
||||
throw is.invalidParameterError('background', 'object or string', value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +115,7 @@ module.exports = function (Sharp) {
|
||||
toColourspace,
|
||||
toColorspace,
|
||||
// Private
|
||||
_setColourOption
|
||||
_setBackgroundColourOption
|
||||
});
|
||||
// Class attributes
|
||||
Sharp.colourspace = colourspace;
|
||||
|
||||
@@ -81,6 +81,7 @@ const blend = {
|
||||
* @param {Number} [images[].top] - the pixel offset from the top edge.
|
||||
* @param {Number} [images[].left] - the pixel offset from the left edge.
|
||||
* @param {Boolean} [images[].tile=false] - set to true to repeat the overlay image across the entire image with the given `gravity`.
|
||||
* @param {Boolean} [images[].premultiplied=false] - set to true to avoid premultipling the image below. Equivalent to the `--premultiplied` vips option.
|
||||
* @param {Number} [images[].density=72] - number representing the DPI for vector overlay image.
|
||||
* @param {Object} [images[].raw] - describes overlay when using raw pixel data.
|
||||
* @param {Number} [images[].raw.width]
|
||||
@@ -105,7 +106,8 @@ function composite (images) {
|
||||
tile: false,
|
||||
left: -1,
|
||||
top: -1,
|
||||
gravity: 0
|
||||
gravity: 0,
|
||||
premultiplied: false
|
||||
};
|
||||
if (is.defined(image.blend)) {
|
||||
if (is.string(blend[image.blend])) {
|
||||
@@ -147,6 +149,14 @@ function composite (images) {
|
||||
throw is.invalidParameterError('gravity', 'valid gravity', image.gravity);
|
||||
}
|
||||
}
|
||||
if (is.defined(image.premultiplied)) {
|
||||
if (is.bool(image.premultiplied)) {
|
||||
composite.premultiplied = image.premultiplied;
|
||||
} else {
|
||||
throw is.invalidParameterError('premultiplied', 'boolean', image.premultiplied);
|
||||
}
|
||||
}
|
||||
|
||||
return composite;
|
||||
});
|
||||
return this;
|
||||
|
||||
@@ -78,7 +78,7 @@ const debuglog = util.debuglog('sharp');
|
||||
*
|
||||
* @param {(Buffer|String)} [input] - if present, can be
|
||||
* a Buffer containing JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data, or
|
||||
* a String containing the path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.
|
||||
* a String containing the filesystem path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.
|
||||
* JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
|
||||
* @param {Object} [options] - if present, is an Object with optional attributes.
|
||||
* @param {Boolean} [options.failOnError=true] - by default halt processing and raise an error when loading invalid images.
|
||||
@@ -213,6 +213,7 @@ const Sharp = function (input, options) {
|
||||
tileSize: 256,
|
||||
tileOverlap: 0,
|
||||
tileSkipBlanks: -1,
|
||||
tileBackground: [255, 255, 255, 255],
|
||||
linearA: 1,
|
||||
linearB: 0,
|
||||
// Function to notify of libvips warnings
|
||||
|
||||
@@ -65,11 +65,15 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
||||
if (is.defined(inputOptions.pages)) {
|
||||
if (is.integer(inputOptions.pages) && is.inRange(inputOptions.pages, -1, 100000)) {
|
||||
inputDescriptor.pages = inputOptions.pages;
|
||||
} else {
|
||||
throw is.invalidParameterError('pages', 'integer between -1 and 100000', inputOptions.pages);
|
||||
}
|
||||
}
|
||||
if (is.defined(inputOptions.page)) {
|
||||
if (is.integer(inputOptions.page) && is.inRange(inputOptions.page, 0, 100000)) {
|
||||
inputDescriptor.page = inputOptions.page;
|
||||
} else {
|
||||
throw is.invalidParameterError('page', 'integer between 0 and 100000', inputOptions.page);
|
||||
}
|
||||
}
|
||||
// Create new image
|
||||
|
||||
@@ -179,7 +179,7 @@ function blur (sigma) {
|
||||
function flatten (options) {
|
||||
this.options.flatten = is.bool(options) ? options : true;
|
||||
if (is.object(options)) {
|
||||
this._setColourOption('flattenBackground', options.background);
|
||||
this._setBackgroundColourOption('flattenBackground', options.background);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ const sharp = require('../build/Release/sharp.node');
|
||||
* with JPEG, PNG, WebP, TIFF, DZI, and libvips' V format supported.
|
||||
* Note that raw pixel data is only supported for buffer output.
|
||||
*
|
||||
* By default all metadata will be removed, which includes EXIF-based orientation.
|
||||
* See {@link withMetadata} for control over this.
|
||||
*
|
||||
* A `Promise` is returned when `callback` is not provided.
|
||||
*
|
||||
* @example
|
||||
@@ -57,7 +60,11 @@ function toFile (fileOut, callback) {
|
||||
/**
|
||||
* Write output to a Buffer.
|
||||
* JPEG, PNG, WebP, TIFF and RAW output are supported.
|
||||
* By default, the format will match the input image, except GIF and SVG input which become PNG output.
|
||||
*
|
||||
* If no explicit format is set, the output format will match the input image, except GIF and SVG input which become PNG output.
|
||||
*
|
||||
* By default all metadata will be removed, which includes EXIF-based orientation.
|
||||
* See {@link withMetadata} for control over this.
|
||||
*
|
||||
* `callback`, if present, gets three arguments `(err, data, info)` where:
|
||||
* - `err` is an error, if any.
|
||||
@@ -92,6 +99,8 @@ function toFile (fileOut, callback) {
|
||||
function toBuffer (options, callback) {
|
||||
if (is.object(options)) {
|
||||
this._setBooleanOption('resolveWithObject', options.resolveWithObject);
|
||||
} else if (this.options.resolveWithObject) {
|
||||
this.options.resolveWithObject = false;
|
||||
}
|
||||
return this._pipeline(is.fn(options) ? options : callback);
|
||||
}
|
||||
@@ -487,6 +496,17 @@ function raw () {
|
||||
return this._updateFormatOut('raw');
|
||||
}
|
||||
|
||||
const formats = new Map([
|
||||
['heic', 'heif'],
|
||||
['heif', 'heif'],
|
||||
['jpeg', 'jpeg'],
|
||||
['jpg', 'jpeg'],
|
||||
['png', 'png'],
|
||||
['raw', 'raw'],
|
||||
['tiff', 'tiff'],
|
||||
['webp', 'webp']
|
||||
]);
|
||||
|
||||
/**
|
||||
* Force output to a given format.
|
||||
*
|
||||
@@ -502,14 +522,11 @@ function raw () {
|
||||
* @throws {Error} unsupported format or options
|
||||
*/
|
||||
function toFormat (format, options) {
|
||||
if (is.object(format) && is.string(format.id)) {
|
||||
format = format.id;
|
||||
const actualFormat = formats.get(is.object(format) && is.string(format.id) ? format.id : format);
|
||||
if (!actualFormat) {
|
||||
throw is.invalidParameterError('format', `one of: ${[...formats.keys()].join(', ')}`, format);
|
||||
}
|
||||
if (format === 'jpg') format = 'jpeg';
|
||||
if (!is.inArray(format, ['jpeg', 'png', 'webp', 'tiff', 'raw'])) {
|
||||
throw is.invalidParameterError('format', 'one of: jpeg, png, webp, tiff, raw', format);
|
||||
}
|
||||
return this[format](options);
|
||||
return this[actualFormat](options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -534,6 +551,7 @@ function toFormat (format, options) {
|
||||
* @param {Number} [options.size=256] tile size in pixels, a value between 1 and 8192.
|
||||
* @param {Number} [options.overlap=0] tile overlap in pixels, a value between 0 and 8192.
|
||||
* @param {Number} [options.angle=0] tile angle of rotation, must be a multiple of 90.
|
||||
* @param {String|Object} [options.background={r: 255, g: 255, b: 255, alpha: 1}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to white without transparency.
|
||||
* @param {String} [options.depth] how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
|
||||
* @param {Number} [options.skipBlanks=-1] threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images
|
||||
* @param {String} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
|
||||
@@ -557,7 +575,7 @@ function tile (options) {
|
||||
if (options.overlap > this.options.tileSize) {
|
||||
throw is.invalidParameterError('overlap', `<= size (${this.options.tileSize})`, options.overlap);
|
||||
}
|
||||
this.options.tileOverlap = tile.overlap;
|
||||
this.options.tileOverlap = options.overlap;
|
||||
} else {
|
||||
throw is.invalidParameterError('overlap', 'integer between 0 and 8192', options.overlap);
|
||||
}
|
||||
@@ -586,6 +604,8 @@ function tile (options) {
|
||||
throw is.invalidParameterError('angle', 'positive/negative multiple of 90', options.angle);
|
||||
}
|
||||
}
|
||||
// Background colour
|
||||
this._setBackgroundColourOption('tileBackground', options.background);
|
||||
// Depth of tiles
|
||||
if (is.defined(options.depth)) {
|
||||
if (is.string(options.depth) && is.inArray(options.depth, ['onepixel', 'onetile', 'one'])) {
|
||||
|
||||
@@ -7,6 +7,7 @@ const env = process.env;
|
||||
module.exports = function () {
|
||||
const arch = env.npm_config_arch || process.arch;
|
||||
const platform = env.npm_config_platform || process.platform;
|
||||
/* istanbul ignore next */
|
||||
const libc = (platform === 'linux' && detectLibc.isNonGlibcLinux) ? detectLibc.family : '';
|
||||
|
||||
const platformId = [`${platform}${libc}`];
|
||||
|
||||
@@ -210,12 +210,20 @@ function resize (width, height, options) {
|
||||
}
|
||||
if (is.object(options)) {
|
||||
// Width
|
||||
if (is.integer(options.width) && options.width > 0) {
|
||||
this.options.width = options.width;
|
||||
if (is.defined(options.width)) {
|
||||
if (is.integer(options.width) && options.width > 0) {
|
||||
this.options.width = options.width;
|
||||
} else {
|
||||
throw is.invalidParameterError('width', 'positive integer', options.width);
|
||||
}
|
||||
}
|
||||
// Height
|
||||
if (is.integer(options.height) && options.height > 0) {
|
||||
this.options.height = options.height;
|
||||
if (is.defined(options.height)) {
|
||||
if (is.integer(options.height) && options.height > 0) {
|
||||
this.options.height = options.height;
|
||||
} else {
|
||||
throw is.invalidParameterError('height', 'positive integer', options.height);
|
||||
}
|
||||
}
|
||||
// Fit
|
||||
if (is.defined(options.fit)) {
|
||||
@@ -238,9 +246,7 @@ function resize (width, height, options) {
|
||||
}
|
||||
}
|
||||
// Background
|
||||
if (is.defined(options.background)) {
|
||||
this._setColourOption('resizeBackground', options.background);
|
||||
}
|
||||
this._setBackgroundColourOption('resizeBackground', options.background);
|
||||
// Kernel
|
||||
if (is.defined(options.kernel)) {
|
||||
if (is.string(kernel[options.kernel])) {
|
||||
@@ -305,7 +311,7 @@ function extend (extend) {
|
||||
this.options.extendBottom = extend.bottom;
|
||||
this.options.extendLeft = extend.left;
|
||||
this.options.extendRight = extend.right;
|
||||
this._setColourOption('extendBackground', extend.background);
|
||||
this._setBackgroundColourOption('extendBackground', extend.background);
|
||||
} else {
|
||||
throw is.invalidParameterError('extend', 'integer or object', extend);
|
||||
}
|
||||
@@ -361,7 +367,10 @@ function extract (options) {
|
||||
|
||||
/**
|
||||
* Trim "boring" pixels from all edges that contain values similar to the top-left pixel.
|
||||
* Images consisting entirely of a single colour will calculate "boring" using the alpha channel, if any.
|
||||
*
|
||||
* The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` properties.
|
||||
*
|
||||
* @param {Number} [threshold=10] the allowed difference from the top-left pixel, a number greater than zero.
|
||||
* @returns {Sharp}
|
||||
* @throws {Error} Invalid parameters
|
||||
|
||||
47
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "sharp",
|
||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
|
||||
"version": "0.23.0",
|
||||
"version": "0.23.3",
|
||||
"author": "Lovell Fuller <npm@lovell.info>",
|
||||
"homepage": "https://github.com/lovell/sharp",
|
||||
"contributors": [
|
||||
@@ -61,12 +61,15 @@
|
||||
"Keith Belovay <keith@picthrive.com>",
|
||||
"Michael B. Klein <mbklein@gmail.com>",
|
||||
"Jordan Prudhomme <jordan@raboland.fr>",
|
||||
"Ilya Ovdin <iovdin@gmail.com>"
|
||||
"Ilya Ovdin <iovdin@gmail.com>",
|
||||
"Andargor <andargor@yahoo.com>",
|
||||
"Paul Neave <paul.neave@gmail.com>",
|
||||
"Brendan Kennedy <brenwken@gmail.com>"
|
||||
],
|
||||
"scripts": {
|
||||
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)",
|
||||
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
||||
"test": "semistandard && cc && npm run test-unit && npm run test-licensing && prebuild-ci",
|
||||
"test": "semistandard && cpplint && npm run test-unit && npm run test-licensing && prebuild-ci",
|
||||
"test-unit": "nyc --reporter=lcov --branches=99 mocha --slow=5000 --timeout=60000 ./test/unit/*.js",
|
||||
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
||||
"test-coverage": "./test/coverage/report.sh",
|
||||
@@ -74,6 +77,14 @@
|
||||
"docs": "for m in constructor input resize composite operation colour channel output utility; do documentation build --shallow --format=md --markdown-toc=false lib/$m.js >docs/api-$m.md; done"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"binding.gyp",
|
||||
"docs/**",
|
||||
"!docs/css/**",
|
||||
"install/**",
|
||||
"lib/**",
|
||||
"src/**"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/lovell/sharp"
|
||||
@@ -99,27 +110,27 @@
|
||||
"detect-libc": "^1.0.3",
|
||||
"nan": "^2.14.0",
|
||||
"npmlog": "^4.1.2",
|
||||
"prebuild-install": "^5.3.0",
|
||||
"prebuild-install": "^5.3.3",
|
||||
"semver": "^6.3.0",
|
||||
"simple-get": "^3.0.3",
|
||||
"tar": "^4.4.10",
|
||||
"simple-get": "^3.1.0",
|
||||
"tar": "^5.0.5",
|
||||
"tunnel-agent": "^0.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"async": "^3.1.0",
|
||||
"cc": "^1.0.2",
|
||||
"cc": "^2.0.1",
|
||||
"decompress-zip": "^0.3.2",
|
||||
"documentation": "^12.0.3",
|
||||
"exif-reader": "^1.0.2",
|
||||
"documentation": "^12.1.4",
|
||||
"exif-reader": "^1.0.3",
|
||||
"icc": "^1.0.0",
|
||||
"license-checker": "^25.0.1",
|
||||
"mocha": "^6.2.0",
|
||||
"mock-fs": "^4.10.1",
|
||||
"mocha": "^6.2.2",
|
||||
"mock-fs": "^4.10.3",
|
||||
"nyc": "^14.1.1",
|
||||
"prebuild": "^9.0.1",
|
||||
"prebuild": "^9.1.1",
|
||||
"prebuild-ci": "^3.1.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"semistandard": "^13.0.1"
|
||||
"rimraf": "^3.0.0",
|
||||
"semistandard": "^14.2.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"config": {
|
||||
@@ -128,6 +139,9 @@
|
||||
"engines": {
|
||||
"node": ">=8.5.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
},
|
||||
"semistandard": {
|
||||
"env": [
|
||||
"mocha"
|
||||
@@ -136,10 +150,7 @@
|
||||
"cc": {
|
||||
"linelength": "120",
|
||||
"filter": [
|
||||
"build/c++11",
|
||||
"build/include",
|
||||
"runtime/indentation_namespace",
|
||||
"runtime/references"
|
||||
"build/include"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <mutex> // NOLINT(build/c++11)
|
||||
|
||||
#include <node.h>
|
||||
#include <node_buffer.h>
|
||||
@@ -147,7 +147,7 @@ namespace sharp {
|
||||
case ImageType::OPENSLIDE: id = "openslide"; break;
|
||||
case ImageType::PPM: id = "ppm"; break;
|
||||
case ImageType::FITS: id = "fits"; break;
|
||||
case ImageType::VIPS: id = "v"; break;
|
||||
case ImageType::VIPS: id = "vips"; break;
|
||||
case ImageType::RAW: id = "raw"; break;
|
||||
case ImageType::UNKNOWN: id = "unknown"; break;
|
||||
case ImageType::MISSING: id = "missing"; break;
|
||||
|
||||
@@ -43,7 +43,7 @@ using vips::VImage;
|
||||
|
||||
namespace sharp {
|
||||
|
||||
struct InputDescriptor {
|
||||
struct InputDescriptor { // NOLINT(runtime/indentation_namespace)
|
||||
std::string name;
|
||||
std::string file;
|
||||
char *buffer;
|
||||
@@ -92,7 +92,7 @@ namespace sharp {
|
||||
|
||||
// Create an InputDescriptor instance from a v8::Object describing an input image
|
||||
InputDescriptor* CreateInputDescriptor(
|
||||
v8::Local<v8::Object> input, std::vector<v8::Local<v8::Object>> &buffersToPersist);
|
||||
v8::Local<v8::Object> input, std::vector<v8::Local<v8::Object>> &buffersToPersist); // NOLINT(runtime/references)
|
||||
|
||||
enum class ImageType {
|
||||
JPEG,
|
||||
|
||||
@@ -191,12 +191,20 @@ namespace sharp {
|
||||
VImage alpha = image[image.bands() - 1];
|
||||
return RemoveAlpha(image)
|
||||
.colourspace(VIPS_INTERPRETATION_LCH)
|
||||
.linear({brightness, saturation, 1}, {0, 0, static_cast<double>(hue)})
|
||||
.linear(
|
||||
{ brightness, saturation, 1},
|
||||
{ 0.0, 0.0, static_cast<double>(hue) }
|
||||
)
|
||||
.colourspace(VIPS_INTERPRETATION_sRGB)
|
||||
.bandjoin(alpha);
|
||||
} else {
|
||||
return image
|
||||
.colourspace(VIPS_INTERPRETATION_LCH)
|
||||
.linear({brightness, saturation, 1}, {0, 0, static_cast<double>(hue)});
|
||||
.linear(
|
||||
{ brightness, saturation, 1 },
|
||||
{ 0.0, 0.0, static_cast<double>(hue) }
|
||||
)
|
||||
.colourspace(VIPS_INTERPRETATION_sRGB);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,17 +258,30 @@ namespace sharp {
|
||||
Trim an image
|
||||
*/
|
||||
VImage Trim(VImage image, double const threshold) {
|
||||
if (image.width() < 3 && image.height() < 3) {
|
||||
throw VError("Image to trim must be at least 3x3 pixels");
|
||||
}
|
||||
// Top-left pixel provides the background colour
|
||||
VImage background = image.extract_area(0, 0, 1, 1);
|
||||
if (HasAlpha(background)) {
|
||||
background = background.flatten();
|
||||
}
|
||||
int top, width, height;
|
||||
int const left = image.find_trim(&top, &width, &height, VImage::option()
|
||||
int left, top, width, height;
|
||||
left = image.find_trim(&top, &width, &height, VImage::option()
|
||||
->set("background", background(0, 0))
|
||||
->set("threshold", threshold));
|
||||
if (width == 0 || height == 0) {
|
||||
throw VError("Unexpected error while trimming. Try to lower the tolerance");
|
||||
if (HasAlpha(image)) {
|
||||
// Search alpha channel
|
||||
VImage alpha = image[image.bands() - 1];
|
||||
VImage backgroundAlpha = alpha.extract_area(0, 0, 1, 1);
|
||||
left = alpha.find_trim(&top, &width, &height, VImage::option()
|
||||
->set("background", backgroundAlpha(0, 0))
|
||||
->set("threshold", threshold));
|
||||
}
|
||||
if (width == 0 || height == 0) {
|
||||
throw VError("Unexpected error while trimming. Try to lower the tolerance");
|
||||
}
|
||||
}
|
||||
return image.extract_area(left, top, width, height);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
#elif defined(__APPLE__)
|
||||
#define STAT64_STRUCT stat
|
||||
#define STAT64_FUNCTION stat
|
||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||
#define STAT64_STRUCT stat
|
||||
#define STAT64_FUNCTION stat
|
||||
#else
|
||||
#define STAT64_STRUCT stat64
|
||||
#define STAT64_FUNCTION stat64
|
||||
@@ -591,7 +594,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
||||
if (!HasAlpha(compositeImage)) {
|
||||
compositeImage = sharp::EnsureAlpha(compositeImage);
|
||||
}
|
||||
compositeImage = compositeImage.premultiply();
|
||||
if (!composite->premultiplied) compositeImage = compositeImage.premultiply();
|
||||
// Calculate position
|
||||
int left;
|
||||
int top;
|
||||
@@ -959,6 +962,11 @@ class PipelineWorker : public Nan::AsyncWorker {
|
||||
};
|
||||
suffix = AssembleSuffixString(extname, options);
|
||||
}
|
||||
|
||||
// Remove alpha channel from tile background if image does not contain an alpha channel
|
||||
if (!HasAlpha(image)) {
|
||||
baton->tileBackground.pop_back();
|
||||
}
|
||||
// Write DZ to file
|
||||
vips::VOption *options = VImage::option()
|
||||
->set("strip", !baton->withMetadata)
|
||||
@@ -968,6 +976,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
||||
->set("layout", baton->tileLayout)
|
||||
->set("suffix", const_cast<char*>(suffix.data()))
|
||||
->set("angle", CalculateAngleRotation(baton->tileAngle))
|
||||
->set("background", baton->tileBackground)
|
||||
->set("skip_blanks", baton->tileSkipBlanks);
|
||||
|
||||
// libvips chooses a default depth based on layout. Instead of replicating that logic here by
|
||||
@@ -1230,6 +1239,7 @@ NAN_METHOD(pipeline) {
|
||||
composite->left = AttrTo<int32_t>(compositeObject, "left");
|
||||
composite->top = AttrTo<int32_t>(compositeObject, "top");
|
||||
composite->tile = AttrTo<bool>(compositeObject, "tile");
|
||||
composite->premultiplied = AttrTo<bool>(compositeObject, "premultiplied");
|
||||
baton->composite.push_back(composite);
|
||||
}
|
||||
// Resize options
|
||||
@@ -1373,6 +1383,7 @@ NAN_METHOD(pipeline) {
|
||||
baton->tileOverlap = AttrTo<uint32_t>(options, "tileOverlap");
|
||||
std::string tileContainer = AttrAsStr(options, "tileContainer");
|
||||
baton->tileAngle = AttrTo<int32_t>(options, "tileAngle");
|
||||
baton->tileBackground = AttrAsRgba(options, "tileBackground");
|
||||
baton->tileSkipBlanks = AttrTo<int32_t>(options, "tileSkipBlanks");
|
||||
if (tileContainer == "zip") {
|
||||
baton->tileContainer = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
|
||||
|
||||
@@ -41,6 +41,7 @@ struct Composite {
|
||||
int left;
|
||||
int top;
|
||||
bool tile;
|
||||
bool premultiplied;
|
||||
|
||||
Composite():
|
||||
input(nullptr),
|
||||
@@ -48,7 +49,8 @@ struct Composite {
|
||||
gravity(0),
|
||||
left(-1),
|
||||
top(-1),
|
||||
tile(false) {}
|
||||
tile(false),
|
||||
premultiplied(false) {}
|
||||
};
|
||||
|
||||
struct PipelineBaton {
|
||||
@@ -173,6 +175,7 @@ struct PipelineBaton {
|
||||
VipsForeignDzLayout tileLayout;
|
||||
std::string tileFormat;
|
||||
int tileAngle;
|
||||
std::vector<double> tileBackground;
|
||||
int tileSkipBlanks;
|
||||
VipsForeignDzDepth tileDepth;
|
||||
std::unique_ptr<double[]> recombMatrix;
|
||||
@@ -278,6 +281,7 @@ struct PipelineBaton {
|
||||
tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
|
||||
tileLayout(VIPS_FOREIGN_DZ_LAYOUT_DZ),
|
||||
tileAngle(0),
|
||||
tileBackground{ 255.0, 255.0, 255.0, 255.0 },
|
||||
tileSkipBlanks(-1),
|
||||
tileDepth(VIPS_FOREIGN_DZ_DEPTH_LAST) {}
|
||||
};
|
||||
|
||||
@@ -150,8 +150,9 @@ NAN_METHOD(format) {
|
||||
|
||||
// Which load/save operations are available for each compressed format?
|
||||
Local<Object> format = New<Object>();
|
||||
for (std::string f : {
|
||||
"jpeg", "png", "webp", "tiff", "magick", "openslide", "dz", "ppm", "fits", "gif", "svg", "heif", "pdf", "v"
|
||||
for (std::string const f : {
|
||||
"jpeg", "png", "webp", "tiff", "magick", "openslide", "dz",
|
||||
"ppm", "fits", "gif", "svg", "heif", "pdf", "vips"
|
||||
}) {
|
||||
// Input
|
||||
Local<Boolean> hasInputFile =
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
"benchmark": "^2.1.4",
|
||||
"gm": "^1.23.1",
|
||||
"imagemagick": "^0.1.3",
|
||||
"imagemagick-native": "^1.9.3",
|
||||
"jimp": "^0.6.4",
|
||||
"mapnik": "^4.2.1",
|
||||
"semver": "^6.1.2"
|
||||
"jimp": "^0.8.4",
|
||||
"mapnik": "^4.3.1",
|
||||
"semver": "^6.3.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
|
||||
@@ -12,12 +12,6 @@ const gm = require('gm');
|
||||
const imagemagick = require('imagemagick');
|
||||
const mapnik = require('mapnik');
|
||||
const jimp = require('jimp');
|
||||
let imagemagickNative;
|
||||
try {
|
||||
imagemagickNative = require('imagemagick-native');
|
||||
} catch (err) {
|
||||
console.log('Excluding imagemagick-native');
|
||||
}
|
||||
|
||||
const fixtures = require('../fixtures');
|
||||
|
||||
@@ -28,7 +22,7 @@ const height = 588;
|
||||
sharp.cache(false);
|
||||
|
||||
async.series({
|
||||
'jpeg': function (callback) {
|
||||
jpeg: function (callback) {
|
||||
const inputJpgBuffer = fs.readFileSync(fixtures.inputJpg);
|
||||
const jpegSuite = new Benchmark.Suite('jpeg');
|
||||
// jimp
|
||||
@@ -126,29 +120,6 @@ async.series({
|
||||
});
|
||||
}
|
||||
});
|
||||
// imagemagick-native
|
||||
if (typeof imagemagickNative !== 'undefined') {
|
||||
jpegSuite.add('imagemagick-native-buffer-buffer', {
|
||||
defer: true,
|
||||
fn: function (deferred) {
|
||||
imagemagickNative.convert({
|
||||
srcData: inputJpgBuffer,
|
||||
quality: 80,
|
||||
width: width,
|
||||
height: height,
|
||||
format: 'JPEG',
|
||||
filter: 'Lanczos'
|
||||
}, function (err, buffer) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
assert.notStrictEqual(null, buffer);
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// gm
|
||||
jpegSuite.add('gm-buffer-file', {
|
||||
defer: true,
|
||||
@@ -289,6 +260,9 @@ async.series({
|
||||
.then(function (buffer) {
|
||||
assert.notStrictEqual(null, buffer);
|
||||
deferred.resolve();
|
||||
})
|
||||
.catch(function (err) {
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
}).on('cycle', function (event) {
|
||||
@@ -698,22 +672,6 @@ async.series({
|
||||
});
|
||||
}
|
||||
});
|
||||
// imagemagick-native
|
||||
if (typeof imagemagickNative !== 'undefined') {
|
||||
pngSuite.add('imagemagick-native-buffer-buffer', {
|
||||
defer: true,
|
||||
fn: function (deferred) {
|
||||
imagemagickNative.convert({
|
||||
srcData: inputPngBuffer,
|
||||
width: width,
|
||||
height: height,
|
||||
format: 'PNG',
|
||||
filter: 'Lanczos'
|
||||
});
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
// gm
|
||||
pngSuite.add('gm-file-file', {
|
||||
defer: true,
|
||||
|
||||
BIN
test/fixtures/expected/expected.absent.composite.premultiplied.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
test/fixtures/expected/expected.false.composite.premultiplied.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
test/fixtures/expected/expected.true.composite.premultiplied.png
vendored
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
test/fixtures/expected/flatten-rgb16-orange.jpg
vendored
|
Before Width: | Height: | Size: 839 B After Width: | Height: | Size: 824 B |
BIN
test/fixtures/expected/modulate-linear.jpg
vendored
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
test/fixtures/image-in-alpha.png
vendored
Normal file
|
After Width: | Height: | Size: 70 KiB |
2
test/fixtures/index.js
vendored
@@ -13,6 +13,7 @@ const getPath = function (filename) {
|
||||
// Based on the dHash gradient method - see http://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html
|
||||
const fingerprint = function (image, callback) {
|
||||
sharp(image)
|
||||
.flatten('gray')
|
||||
.greyscale()
|
||||
.normalise()
|
||||
.resize(9, 8, { fit: sharp.fit.fill })
|
||||
@@ -87,6 +88,7 @@ module.exports = {
|
||||
inputPngTruncated: getPath('truncated.png'), // gm convert 2569067123_aca715a2ee_o.jpg -resize 320x240 saw.png ; head -c 10000 saw.png > truncated.png
|
||||
inputPngEmbed: getPath('embedgravitybird.png'), // Released to sharp under a CC BY 4.0
|
||||
inputPngRGBWithAlpha: getPath('2569067123_aca715a2ee_o.png'), // http://www.flickr.com/photos/grizdave/2569067123/ (same as inputJpg)
|
||||
inputPngImageInAlpha: getPath('image-in-alpha.png'), // https://github.com/lovell/sharp/issues/1597
|
||||
|
||||
inputWebP: getPath('4.webp'), // http://www.gstatic.com/webp/gallery/4.webp
|
||||
inputWebPWithTransparency: getPath('5_webp_a.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp
|
||||
|
||||
BIN
test/fixtures/input.above.composite.premultiplied.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
test/fixtures/input.below.composite.premultiplied.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
@@ -54,7 +54,7 @@ describe('Alpha transparency', function () {
|
||||
assert.strictEqual(true, info.size > 0);
|
||||
assert.strictEqual(32, info.width);
|
||||
assert.strictEqual(32, info.height);
|
||||
fixtures.assertMaxColourDistance(output, fixtures.expected('flatten-rgb16-orange.jpg'), 25);
|
||||
fixtures.assertMaxColourDistance(output, fixtures.expected('flatten-rgb16-orange.jpg'), 10);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -81,6 +81,18 @@ describe('Alpha transparency', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Flatten with options but without colour does not throw', () => {
|
||||
assert.doesNotThrow(() => {
|
||||
sharp().flatten({});
|
||||
});
|
||||
});
|
||||
|
||||
it('Flatten to invalid colour throws', () => {
|
||||
assert.throws(() => {
|
||||
sharp().flatten({ background: 1 });
|
||||
});
|
||||
});
|
||||
|
||||
it('Enlargement with non-nearest neighbor interpolation shouldn’t cause dark edges', function () {
|
||||
const base = 'alpha-premultiply-enlargement-2048x1536-paper.png';
|
||||
const actual = fixtures.path('output.' + base);
|
||||
|
||||
@@ -62,6 +62,65 @@ describe('composite', () => {
|
||||
})
|
||||
));
|
||||
|
||||
it('premultiplied true', () => {
|
||||
const filename = 'composite.premultiplied.png';
|
||||
const below = fixtures.path(`input.below.${filename}`);
|
||||
const above = fixtures.path(`input.above.${filename}`);
|
||||
const actual = fixtures.path(`output.true.${filename}`);
|
||||
const expected = fixtures.expected(`expected.true.${filename}`);
|
||||
return sharp(below)
|
||||
.composite([{
|
||||
input: above,
|
||||
blend: 'color-burn',
|
||||
top: 0,
|
||||
left: 0,
|
||||
premultiplied: true
|
||||
}])
|
||||
.toFile(actual)
|
||||
.then(() => {
|
||||
fixtures.assertMaxColourDistance(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('premultiplied false', () => {
|
||||
const filename = 'composite.premultiplied.png';
|
||||
const below = fixtures.path(`input.below.${filename}`);
|
||||
const above = fixtures.path(`input.above.${filename}`);
|
||||
const actual = fixtures.path(`output.false.${filename}`);
|
||||
const expected = fixtures.expected(`expected.false.${filename}`);
|
||||
return sharp(below)
|
||||
.composite([{
|
||||
input: above,
|
||||
blend: 'color-burn',
|
||||
top: 0,
|
||||
left: 0,
|
||||
premultiplied: false
|
||||
}])
|
||||
.toFile(actual)
|
||||
.then(() => {
|
||||
fixtures.assertMaxColourDistance(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('premultiplied absent', () => {
|
||||
const filename = 'composite.premultiplied.png';
|
||||
const below = fixtures.path(`input.below.${filename}`);
|
||||
const above = fixtures.path(`input.above.${filename}`);
|
||||
const actual = fixtures.path(`output.absent.${filename}`);
|
||||
const expected = fixtures.expected(`expected.absent.${filename}`);
|
||||
return sharp(below)
|
||||
.composite([{
|
||||
input: above,
|
||||
blend: 'color-burn',
|
||||
top: 0,
|
||||
left: 0
|
||||
}])
|
||||
.toFile(actual)
|
||||
.then(() => {
|
||||
fixtures.assertMaxColourDistance(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('multiple', () => {
|
||||
const filename = 'composite-multiple.png';
|
||||
const actual = fixtures.path(`output.${filename}`);
|
||||
@@ -265,6 +324,12 @@ describe('composite', () => {
|
||||
}, /Expected boolean for tile but received invalid of type string/);
|
||||
});
|
||||
|
||||
it('invalid premultiplied', () => {
|
||||
assert.throws(() => {
|
||||
sharp().composite([{ input: 'test', premultiplied: 'invalid' }]);
|
||||
}, /Expected boolean for premultiplied but received invalid of type string/);
|
||||
});
|
||||
|
||||
it('invalid left', () => {
|
||||
assert.throws(() => {
|
||||
sharp().composite([{ input: 'test', left: 0.5 }]);
|
||||
|
||||
@@ -648,6 +648,16 @@ describe('Input/output', function () {
|
||||
it('Ignore unknown attribute', function () {
|
||||
sharp(null, { unknown: true });
|
||||
});
|
||||
it('Invalid page property throws', function () {
|
||||
assert.throws(function () {
|
||||
sharp(null, { page: -1 });
|
||||
}, /Expected integer between 0 and 100000 for page but received -1 of type number/);
|
||||
});
|
||||
it('Invalid pages property throws', function () {
|
||||
assert.throws(function () {
|
||||
sharp(null, { pages: '1' });
|
||||
}, /Expected integer between -1 and 100000 for pages but received 1 of type string/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('create new image', function () {
|
||||
|
||||
@@ -259,4 +259,35 @@ describe('JPEG', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Specifying quantization table provides different JPEG', function (done) {
|
||||
// First generate with default quantization table
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.jpeg({ optimiseCoding: false })
|
||||
.toBuffer(function (err, withDefaultQuantizationTable, withInfo) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, withDefaultQuantizationTable.length > 0);
|
||||
assert.strictEqual(withDefaultQuantizationTable.length, withInfo.size);
|
||||
assert.strictEqual('jpeg', withInfo.format);
|
||||
assert.strictEqual(320, withInfo.width);
|
||||
assert.strictEqual(240, withInfo.height);
|
||||
// Then generate with different quantization table
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.jpeg({ optimiseCoding: false, quantizationTable: 3 })
|
||||
.toBuffer(function (err, withQuantTable3, withoutInfo) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, withQuantTable3.length > 0);
|
||||
assert.strictEqual(withQuantTable3.length, withoutInfo.size);
|
||||
assert.strictEqual('jpeg', withoutInfo.format);
|
||||
assert.strictEqual(320, withoutInfo.width);
|
||||
assert.strictEqual(240, withoutInfo.height);
|
||||
|
||||
// Verify image is same (as mozjpeg may not be present) size or less
|
||||
assert.strictEqual(true, withQuantTable3.length <= withDefaultQuantizationTable.length);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,7 +73,7 @@ describe('Linear adjustment', function () {
|
||||
|
||||
assert.throws(function () {
|
||||
sharp(fixtures.inputPngOverlayLayer1)
|
||||
.linear(undefined, { 'bar': 'baz' });
|
||||
.linear(undefined, { bar: 'baz' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -232,6 +232,26 @@ describe('Image metadata', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('vips', () =>
|
||||
sharp(fixtures.inputV)
|
||||
.metadata()
|
||||
.then(metadata => {
|
||||
assert.strictEqual('vips', metadata.format);
|
||||
assert.strictEqual('undefined', typeof metadata.size);
|
||||
assert.strictEqual(70, metadata.width);
|
||||
assert.strictEqual(60, metadata.height);
|
||||
assert.strictEqual(3, metadata.channels);
|
||||
assert.strictEqual('uchar', metadata.depth);
|
||||
assert.strictEqual(72, metadata.density);
|
||||
assert.strictEqual('undefined', typeof metadata.chromaSubsampling);
|
||||
assert.strictEqual(false, metadata.isProgressive);
|
||||
assert.strictEqual(false, metadata.hasProfile);
|
||||
assert.strictEqual(false, metadata.hasAlpha);
|
||||
assert.strictEqual('undefined', typeof metadata.orientation);
|
||||
assert.strictEqual('undefined', typeof metadata.exif);
|
||||
assert.strictEqual('undefined', typeof metadata.icc);
|
||||
})
|
||||
);
|
||||
|
||||
it('File in, Promise out', function (done) {
|
||||
sharp(fixtures.inputJpg).metadata().then(function (metadata) {
|
||||
@@ -287,6 +307,20 @@ describe('Image metadata', function () {
|
||||
readable.pipe(pipeline);
|
||||
});
|
||||
|
||||
it('Stream in, rejected Promise out', () => {
|
||||
const pipeline = sharp();
|
||||
fs
|
||||
.createReadStream(__filename)
|
||||
.pipe(pipeline);
|
||||
|
||||
return pipeline
|
||||
.metadata()
|
||||
.then(
|
||||
() => Promise.reject(new Error('Expected metadata to reject')),
|
||||
err => assert.strictEqual(err.message, 'Input buffer contains unsupported image format')
|
||||
);
|
||||
});
|
||||
|
||||
it('Stream', function (done) {
|
||||
const readable = fs.createReadStream(fixtures.inputJpg);
|
||||
const pipeline = sharp().metadata(function (err, metadata) {
|
||||
@@ -370,6 +404,34 @@ describe('Image metadata', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Include metadata in output, enabled via empty object', () =>
|
||||
sharp(fixtures.inputJpgWithExif)
|
||||
.withMetadata({})
|
||||
.toBuffer()
|
||||
.then((buffer) => sharp(buffer)
|
||||
.metadata()
|
||||
.then(metadata => {
|
||||
assert.strictEqual(true, metadata.hasProfile);
|
||||
assert.strictEqual(8, metadata.orientation);
|
||||
assert.strictEqual('object', typeof metadata.exif);
|
||||
assert.strictEqual(true, metadata.exif instanceof Buffer);
|
||||
// EXIF
|
||||
const exif = exifReader(metadata.exif);
|
||||
assert.strictEqual('object', typeof exif);
|
||||
assert.strictEqual('object', typeof exif.image);
|
||||
assert.strictEqual('number', typeof exif.image.XResolution);
|
||||
// ICC
|
||||
assert.strictEqual('object', typeof metadata.icc);
|
||||
assert.strictEqual(true, metadata.icc instanceof Buffer);
|
||||
const profile = icc.parse(metadata.icc);
|
||||
assert.strictEqual('object', typeof profile);
|
||||
assert.strictEqual('RGB', profile.colorSpace);
|
||||
assert.strictEqual('Perceptual', profile.intent);
|
||||
assert.strictEqual('Monitor', profile.deviceClass);
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
it('Remove EXIF metadata after a resize', function (done) {
|
||||
sharp(fixtures.inputJpgWithExif)
|
||||
.resize(320, 240)
|
||||
|
||||
@@ -122,4 +122,21 @@ describe('Modulate', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to use linear and modulate together', function () {
|
||||
const base = 'modulate-linear.jpg';
|
||||
const actual = fixtures.path('output.' + base);
|
||||
const expected = fixtures.expected(base);
|
||||
|
||||
const contrast = 1.5;
|
||||
const brightness = 0.5;
|
||||
|
||||
return sharp(fixtures.testPattern)
|
||||
.linear(contrast, -(128 * contrast) + 128)
|
||||
.modulate({ brightness })
|
||||
.toFile(actual)
|
||||
.then(function () {
|
||||
fixtures.assertMaxColourDistance(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,7 +53,8 @@ describe('Raw pixel data', function () {
|
||||
width: info.width,
|
||||
height: info.height,
|
||||
channels: info.channels
|
||||
} })
|
||||
}
|
||||
})
|
||||
.jpeg()
|
||||
.toBuffer(function (err, data, info) {
|
||||
if (err) throw err;
|
||||
@@ -81,7 +82,8 @@ describe('Raw pixel data', function () {
|
||||
width: info.width,
|
||||
height: info.height,
|
||||
channels: info.channels
|
||||
} })
|
||||
}
|
||||
})
|
||||
.png()
|
||||
.toBuffer(function (err, data, info) {
|
||||
if (err) throw err;
|
||||
|
||||
@@ -87,6 +87,18 @@ describe('Resize dimensions', function () {
|
||||
}, /Expected positive integer for height but received 1.5 of type number/);
|
||||
});
|
||||
|
||||
it('Invalid width - via options', () => {
|
||||
assert.throws(() => {
|
||||
sharp().resize({ width: 1.5, height: 240 });
|
||||
}, /Expected positive integer for width but received 1.5 of type number/);
|
||||
});
|
||||
|
||||
it('Invalid height - via options', () => {
|
||||
assert.throws(() => {
|
||||
sharp().resize({ width: 320, height: 1.5 });
|
||||
}, /Expected positive integer for height but received 1.5 of type number/);
|
||||
});
|
||||
|
||||
it('Invalid width - too large', function (done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(0x4000, 1)
|
||||
|
||||
@@ -27,52 +27,52 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.319914765248541));
|
||||
|
||||
// red channel
|
||||
assert.strictEqual(0, stats.channels[0]['min']);
|
||||
assert.strictEqual(255, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 615101275));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 83061892917));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 101.44954540768993));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 58.373870588815414));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[0].min);
|
||||
assert.strictEqual(255, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 615101275));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 83061892917));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 101.44954540768993));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 58.373870588815414));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 2725));
|
||||
|
||||
// green channel
|
||||
assert.strictEqual(0, stats.channels[1]['min']);
|
||||
assert.strictEqual(255, stats.channels[1]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['sum'], 462824115));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['squaresSum'], 47083677255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['mean'], 76.33425255128337));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['stdev'], 44.03023262954866));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[1].min);
|
||||
assert.strictEqual(255, stats.channels[1].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].sum, 462824115));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].squaresSum, 47083677255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].mean, 76.33425255128337));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].stdev, 44.03023262954866));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxY, 0, 2725));
|
||||
|
||||
// blue channel
|
||||
assert.strictEqual(0, stats.channels[2]['min']);
|
||||
assert.strictEqual(255, stats.channels[2]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['sum'], 372986756));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['squaresSum'], 32151543524));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['mean'], 61.51724663436759));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['stdev'], 38.96702865090125));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[2].min);
|
||||
assert.strictEqual(255, stats.channels[2].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].sum, 372986756));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].squaresSum, 32151543524));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].mean, 61.51724663436759));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].stdev, 38.96702865090125));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxY, 0, 2725));
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -86,20 +86,20 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 0.3409031108021736));
|
||||
|
||||
// red channel
|
||||
assert.strictEqual(0, stats.channels[0]['min']);
|
||||
assert.strictEqual(255, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 1391368230));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 354798898650));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 238.8259925648822));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 62.15121915523771));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2809));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 2074));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2809));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 2074));
|
||||
assert.strictEqual(0, stats.channels[0].min);
|
||||
assert.strictEqual(255, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 1391368230));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 354798898650));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 238.8259925648822));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 62.15121915523771));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2809));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 2074));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2809));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 2074));
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -112,68 +112,68 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 0.06778064835816622));
|
||||
|
||||
// red channel
|
||||
assert.strictEqual(0, stats.channels[0]['min']);
|
||||
assert.strictEqual(255, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 795678795));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 202898092725));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 252.9394769668579));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 22.829537532816));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 1536));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 1536));
|
||||
assert.strictEqual(0, stats.channels[0].min);
|
||||
assert.strictEqual(255, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 795678795));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 202898092725));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 252.9394769668579));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 22.829537532816));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 1536));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 1536));
|
||||
|
||||
// green channel
|
||||
assert.strictEqual(0, stats.channels[1]['min']);
|
||||
assert.strictEqual(255, stats.channels[1]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['sum'], 795678795));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['squaresSum'], 202898092725));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['mean'], 252.9394769668579));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['stdev'], 22.829537532816));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minX'], 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minY'], 0, 1536));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxX'], 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxY'], 0, 1536));
|
||||
assert.strictEqual(0, stats.channels[1].min);
|
||||
assert.strictEqual(255, stats.channels[1].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].sum, 795678795));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].squaresSum, 202898092725));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].mean, 252.9394769668579));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].stdev, 22.829537532816));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minX, 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minY, 0, 1536));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxX, 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxY, 0, 1536));
|
||||
|
||||
// blue channel
|
||||
assert.strictEqual(0, stats.channels[2]['min']);
|
||||
assert.strictEqual(255, stats.channels[2]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['sum'], 795678795));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['squaresSum'], 202898092725));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['mean'], 252.9394769668579));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['stdev'], 22.829537532816));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minX'], 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minY'], 0, 1536));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxX'], 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxY'], 0, 1536));
|
||||
assert.strictEqual(0, stats.channels[2].min);
|
||||
assert.strictEqual(255, stats.channels[2].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].sum, 795678795));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].squaresSum, 202898092725));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].mean, 252.9394769668579));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].stdev, 22.829537532816));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minX, 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minY, 0, 1536));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxX, 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxY, 0, 1536));
|
||||
|
||||
// alpha channel
|
||||
assert.strictEqual(0, stats.channels[3]['min']);
|
||||
assert.strictEqual(255, stats.channels[3]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3]['sum'], 5549142));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3]['squaresSum'], 1333571132));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3]['mean'], 1.7640247344970703));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3]['stdev'], 20.51387814157297));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3]['minX'], 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3]['minY'], 0, 1536));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3]['maxX'], 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3]['maxY'], 0, 1536));
|
||||
assert.strictEqual(0, stats.channels[3].min);
|
||||
assert.strictEqual(255, stats.channels[3].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3].sum, 5549142));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3].squaresSum, 1333571132));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3].mean, 1.7640247344970703));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3].stdev, 20.51387814157297));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3].minX, 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3].minY, 0, 1536));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3].maxX, 0, 2048));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3].maxY, 0, 1536));
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -187,20 +187,20 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 0));
|
||||
|
||||
// alpha channel
|
||||
assert.strictEqual(0, stats.channels[3]['min']);
|
||||
assert.strictEqual(0, stats.channels[3]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3]['sum'], 0));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3]['squaresSum'], 0));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3]['mean'], 0));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3]['stdev'], 0));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3]['minX'], 0, 300));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3]['minY'], 0, 300));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3]['maxX'], 0, 300));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3]['maxY'], 0, 300));
|
||||
assert.strictEqual(0, stats.channels[3].min);
|
||||
assert.strictEqual(0, stats.channels[3].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3].sum, 0));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3].squaresSum, 0));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3].mean, 0));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[3].stdev, 0));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3].minX, 0, 300));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3].minY, 0, 300));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3].maxX, 0, 300));
|
||||
assert.strictEqual(true, isInteger(stats.channels[3].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[3].maxY, 0, 300));
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -214,20 +214,20 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 0.3851250782608986));
|
||||
|
||||
// red channel
|
||||
assert.strictEqual(0, stats.channels[0]['min']);
|
||||
assert.strictEqual(255, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 1887266220));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 481252886100));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 235.81772349417824));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 67.25712856093298));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2464));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 3248));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2464));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 3248));
|
||||
assert.strictEqual(0, stats.channels[0].min);
|
||||
assert.strictEqual(255, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 1887266220));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 481252886100));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 235.81772349417824));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 67.25712856093298));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2464));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 3248));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2464));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 3248));
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -241,52 +241,52 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.51758075132966));
|
||||
|
||||
// red channel
|
||||
assert.strictEqual(0, stats.channels[0]['min']);
|
||||
assert.strictEqual(255, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 83291370));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 11379783198));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 105.36169496842616));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 57.39412151419967));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 772));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 772));
|
||||
assert.strictEqual(0, stats.channels[0].min);
|
||||
assert.strictEqual(255, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 83291370));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 11379783198));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 105.36169496842616));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 57.39412151419967));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 772));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 772));
|
||||
|
||||
// green channel
|
||||
assert.strictEqual(0, stats.channels[1]['min']);
|
||||
assert.strictEqual(255, stats.channels[1]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['sum'], 120877425));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['squaresSum'], 20774687595));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['mean'], 152.9072025279307));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['stdev'], 53.84143349689916));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minX'], 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minY'], 0, 772));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxX'], 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxY'], 0, 772));
|
||||
assert.strictEqual(0, stats.channels[1].min);
|
||||
assert.strictEqual(255, stats.channels[1].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].sum, 120877425));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].squaresSum, 20774687595));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].mean, 152.9072025279307));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].stdev, 53.84143349689916));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minX, 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minY, 0, 772));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxX, 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxY, 0, 772));
|
||||
|
||||
// blue channel
|
||||
assert.strictEqual(0, stats.channels[2]['min']);
|
||||
assert.strictEqual(255, stats.channels[2]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['sum'], 138938859));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['squaresSum'], 28449125593));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['mean'], 175.75450711423252));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['stdev'], 71.39929031070358));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minX'], 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minY'], 0, 772));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxX'], 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxY'], 0, 772));
|
||||
assert.strictEqual(0, stats.channels[2].min);
|
||||
assert.strictEqual(255, stats.channels[2].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].sum, 138938859));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].squaresSum, 28449125593));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].mean, 175.75450711423252));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].stdev, 71.39929031070358));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minX, 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minY, 0, 772));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxX, 0, 1024));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxY, 0, 772));
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -300,52 +300,52 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 6.087309412541799));
|
||||
|
||||
// red channel
|
||||
assert.strictEqual(35, stats.channels[0]['min']);
|
||||
assert.strictEqual(254, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 56088385));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 8002132113));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 131.53936444652908));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 38.26389131415863));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 533));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 533));
|
||||
assert.strictEqual(35, stats.channels[0].min);
|
||||
assert.strictEqual(254, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 56088385));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 8002132113));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 131.53936444652908));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 38.26389131415863));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 533));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 533));
|
||||
|
||||
// green channel
|
||||
assert.strictEqual(43, stats.channels[1]['min']);
|
||||
assert.strictEqual(255, stats.channels[1]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['sum'], 58612156));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['squaresSum'], 8548344254));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['mean'], 137.45815196998123));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['stdev'], 33.955424103758205));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minX'], 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minY'], 0, 533));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxX'], 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxY'], 0, 533));
|
||||
assert.strictEqual(43, stats.channels[1].min);
|
||||
assert.strictEqual(255, stats.channels[1].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].sum, 58612156));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].squaresSum, 8548344254));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].mean, 137.45815196998123));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].stdev, 33.955424103758205));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minX, 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minY, 0, 533));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxX, 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxY, 0, 533));
|
||||
|
||||
// blue channel
|
||||
assert.strictEqual(51, stats.channels[2]['min']);
|
||||
assert.strictEqual(254, stats.channels[2]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['sum'], 49628525));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['squaresSum'], 6450556071));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['mean'], 116.38959896810506));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['stdev'], 39.7669551046809));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minX'], 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minY'], 0, 533));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxX'], 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxY'], 0, 533));
|
||||
assert.strictEqual(51, stats.channels[2].min);
|
||||
assert.strictEqual(254, stats.channels[2].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].sum, 49628525));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].squaresSum, 6450556071));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].mean, 116.38959896810506));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].stdev, 39.7669551046809));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minX, 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minY, 0, 533));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxX, 0, 800));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxY, 0, 533));
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -359,36 +359,36 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 1));
|
||||
|
||||
// gray channel
|
||||
assert.strictEqual(0, stats.channels[0]['min']);
|
||||
assert.strictEqual(101, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 101));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 10201));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 50.5));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 71.4177848998413));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 1));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 1));
|
||||
assert.strictEqual(0, stats.channels[0].min);
|
||||
assert.strictEqual(101, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 101));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 10201));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 50.5));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 71.4177848998413));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 1));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 1));
|
||||
|
||||
// alpha channel
|
||||
assert.strictEqual(0, stats.channels[1]['min']);
|
||||
assert.strictEqual(255, stats.channels[1]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['sum'], 255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['squaresSum'], 65025));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['mean'], 127.5));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['stdev'], 180.31222920256963));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minX'], 0, 2));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minY'], 0, 1));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxX'], 0, 2));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxY'], 0, 1));
|
||||
assert.strictEqual(0, stats.channels[1].min);
|
||||
assert.strictEqual(255, stats.channels[1].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].sum, 255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].squaresSum, 65025));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].mean, 127.5));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].stdev, 180.31222920256963));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minX, 0, 2));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minY, 0, 1));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxX, 0, 2));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxY, 0, 1));
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -412,52 +412,52 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.319914765248541));
|
||||
|
||||
// red channel
|
||||
assert.strictEqual(0, stats.channels[0]['min']);
|
||||
assert.strictEqual(255, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 615101275));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 83061892917));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 101.44954540768993));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 58.373870588815414));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[0].min);
|
||||
assert.strictEqual(255, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 615101275));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 83061892917));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 101.44954540768993));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 58.373870588815414));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 2725));
|
||||
|
||||
// green channel
|
||||
assert.strictEqual(0, stats.channels[1]['min']);
|
||||
assert.strictEqual(255, stats.channels[1]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['sum'], 462824115));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['squaresSum'], 47083677255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['mean'], 76.33425255128337));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['stdev'], 44.03023262954866));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[1].min);
|
||||
assert.strictEqual(255, stats.channels[1].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].sum, 462824115));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].squaresSum, 47083677255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].mean, 76.33425255128337));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].stdev, 44.03023262954866));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[1].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[1].maxY, 0, 2725));
|
||||
|
||||
// blue channel
|
||||
assert.strictEqual(0, stats.channels[2]['min']);
|
||||
assert.strictEqual(255, stats.channels[2]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['sum'], 372986756));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['squaresSum'], 32151543524));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['mean'], 61.51724663436759));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['stdev'], 38.96702865090125));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[2].min);
|
||||
assert.strictEqual(255, stats.channels[2].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].sum, 372986756));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].squaresSum, 32151543524));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].mean, 61.51724663436759));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].stdev, 38.96702865090125));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[2].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[2].maxY, 0, 2725));
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -474,52 +474,52 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.319914765248541));
|
||||
|
||||
// red channel
|
||||
assert.strictEqual(0, stats.channels[0]['min']);
|
||||
assert.strictEqual(255, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 615101275));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 83061892917));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 101.44954540768993));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 58.373870588815414));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[0].min);
|
||||
assert.strictEqual(255, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 615101275));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 83061892917));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 101.44954540768993));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 58.373870588815414));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 2725));
|
||||
|
||||
// green channel
|
||||
assert.strictEqual(0, stats.channels[1]['min']);
|
||||
assert.strictEqual(255, stats.channels[1]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['sum'], 462824115));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['squaresSum'], 47083677255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['mean'], 76.33425255128337));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['stdev'], 44.03023262954866));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[1].min);
|
||||
assert.strictEqual(255, stats.channels[1].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].sum, 462824115));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].squaresSum, 47083677255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].mean, 76.33425255128337));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].stdev, 44.03023262954866));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 2725));
|
||||
|
||||
// blue channel
|
||||
assert.strictEqual(0, stats.channels[2]['min']);
|
||||
assert.strictEqual(255, stats.channels[2]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['sum'], 372986756));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['squaresSum'], 32151543524));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['mean'], 61.51724663436759));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['stdev'], 38.96702865090125));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[2].min);
|
||||
assert.strictEqual(255, stats.channels[2].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].sum, 372986756));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].squaresSum, 32151543524));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].mean, 61.51724663436759));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].stdev, 38.96702865090125));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 2725));
|
||||
}).catch(function (err) {
|
||||
throw err;
|
||||
});
|
||||
@@ -531,52 +531,52 @@ describe('Image Stats', function () {
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.entropy, 7.319914765248541));
|
||||
|
||||
// red channel
|
||||
assert.strictEqual(0, stats.channels[0]['min']);
|
||||
assert.strictEqual(255, stats.channels[0]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['sum'], 615101275));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['squaresSum'], 83061892917));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['mean'], 101.44954540768993));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0]['stdev'], 58.373870588815414));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[0].min);
|
||||
assert.strictEqual(255, stats.channels[0].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].sum, 615101275));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].squaresSum, 83061892917));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].mean, 101.44954540768993));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[0].stdev, 58.373870588815414));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 2725));
|
||||
|
||||
// green channel
|
||||
assert.strictEqual(0, stats.channels[1]['min']);
|
||||
assert.strictEqual(255, stats.channels[1]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['sum'], 462824115));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['squaresSum'], 47083677255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['mean'], 76.33425255128337));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1]['stdev'], 44.03023262954866));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[1].min);
|
||||
assert.strictEqual(255, stats.channels[1].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].sum, 462824115));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].squaresSum, 47083677255));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].mean, 76.33425255128337));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[1].stdev, 44.03023262954866));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 2725));
|
||||
|
||||
// blue channel
|
||||
assert.strictEqual(0, stats.channels[2]['min']);
|
||||
assert.strictEqual(255, stats.channels[2]['max']);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['sum'], 372986756));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['squaresSum'], 32151543524));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['mean'], 61.51724663436759));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2]['stdev'], 38.96702865090125));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['minY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['minY'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxX']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxX'], 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0]['maxY']));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0]['maxY'], 0, 2725));
|
||||
assert.strictEqual(0, stats.channels[2].min);
|
||||
assert.strictEqual(255, stats.channels[2].max);
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].sum, 372986756));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].squaresSum, 32151543524));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].mean, 61.51724663436759));
|
||||
assert.strictEqual(true, isInAcceptableRange(stats.channels[2].stdev, 38.96702865090125));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].minY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].minY, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxX));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxX, 0, 2725));
|
||||
assert.strictEqual(true, isInteger(stats.channels[0].maxY));
|
||||
assert.strictEqual(true, isInRange(stats.channels[0].maxY, 0, 2725));
|
||||
}).catch(function (err) {
|
||||
throw err;
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
const fs = require('fs');
|
||||
const assert = require('assert');
|
||||
const promisify = require('util').promisify;
|
||||
const rimraf = require('rimraf');
|
||||
|
||||
const sharp = require('../../');
|
||||
@@ -85,6 +86,19 @@ describe('TIFF', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Increasing TIFF quality increases file size', () =>
|
||||
sharp(fixtures.inputJpgWithLandscapeExif1)
|
||||
.tiff({ quality: 40 })
|
||||
.toBuffer()
|
||||
.then(tiff40 => sharp(fixtures.inputJpgWithLandscapeExif1)
|
||||
.tiff({ quality: 90 })
|
||||
.toBuffer()
|
||||
.then(tiff90 =>
|
||||
assert.strictEqual(true, tiff40.length < tiff90.length)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
it('Invalid TIFF quality throws error', function () {
|
||||
assert.throws(function () {
|
||||
sharp().tiff({ quality: 101 });
|
||||
@@ -137,40 +151,40 @@ describe('TIFF', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('TIFF setting xres and yres on file', function (done) {
|
||||
const res = 1000.0; // inputTiff has a dpi of 300 (res*2.54)
|
||||
it('TIFF setting xres and yres on file', () =>
|
||||
sharp(fixtures.inputTiff)
|
||||
.tiff({
|
||||
xres: (res),
|
||||
yres: (res)
|
||||
xres: 1000,
|
||||
yres: 1000
|
||||
})
|
||||
.toFile(fixtures.outputTiff, (err, info) => {
|
||||
if (err) throw err;
|
||||
assert.strictEqual('tiff', info.format);
|
||||
sharp(fixtures.outputTiff).metadata(function (err, metadata) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(metadata.density, res * 2.54); // convert to dpi
|
||||
rimraf(fixtures.outputTiff, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
.toFile(fixtures.outputTiff)
|
||||
.then(() => sharp(fixtures.outputTiff)
|
||||
.metadata()
|
||||
.then(({ density }) => {
|
||||
assert.strictEqual(true,
|
||||
density === 2540 || // libvips <= 8.8.2
|
||||
density === 25400); // libvips >= 8.8.3
|
||||
return promisify(rimraf)(fixtures.outputTiff);
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
it('TIFF setting xres and yres on buffer', function (done) {
|
||||
const res = 1000.0; // inputTiff has a dpi of 300 (res*2.54)
|
||||
it('TIFF setting xres and yres on buffer', () =>
|
||||
sharp(fixtures.inputTiff)
|
||||
.tiff({
|
||||
xres: (res),
|
||||
yres: (res)
|
||||
xres: 1000,
|
||||
yres: 1000
|
||||
})
|
||||
.toBuffer(function (err, data, info) {
|
||||
if (err) throw err;
|
||||
sharp(data).metadata(function (err, metadata) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(metadata.density, res * 2.54); // convert to dpi
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
.toBuffer()
|
||||
.then(data => sharp(data)
|
||||
.metadata()
|
||||
.then(({ density }) => {
|
||||
assert.strictEqual(true,
|
||||
density === 2540 || // libvips <= 8.8.2
|
||||
density === 25400); // libvips >= 8.8.3
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
it('TIFF invalid xres value should throw an error', function () {
|
||||
assert.throws(function () {
|
||||
|
||||
@@ -56,7 +56,7 @@ const assertZoomifyTiles = function (directory, expectedTileSize, expectedLevels
|
||||
fs.readdirSync(path.join(directory, 'TileGroup0')).forEach(function (tile) {
|
||||
// Verify tile file name
|
||||
assert.ok(/^[0-9]+-[0-9]+-[0-9]+\.jpg$/.test(tile));
|
||||
let level = parseInt(tile.split('-')[0]);
|
||||
const level = parseInt(tile.split('-')[0]);
|
||||
maxTileLevel = Math.max(maxTileLevel, level);
|
||||
});
|
||||
|
||||
@@ -91,6 +91,29 @@ const assertGoogleTiles = function (directory, expectedTileSize, expectedLevels,
|
||||
});
|
||||
};
|
||||
|
||||
// Verifies tiles at specified level in a given output directory are > size+overlap
|
||||
const assertTileOverlap = function (directory, tileSize, done) {
|
||||
// Get sorted levels
|
||||
const levels = fs.readdirSync(directory).sort((a, b) => a - b);
|
||||
// Select the highest tile level
|
||||
const highestLevel = levels[levels.length - 1];
|
||||
// Get sorted tiles from greatest level
|
||||
const tiles = fs.readdirSync(path.join(directory, highestLevel)).sort();
|
||||
// Select a tile from the approximate center of the image
|
||||
const squareTile = path.join(directory, highestLevel, tiles[Math.floor(tiles.length / 2)]);
|
||||
|
||||
sharp(squareTile).metadata(function (err, metadata) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
// Tile with an overlap should be larger than original size
|
||||
assert.strictEqual(true, metadata.width > tileSize);
|
||||
assert.strictEqual(true, metadata.height > tileSize);
|
||||
done();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
describe('Tile', function () {
|
||||
it('Valid size values pass', function () {
|
||||
[1, 8192].forEach(function (size) {
|
||||
@@ -297,7 +320,9 @@ describe('Tile', function () {
|
||||
assert.strictEqual(2225, info.height);
|
||||
assert.strictEqual(3, info.channels);
|
||||
assert.strictEqual('undefined', typeof info.size);
|
||||
assertDeepZoomTiles(directory, 512 + (2 * 16), 13, done);
|
||||
assertDeepZoomTiles(directory, 512 + (2 * 16), 13, function () {
|
||||
assertTileOverlap(directory, 512, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -319,7 +344,7 @@ describe('Tile', function () {
|
||||
assert.strictEqual('undefined', typeof info.size);
|
||||
assertDeepZoomTiles(directory, 512, 13, done);
|
||||
// Verifies tiles in 10th level are rotated
|
||||
let tile = path.join(directory, '10', '0_1.jpeg');
|
||||
const tile = path.join(directory, '10', '0_1.jpeg');
|
||||
// verify that the width and height correspond to the rotated image
|
||||
// expected are w=512 and h=170 for the 0_1.jpeg.
|
||||
// if a 0 angle is supplied to the .tile function
|
||||
@@ -396,7 +421,7 @@ describe('Tile', function () {
|
||||
if (err) throw err;
|
||||
// assert them 0_0.jpeg doesn't exist because it's a white tile
|
||||
const whiteTilePath = path.join(directory, '11', '0_0.jpeg');
|
||||
assert.strictEqual(fs.existsSync(whiteTilePath), false, `Tile shouldn't exist`);
|
||||
assert.strictEqual(fs.existsSync(whiteTilePath), false, 'Tile should not exist');
|
||||
// Verify only one depth generated
|
||||
assertDeepZoomTiles(directory, 256, 12, done);
|
||||
});
|
||||
@@ -503,7 +528,7 @@ describe('Tile', function () {
|
||||
if (err) throw err;
|
||||
// assert them 0_0.jpeg doesn't exist because it's a white tile
|
||||
const whiteTilePath = path.join(directory, 'TileGroup0', '2-0-0.jpg');
|
||||
assert.strictEqual(fs.existsSync(whiteTilePath), false, `Tile shouldn't exist`);
|
||||
assert.strictEqual(fs.existsSync(whiteTilePath), false, 'Tile should not exist');
|
||||
assert.strictEqual('dz', info.format);
|
||||
assert.strictEqual(2048, info.width);
|
||||
assert.strictEqual(1536, info.height);
|
||||
@@ -727,7 +752,7 @@ describe('Tile', function () {
|
||||
if (err) throw err;
|
||||
|
||||
const whiteTilePath = path.join(directory, '4', '8', '0.jpg');
|
||||
assert.strictEqual(fs.existsSync(whiteTilePath), false, `Tile shouldn't exist`);
|
||||
assert.strictEqual(fs.existsSync(whiteTilePath), false, 'Tile should not exist');
|
||||
|
||||
assert.strictEqual('dz', info.format);
|
||||
assert.strictEqual(2809, info.width);
|
||||
|
||||
19
test/unit/toBuffer.js
Normal file
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
const sharp = require('../../');
|
||||
const fixtures = require('../fixtures');
|
||||
|
||||
describe('toBuffer', () => {
|
||||
it('reusing same sharp object does not reset previously passed parameters to toBuffer', (done) => {
|
||||
const image = sharp(fixtures.inputJpg);
|
||||
image.toBuffer({ resolveWithObject: true }).then((obj) => {
|
||||
image.toBuffer().then((buff) => {
|
||||
assert.strict.equal(Buffer.isBuffer(buff), true);
|
||||
assert.strict.equal(typeof obj, 'object');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -41,6 +41,21 @@ describe('Trim borders', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('single colour PNG where alpha channel provides the image', () =>
|
||||
sharp(fixtures.inputPngImageInAlpha)
|
||||
.trim()
|
||||
.toBuffer({ resolveWithObject: true })
|
||||
.then(({ data, info }) => {
|
||||
assert.strictEqual(true, data.length > 0);
|
||||
assert.strictEqual('png', info.format);
|
||||
assert.strictEqual(916, info.width);
|
||||
assert.strictEqual(137, info.height);
|
||||
assert.strictEqual(4, info.channels);
|
||||
assert.strictEqual(-6, info.trimOffsetLeft);
|
||||
assert.strictEqual(-20, info.trimOffsetTop);
|
||||
})
|
||||
);
|
||||
|
||||
it('16-bit PNG with alpha channel', function (done) {
|
||||
sharp(fixtures.inputPngWithTransparency16bit)
|
||||
.resize(32, 32)
|
||||
@@ -58,6 +73,27 @@ describe('Trim borders', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('Attempt to trim 2x2 pixel image fails', function (done) {
|
||||
sharp({
|
||||
create: {
|
||||
width: 2,
|
||||
height: 2,
|
||||
channels: 3,
|
||||
background: 'red'
|
||||
}
|
||||
})
|
||||
.trim()
|
||||
.toBuffer()
|
||||
.then(() => {
|
||||
done(new Error('Expected an error'));
|
||||
})
|
||||
.catch(err => {
|
||||
assert.strictEqual('Image to trim must be at least 3x3 pixels', err.message);
|
||||
done();
|
||||
})
|
||||
.catch(done);
|
||||
});
|
||||
|
||||
describe('Invalid thresholds', function () {
|
||||
[-1, 'fail', {}].forEach(function (threshold) {
|
||||
it(JSON.stringify(threshold), function () {
|
||||
|
||||
@@ -118,6 +118,13 @@ describe('Utilities', function () {
|
||||
assert.strictEqual(true, sharp.format.raw[direction].stream);
|
||||
});
|
||||
});
|
||||
it('vips format supports filesystem only', function () {
|
||||
['input', 'output'].forEach(function (direction) {
|
||||
assert.strictEqual(true, sharp.format.vips[direction].file);
|
||||
assert.strictEqual(false, sharp.format.vips[direction].buffer);
|
||||
assert.strictEqual(false, sharp.format.vips[direction].stream);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Versions', function () {
|
||||
|
||||