UNPKG

5.31 kBJavaScriptView Raw
1// Copyright 2013 Lovell Fuller and others.
2// SPDX-License-Identifier: Apache-2.0
3
4'use strict';
5
6const color = require('color');
7const is = require('./is');
8
9/**
10 * Colourspaces.
11 * @private
12 */
13const colourspace = {
14 multiband: 'multiband',
15 'b-w': 'b-w',
16 bw: 'b-w',
17 cmyk: 'cmyk',
18 srgb: 'srgb'
19};
20
21/**
22 * Tint the image using the provided chroma while preserving the image luminance.
23 * An alpha channel may be present and will be unchanged by the operation.
24 *
25 * @example
26 * const output = await sharp(input)
27 * .tint({ r: 255, g: 240, b: 16 })
28 * .toBuffer();
29 *
30 * @param {string|Object} rgb - parsed by the [color](https://www.npmjs.org/package/color) module to extract chroma values.
31 * @returns {Sharp}
32 * @throws {Error} Invalid parameter
33 */
34function tint (rgb) {
35 const colour = color(rgb);
36 this.options.tintA = colour.a();
37 this.options.tintB = colour.b();
38 return this;
39}
40
41/**
42 * Convert to 8-bit greyscale; 256 shades of grey.
43 * This is a linear operation. If the input image is in a non-linear colour space such as sRGB, use `gamma()` with `greyscale()` for the best results.
44 * By default the output image will be web-friendly sRGB and contain three (identical) color channels.
45 * This may be overridden by other sharp operations such as `toColourspace('b-w')`,
46 * which will produce an output image containing one color channel.
47 * An alpha channel may be present, and will be unchanged by the operation.
48 *
49 * @example
50 * const output = await sharp(input).greyscale().toBuffer();
51 *
52 * @param {Boolean} [greyscale=true]
53 * @returns {Sharp}
54 */
55function greyscale (greyscale) {
56 this.options.greyscale = is.bool(greyscale) ? greyscale : true;
57 return this;
58}
59
60/**
61 * Alternative spelling of `greyscale`.
62 * @param {Boolean} [grayscale=true]
63 * @returns {Sharp}
64 */
65function grayscale (grayscale) {
66 return this.greyscale(grayscale);
67}
68
69/**
70 * Set the pipeline colourspace.
71 *
72 * The input image will be converted to the provided colourspace at the start of the pipeline.
73 * All operations will use this colourspace before converting to the output colourspace,
74 * as defined by {@link #tocolourspace|toColourspace}.
75 *
76 * This feature is experimental and has not yet been fully-tested with all operations.
77 *
78 * @since 0.29.0
79 *
80 * @example
81 * // Run pipeline in 16 bits per channel RGB while converting final result to 8 bits per channel sRGB.
82 * await sharp(input)
83 * .pipelineColourspace('rgb16')
84 * .toColourspace('srgb')
85 * .toFile('16bpc-pipeline-to-8bpc-output.png')
86 *
87 * @param {string} [colourspace] - pipeline colourspace e.g. `rgb16`, `scrgb`, `lab`, `grey16` [...](https://github.com/libvips/libvips/blob/41cff4e9d0838498487a00623462204eb10ee5b8/libvips/iofuncs/enumtypes.c#L774)
88 * @returns {Sharp}
89 * @throws {Error} Invalid parameters
90 */
91function pipelineColourspace (colourspace) {
92 if (!is.string(colourspace)) {
93 throw is.invalidParameterError('colourspace', 'string', colourspace);
94 }
95 this.options.colourspaceInput = colourspace;
96 return this;
97}
98
99/**
100 * Alternative spelling of `pipelineColourspace`.
101 * @param {string} [colorspace] - pipeline colorspace.
102 * @returns {Sharp}
103 * @throws {Error} Invalid parameters
104 */
105function pipelineColorspace (colorspace) {
106 return this.pipelineColourspace(colorspace);
107}
108
109/**
110 * Set the output colourspace.
111 * By default output image will be web-friendly sRGB, with additional channels interpreted as alpha channels.
112 *
113 * @example
114 * // Output 16 bits per pixel RGB
115 * await sharp(input)
116 * .toColourspace('rgb16')
117 * .toFile('16-bpp.png')
118 *
119 * @param {string} [colourspace] - output colourspace e.g. `srgb`, `rgb`, `cmyk`, `lab`, `b-w` [...](https://github.com/libvips/libvips/blob/3c0bfdf74ce1dc37a6429bed47fa76f16e2cd70a/libvips/iofuncs/enumtypes.c#L777-L794)
120 * @returns {Sharp}
121 * @throws {Error} Invalid parameters
122 */
123function toColourspace (colourspace) {
124 if (!is.string(colourspace)) {
125 throw is.invalidParameterError('colourspace', 'string', colourspace);
126 }
127 this.options.colourspace = colourspace;
128 return this;
129}
130
131/**
132 * Alternative spelling of `toColourspace`.
133 * @param {string} [colorspace] - output colorspace.
134 * @returns {Sharp}
135 * @throws {Error} Invalid parameters
136 */
137function toColorspace (colorspace) {
138 return this.toColourspace(colorspace);
139}
140
141/**
142 * Update a colour attribute of the this.options Object.
143 * @private
144 * @param {string} key
145 * @param {string|Object} value
146 * @throws {Error} Invalid value
147 */
148function _setBackgroundColourOption (key, value) {
149 if (is.defined(value)) {
150 if (is.object(value) || is.string(value)) {
151 const colour = color(value);
152 this.options[key] = [
153 colour.red(),
154 colour.green(),
155 colour.blue(),
156 Math.round(colour.alpha() * 255)
157 ];
158 } else {
159 throw is.invalidParameterError('background', 'object or string', value);
160 }
161 }
162}
163
164/**
165 * Decorate the Sharp prototype with colour-related functions.
166 * @private
167 */
168module.exports = function (Sharp) {
169 Object.assign(Sharp.prototype, {
170 // Public
171 tint,
172 greyscale,
173 grayscale,
174 pipelineColourspace,
175 pipelineColorspace,
176 toColourspace,
177 toColorspace,
178 // Private
179 _setBackgroundColourOption
180 });
181 // Class attributes
182 Sharp.colourspace = colourspace;
183 Sharp.colorspace = colourspace;
184};