UNPKG

7.36 kBJavaScriptView Raw
1// Copyright 2013 Lovell Fuller and others.
2// SPDX-License-Identifier: Apache-2.0
3
4'use strict';
5
6const fs = require('fs');
7const path = require('path');
8const events = require('events');
9const detectLibc = require('detect-libc');
10
11const is = require('./is');
12const platformAndArch = require('./platform')();
13const sharp = require('./sharp');
14
15/**
16 * An Object containing nested boolean values representing the available input and output formats/methods.
17 * @member
18 * @example
19 * console.log(sharp.format);
20 * @returns {Object}
21 */
22const format = sharp.format();
23format.heif.output.alias = ['avif', 'heic'];
24format.jpeg.output.alias = ['jpe', 'jpg'];
25format.tiff.output.alias = ['tif'];
26format.jp2k.output.alias = ['j2c', 'j2k', 'jp2', 'jpx'];
27
28/**
29 * An Object containing the available interpolators and their proper values
30 * @readonly
31 * @enum {string}
32 */
33const interpolators = {
34 /** [Nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation). Suitable for image enlargement only. */
35 nearest: 'nearest',
36 /** [Bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation). Faster than bicubic but with less smooth results. */
37 bilinear: 'bilinear',
38 /** [Bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) (the default). */
39 bicubic: 'bicubic',
40 /** [LBB interpolation](https://github.com/libvips/libvips/blob/master/libvips/resample/lbb.cpp#L100). Prevents some "[acutance](http://en.wikipedia.org/wiki/Acutance)" but typically reduces performance by a factor of 2. */
41 locallyBoundedBicubic: 'lbb',
42 /** [Nohalo interpolation](http://eprints.soton.ac.uk/268086/). Prevents acutance but typically reduces performance by a factor of 3. */
43 nohalo: 'nohalo',
44 /** [VSQBS interpolation](https://github.com/libvips/libvips/blob/master/libvips/resample/vsqbs.cpp#L48). Prevents "staircasing" when enlarging. */
45 vertexSplitQuadraticBasisSpline: 'vsqbs'
46};
47
48/**
49 * An Object containing the version numbers of sharp, libvips and its dependencies.
50 * @member
51 * @example
52 * console.log(sharp.versions);
53 */
54let versions = {
55 vips: sharp.libvipsVersion()
56};
57try {
58 versions = require(`../vendor/${versions.vips}/${platformAndArch}/versions.json`);
59} catch (_err) { /* ignore */ }
60versions.sharp = require('../package.json').version;
61
62/**
63 * An Object containing the platform and architecture
64 * of the current and installed vendored binaries.
65 * @member
66 * @example
67 * console.log(sharp.vendor);
68 */
69const vendor = {
70 current: platformAndArch,
71 installed: []
72};
73try {
74 vendor.installed = fs.readdirSync(path.join(__dirname, `../vendor/${versions.vips}`));
75} catch (_err) { /* ignore */ }
76
77/**
78 * Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
79 * Existing entries in the cache will be trimmed after any change in limits.
80 * This method always returns cache statistics,
81 * useful for determining how much working memory is required for a particular task.
82 *
83 * @example
84 * const stats = sharp.cache();
85 * @example
86 * sharp.cache( { items: 200 } );
87 * sharp.cache( { files: 0 } );
88 * sharp.cache(false);
89 *
90 * @param {Object|boolean} [options=true] - Object with the following attributes, or boolean where true uses default cache settings and false removes all caching
91 * @param {number} [options.memory=50] - is the maximum memory in MB to use for this cache
92 * @param {number} [options.files=20] - is the maximum number of files to hold open
93 * @param {number} [options.items=100] - is the maximum number of operations to cache
94 * @returns {Object}
95 */
96function cache (options) {
97 if (is.bool(options)) {
98 if (options) {
99 // Default cache settings of 50MB, 20 files, 100 items
100 return sharp.cache(50, 20, 100);
101 } else {
102 return sharp.cache(0, 0, 0);
103 }
104 } else if (is.object(options)) {
105 return sharp.cache(options.memory, options.files, options.items);
106 } else {
107 return sharp.cache();
108 }
109}
110cache(true);
111
112/**
113 * Gets or, when a concurrency is provided, sets
114 * the maximum number of threads _libvips_ should use to process _each image_.
115 * These are from a thread pool managed by glib,
116 * which helps avoid the overhead of creating new threads.
117 *
118 * This method always returns the current concurrency.
119 *
120 * The default value is the number of CPU cores,
121 * except when using glibc-based Linux without jemalloc,
122 * where the default is `1` to help reduce memory fragmentation.
123 *
124 * A value of `0` will reset this to the number of CPU cores.
125 *
126 * Some image format libraries spawn additional threads,
127 * e.g. libaom manages its own 4 threads when encoding AVIF images,
128 * and these are independent of the value set here.
129 *
130 * The maximum number of images that sharp can process in parallel
131 * is controlled by libuv's `UV_THREADPOOL_SIZE` environment variable,
132 * which defaults to 4.
133 *
134 * https://nodejs.org/api/cli.html#uv_threadpool_sizesize
135 *
136 * For example, by default, a machine with 8 CPU cores will process
137 * 4 images in parallel and use up to 8 threads per image,
138 * so there will be up to 32 concurrent threads.
139 *
140 * @example
141 * const threads = sharp.concurrency(); // 4
142 * sharp.concurrency(2); // 2
143 * sharp.concurrency(0); // 4
144 *
145 * @param {number} [concurrency]
146 * @returns {number} concurrency
147 */
148function concurrency (concurrency) {
149 return sharp.concurrency(is.integer(concurrency) ? concurrency : null);
150}
151/* istanbul ignore next */
152if (detectLibc.familySync() === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
153 // Reduce default concurrency to 1 when using glibc memory allocator
154 sharp.concurrency(1);
155}
156
157/**
158 * An EventEmitter that emits a `change` event when a task is either:
159 * - queued, waiting for _libuv_ to provide a worker thread
160 * - complete
161 * @member
162 * @example
163 * sharp.queue.on('change', function(queueLength) {
164 * console.log('Queue contains ' + queueLength + ' task(s)');
165 * });
166 */
167const queue = new events.EventEmitter();
168
169/**
170 * Provides access to internal task counters.
171 * - queue is the number of tasks this module has queued waiting for _libuv_ to provide a worker thread from its pool.
172 * - process is the number of resize tasks currently being processed.
173 *
174 * @example
175 * const counters = sharp.counters(); // { queue: 2, process: 4 }
176 *
177 * @returns {Object}
178 */
179function counters () {
180 return sharp.counters();
181}
182
183/**
184 * Get and set use of SIMD vector unit instructions.
185 * Requires libvips to have been compiled with liborc support.
186 *
187 * Improves the performance of `resize`, `blur` and `sharpen` operations
188 * by taking advantage of the SIMD vector unit of the CPU, e.g. Intel SSE and ARM NEON.
189 *
190 * @example
191 * const simd = sharp.simd();
192 * // simd is `true` if the runtime use of liborc is currently enabled
193 * @example
194 * const simd = sharp.simd(false);
195 * // prevent libvips from using liborc at runtime
196 *
197 * @param {boolean} [simd=true]
198 * @returns {boolean}
199 */
200function simd (simd) {
201 return sharp.simd(is.bool(simd) ? simd : null);
202}
203simd(true);
204
205/**
206 * Decorate the Sharp class with utility-related functions.
207 * @private
208 */
209module.exports = function (Sharp) {
210 Sharp.cache = cache;
211 Sharp.concurrency = concurrency;
212 Sharp.counters = counters;
213 Sharp.simd = simd;
214 Sharp.format = format;
215 Sharp.interpolators = interpolators;
216 Sharp.versions = versions;
217 Sharp.vendor = vendor;
218 Sharp.queue = queue;
219};