UNPKG

5.3 kBJavaScriptView Raw
1// Copyright 2013 Lovell Fuller and others.
2// SPDX-License-Identifier: Apache-2.0
3
4'use strict';
5
6const is = require('./is');
7
8/**
9 * Boolean operations for bandbool.
10 * @private
11 */
12const bool = {
13 and: 'and',
14 or: 'or',
15 eor: 'eor'
16};
17
18/**
19 * Remove alpha channel, if any. This is a no-op if the image does not have an alpha channel.
20 *
21 * See also {@link /api-operation#flatten|flatten}.
22 *
23 * @example
24 * sharp('rgba.png')
25 * .removeAlpha()
26 * .toFile('rgb.png', function(err, info) {
27 * // rgb.png is a 3 channel image without an alpha channel
28 * });
29 *
30 * @returns {Sharp}
31 */
32function removeAlpha () {
33 this.options.removeAlpha = true;
34 return this;
35}
36
37/**
38 * Ensure the output image has an alpha transparency channel.
39 * If missing, the added alpha channel will have the specified
40 * transparency level, defaulting to fully-opaque (1).
41 * This is a no-op if the image already has an alpha channel.
42 *
43 * @since 0.21.2
44 *
45 * @example
46 * // rgba.png will be a 4 channel image with a fully-opaque alpha channel
47 * await sharp('rgb.jpg')
48 * .ensureAlpha()
49 * .toFile('rgba.png')
50 *
51 * @example
52 * // rgba is a 4 channel image with a fully-transparent alpha channel
53 * const rgba = await sharp(rgb)
54 * .ensureAlpha(0)
55 * .toBuffer();
56 *
57 * @param {number} [alpha=1] - alpha transparency level (0=fully-transparent, 1=fully-opaque)
58 * @returns {Sharp}
59 * @throws {Error} Invalid alpha transparency level
60 */
61function ensureAlpha (alpha) {
62 if (is.defined(alpha)) {
63 if (is.number(alpha) && is.inRange(alpha, 0, 1)) {
64 this.options.ensureAlpha = alpha;
65 } else {
66 throw is.invalidParameterError('alpha', 'number between 0 and 1', alpha);
67 }
68 } else {
69 this.options.ensureAlpha = 1;
70 }
71 return this;
72}
73
74/**
75 * Extract a single channel from a multi-channel image.
76 *
77 * @example
78 * // green.jpg is a greyscale image containing the green channel of the input
79 * await sharp(input)
80 * .extractChannel('green')
81 * .toFile('green.jpg');
82 *
83 * @example
84 * // red1 is the red value of the first pixel, red2 the second pixel etc.
85 * const [red1, red2, ...] = await sharp(input)
86 * .extractChannel(0)
87 * .raw()
88 * .toBuffer();
89 *
90 * @param {number|string} channel - zero-indexed channel/band number to extract, or `red`, `green`, `blue` or `alpha`.
91 * @returns {Sharp}
92 * @throws {Error} Invalid channel
93 */
94function extractChannel (channel) {
95 const channelMap = { red: 0, green: 1, blue: 2, alpha: 3 };
96 if (Object.keys(channelMap).includes(channel)) {
97 channel = channelMap[channel];
98 }
99 if (is.integer(channel) && is.inRange(channel, 0, 4)) {
100 this.options.extractChannel = channel;
101 } else {
102 throw is.invalidParameterError('channel', 'integer or one of: red, green, blue, alpha', channel);
103 }
104 return this;
105}
106
107/**
108 * Join one or more channels to the image.
109 * The meaning of the added channels depends on the output colourspace, set with `toColourspace()`.
110 * By default the output image will be web-friendly sRGB, with additional channels interpreted as alpha channels.
111 * Channel ordering follows vips convention:
112 * - sRGB: 0: Red, 1: Green, 2: Blue, 3: Alpha.
113 * - CMYK: 0: Magenta, 1: Cyan, 2: Yellow, 3: Black, 4: Alpha.
114 *
115 * Buffers may be any of the image formats supported by sharp.
116 * For raw pixel input, the `options` object should contain a `raw` attribute, which follows the format of the attribute of the same name in the `sharp()` constructor.
117 *
118 * @param {Array<string|Buffer>|string|Buffer} images - one or more images (file paths, Buffers).
119 * @param {Object} options - image options, see `sharp()` constructor.
120 * @returns {Sharp}
121 * @throws {Error} Invalid parameters
122 */
123function joinChannel (images, options) {
124 if (Array.isArray(images)) {
125 images.forEach(function (image) {
126 this.options.joinChannelIn.push(this._createInputDescriptor(image, options));
127 }, this);
128 } else {
129 this.options.joinChannelIn.push(this._createInputDescriptor(images, options));
130 }
131 return this;
132}
133
134/**
135 * Perform a bitwise boolean operation on all input image channels (bands) to produce a single channel output image.
136 *
137 * @example
138 * sharp('3-channel-rgb-input.png')
139 * .bandbool(sharp.bool.and)
140 * .toFile('1-channel-output.png', function (err, info) {
141 * // The output will be a single channel image where each pixel `P = R & G & B`.
142 * // If `I(1,1) = [247, 170, 14] = [0b11110111, 0b10101010, 0b00001111]`
143 * // then `O(1,1) = 0b11110111 & 0b10101010 & 0b00001111 = 0b00000010 = 2`.
144 * });
145 *
146 * @param {string} boolOp - one of `and`, `or` or `eor` to perform that bitwise operation, like the C logic operators `&`, `|` and `^` respectively.
147 * @returns {Sharp}
148 * @throws {Error} Invalid parameters
149 */
150function bandbool (boolOp) {
151 if (is.string(boolOp) && is.inArray(boolOp, ['and', 'or', 'eor'])) {
152 this.options.bandBoolOp = boolOp;
153 } else {
154 throw is.invalidParameterError('boolOp', 'one of: and, or, eor', boolOp);
155 }
156 return this;
157}
158
159/**
160 * Decorate the Sharp prototype with channel-related functions.
161 * @private
162 */
163module.exports = function (Sharp) {
164 Object.assign(Sharp.prototype, {
165 // Public instance functions
166 removeAlpha,
167 ensureAlpha,
168 extractChannel,
169 joinChannel,
170 bandbool
171 });
172 // Class attributes
173 Sharp.bool = bool;
174};