@revizly/sharp 0.33.2-revizly13

Sign up to get free protection for your applications and to get access to all the features.
package/src/pipeline.h ADDED
@@ -0,0 +1,385 @@
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ #ifndef SRC_PIPELINE_H_
5
+ #define SRC_PIPELINE_H_
6
+
7
+ #include <memory>
8
+ #include <string>
9
+ #include <vector>
10
+ #include <unordered_map>
11
+
12
+ #include <napi.h>
13
+ #include <vips/vips8>
14
+
15
+ #include "./common.h"
16
+
17
+ Napi::Value pipeline(const Napi::CallbackInfo& info);
18
+
19
+ struct Composite {
20
+ sharp::InputDescriptor *input;
21
+ VipsBlendMode mode;
22
+ int gravity;
23
+ int left;
24
+ int top;
25
+ bool hasOffset;
26
+ bool tile;
27
+ bool premultiplied;
28
+
29
+ Composite():
30
+ input(nullptr),
31
+ mode(VIPS_BLEND_MODE_OVER),
32
+ gravity(0),
33
+ left(0),
34
+ top(0),
35
+ hasOffset(false),
36
+ tile(false),
37
+ premultiplied(false) {}
38
+ };
39
+
40
+ struct PipelineBaton {
41
+ sharp::InputDescriptor *input;
42
+ std::string formatOut;
43
+ std::string fileOut;
44
+ void *bufferOut;
45
+ size_t bufferOutLength;
46
+ std::vector<Composite *> composite;
47
+ std::vector<sharp::InputDescriptor *> joinChannelIn;
48
+ int topOffsetPre;
49
+ int leftOffsetPre;
50
+ int widthPre;
51
+ int heightPre;
52
+ int topOffsetPost;
53
+ int leftOffsetPost;
54
+ int widthPost;
55
+ int heightPost;
56
+ int width;
57
+ int height;
58
+ int channels;
59
+ VipsKernel kernel;
60
+ sharp::Canvas canvas;
61
+ int position;
62
+ std::vector<double> resizeBackground;
63
+ bool hasCropOffset;
64
+ int cropOffsetLeft;
65
+ int cropOffsetTop;
66
+ bool hasAttentionCenter;
67
+ int attentionX;
68
+ int attentionY;
69
+ bool premultiplied;
70
+ bool tileCentre;
71
+ bool fastShrinkOnLoad;
72
+ std::vector<double> tint;
73
+ bool flatten;
74
+ std::vector<double> flattenBackground;
75
+ bool unflatten;
76
+ bool negate;
77
+ bool negateAlpha;
78
+ double blurSigma;
79
+ double brightness;
80
+ double saturation;
81
+ int hue;
82
+ double lightness;
83
+ int medianSize;
84
+ double sharpenSigma;
85
+ double sharpenM1;
86
+ double sharpenM2;
87
+ double sharpenX1;
88
+ double sharpenY2;
89
+ double sharpenY3;
90
+ int threshold;
91
+ bool thresholdGrayscale;
92
+ std::vector<double> trimBackground;
93
+ double trimThreshold;
94
+ bool trimLineArt;
95
+ int trimOffsetLeft;
96
+ int trimOffsetTop;
97
+ std::vector<double> linearA;
98
+ std::vector<double> linearB;
99
+ double gamma;
100
+ double gammaOut;
101
+ bool greyscale;
102
+ bool normalise;
103
+ int normaliseLower;
104
+ int normaliseUpper;
105
+ int claheWidth;
106
+ int claheHeight;
107
+ int claheMaxSlope;
108
+ bool useExifOrientation;
109
+ int angle;
110
+ double rotationAngle;
111
+ std::vector<double> rotationBackground;
112
+ bool rotateBeforePreExtract;
113
+ bool flip;
114
+ bool flop;
115
+ int extendTop;
116
+ int extendBottom;
117
+ int extendLeft;
118
+ int extendRight;
119
+ std::vector<double> extendBackground;
120
+ VipsExtend extendWith;
121
+ bool withoutEnlargement;
122
+ bool withoutReduction;
123
+ std::vector<double> affineMatrix;
124
+ std::vector<double> affineBackground;
125
+ double affineIdx;
126
+ double affineIdy;
127
+ double affineOdx;
128
+ double affineOdy;
129
+ std::string affineInterpolator;
130
+ int jpegQuality;
131
+ bool jpegProgressive;
132
+ std::string jpegChromaSubsampling;
133
+ bool jpegTrellisQuantisation;
134
+ int jpegQuantisationTable;
135
+ bool jpegOvershootDeringing;
136
+ bool jpegOptimiseScans;
137
+ bool jpegOptimiseCoding;
138
+ bool pngProgressive;
139
+ int pngCompressionLevel;
140
+ bool pngAdaptiveFiltering;
141
+ bool pngPalette;
142
+ int pngQuality;
143
+ int pngEffort;
144
+ int pngBitdepth;
145
+ double pngDither;
146
+ int jp2Quality;
147
+ bool jp2Lossless;
148
+ int jp2TileHeight;
149
+ int jp2TileWidth;
150
+ std::string jp2ChromaSubsampling;
151
+ int webpQuality;
152
+ int webpAlphaQuality;
153
+ bool webpNearLossless;
154
+ bool webpLossless;
155
+ bool webpSmartSubsample;
156
+ VipsForeignWebpPreset webpPreset;
157
+ int webpEffort;
158
+ bool webpMinSize;
159
+ bool webpMixed;
160
+ int gifBitdepth;
161
+ int gifEffort;
162
+ double gifDither;
163
+ double gifInterFrameMaxError;
164
+ double gifInterPaletteMaxError;
165
+ bool gifReuse;
166
+ bool gifProgressive;
167
+ int tiffQuality;
168
+ VipsForeignTiffCompression tiffCompression;
169
+ VipsForeignTiffPredictor tiffPredictor;
170
+ bool tiffPyramid;
171
+ int tiffBitdepth;
172
+ bool tiffMiniswhite;
173
+ bool tiffTile;
174
+ int tiffTileHeight;
175
+ int tiffTileWidth;
176
+ double tiffXres;
177
+ double tiffYres;
178
+ VipsForeignTiffResunit tiffResolutionUnit;
179
+ int heifQuality;
180
+ VipsForeignHeifCompression heifCompression;
181
+ int heifEffort;
182
+ std::string heifChromaSubsampling;
183
+ bool heifLossless;
184
+ double jxlDistance;
185
+ int jxlDecodingTier;
186
+ int jxlEffort;
187
+ bool jxlLossless;
188
+ VipsBandFormat rawDepth;
189
+ std::string err;
190
+ int keepMetadata;
191
+ int withMetadataOrientation;
192
+ double withMetadataDensity;
193
+ std::string withIccProfile;
194
+ std::unordered_map<std::string, std::string> withExif;
195
+ bool withExifMerge;
196
+ int timeoutSeconds;
197
+ std::unique_ptr<double[]> convKernel;
198
+ int convKernelWidth;
199
+ int convKernelHeight;
200
+ double convKernelScale;
201
+ double convKernelOffset;
202
+ sharp::InputDescriptor *boolean;
203
+ VipsOperationBoolean booleanOp;
204
+ VipsOperationBoolean bandBoolOp;
205
+ int extractChannel;
206
+ bool removeAlpha;
207
+ double ensureAlpha;
208
+ VipsInterpretation colourspacePipeline;
209
+ VipsInterpretation colourspace;
210
+ std::vector<int> delay;
211
+ int loop;
212
+ int tileSize;
213
+ int tileOverlap;
214
+ VipsForeignDzContainer tileContainer;
215
+ VipsForeignDzLayout tileLayout;
216
+ std::string tileFormat;
217
+ int tileAngle;
218
+ std::vector<double> tileBackground;
219
+ int tileSkipBlanks;
220
+ VipsForeignDzDepth tileDepth;
221
+ std::string tileId;
222
+ std::string tileBasename;
223
+ std::unique_ptr<double[]> recombMatrix;
224
+
225
+ PipelineBaton():
226
+ input(nullptr),
227
+ bufferOutLength(0),
228
+ topOffsetPre(-1),
229
+ topOffsetPost(-1),
230
+ channels(0),
231
+ kernel(VIPS_KERNEL_LANCZOS3),
232
+ canvas(sharp::Canvas::CROP),
233
+ position(0),
234
+ resizeBackground{ 0.0, 0.0, 0.0, 255.0 },
235
+ hasCropOffset(false),
236
+ cropOffsetLeft(0),
237
+ cropOffsetTop(0),
238
+ hasAttentionCenter(false),
239
+ attentionX(0),
240
+ attentionY(0),
241
+ premultiplied(false),
242
+ tint{ -1.0, 0.0, 0.0, 0.0 },
243
+ flatten(false),
244
+ flattenBackground{ 0.0, 0.0, 0.0 },
245
+ unflatten(false),
246
+ negate(false),
247
+ negateAlpha(true),
248
+ blurSigma(0.0),
249
+ brightness(1.0),
250
+ saturation(1.0),
251
+ hue(0),
252
+ lightness(0),
253
+ medianSize(0),
254
+ sharpenSigma(0.0),
255
+ sharpenM1(1.0),
256
+ sharpenM2(2.0),
257
+ sharpenX1(2.0),
258
+ sharpenY2(10.0),
259
+ sharpenY3(20.0),
260
+ threshold(0),
261
+ thresholdGrayscale(true),
262
+ trimBackground{},
263
+ trimThreshold(-1.0),
264
+ trimLineArt(false),
265
+ trimOffsetLeft(0),
266
+ trimOffsetTop(0),
267
+ linearA{},
268
+ linearB{},
269
+ gamma(0.0),
270
+ greyscale(false),
271
+ normalise(false),
272
+ normaliseLower(1),
273
+ normaliseUpper(99),
274
+ claheWidth(0),
275
+ claheHeight(0),
276
+ claheMaxSlope(3),
277
+ useExifOrientation(false),
278
+ angle(0),
279
+ rotationAngle(0.0),
280
+ rotationBackground{ 0.0, 0.0, 0.0, 255.0 },
281
+ flip(false),
282
+ flop(false),
283
+ extendTop(0),
284
+ extendBottom(0),
285
+ extendLeft(0),
286
+ extendRight(0),
287
+ extendBackground{ 0.0, 0.0, 0.0, 255.0 },
288
+ extendWith(VIPS_EXTEND_BACKGROUND),
289
+ withoutEnlargement(false),
290
+ withoutReduction(false),
291
+ affineMatrix{ 1.0, 0.0, 0.0, 1.0 },
292
+ affineBackground{ 0.0, 0.0, 0.0, 255.0 },
293
+ affineIdx(0),
294
+ affineIdy(0),
295
+ affineOdx(0),
296
+ affineOdy(0),
297
+ affineInterpolator("bicubic"),
298
+ jpegQuality(80),
299
+ jpegProgressive(false),
300
+ jpegChromaSubsampling("4:2:0"),
301
+ jpegTrellisQuantisation(false),
302
+ jpegQuantisationTable(0),
303
+ jpegOvershootDeringing(false),
304
+ jpegOptimiseScans(false),
305
+ jpegOptimiseCoding(true),
306
+ pngProgressive(false),
307
+ pngCompressionLevel(6),
308
+ pngAdaptiveFiltering(false),
309
+ pngPalette(false),
310
+ pngQuality(100),
311
+ pngEffort(7),
312
+ pngBitdepth(8),
313
+ pngDither(1.0),
314
+ jp2Quality(80),
315
+ jp2Lossless(false),
316
+ jp2TileHeight(512),
317
+ jp2TileWidth(512),
318
+ jp2ChromaSubsampling("4:4:4"),
319
+ webpQuality(80),
320
+ webpAlphaQuality(100),
321
+ webpNearLossless(false),
322
+ webpLossless(false),
323
+ webpSmartSubsample(false),
324
+ webpPreset(VIPS_FOREIGN_WEBP_PRESET_DEFAULT),
325
+ webpEffort(4),
326
+ webpMinSize(false),
327
+ webpMixed(false),
328
+ gifBitdepth(8),
329
+ gifEffort(7),
330
+ gifDither(1.0),
331
+ gifInterFrameMaxError(0.0),
332
+ gifInterPaletteMaxError(3.0),
333
+ gifReuse(true),
334
+ gifProgressive(false),
335
+ tiffQuality(80),
336
+ tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
337
+ tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
338
+ tiffPyramid(false),
339
+ tiffBitdepth(8),
340
+ tiffMiniswhite(false),
341
+ tiffTile(false),
342
+ tiffTileHeight(256),
343
+ tiffTileWidth(256),
344
+ tiffXres(1.0),
345
+ tiffYres(1.0),
346
+ tiffResolutionUnit(VIPS_FOREIGN_TIFF_RESUNIT_INCH),
347
+ heifQuality(50),
348
+ heifCompression(VIPS_FOREIGN_HEIF_COMPRESSION_AV1),
349
+ heifEffort(4),
350
+ heifChromaSubsampling("4:4:4"),
351
+ heifLossless(false),
352
+ jxlDistance(1.0),
353
+ jxlDecodingTier(0),
354
+ jxlEffort(7),
355
+ jxlLossless(false),
356
+ rawDepth(VIPS_FORMAT_UCHAR),
357
+ keepMetadata(0),
358
+ withMetadataOrientation(-1),
359
+ withMetadataDensity(0.0),
360
+ withExifMerge(true),
361
+ timeoutSeconds(0),
362
+ convKernelWidth(0),
363
+ convKernelHeight(0),
364
+ convKernelScale(0.0),
365
+ convKernelOffset(0.0),
366
+ boolean(nullptr),
367
+ booleanOp(VIPS_OPERATION_BOOLEAN_LAST),
368
+ bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST),
369
+ extractChannel(-1),
370
+ removeAlpha(false),
371
+ ensureAlpha(-1.0),
372
+ colourspacePipeline(VIPS_INTERPRETATION_LAST),
373
+ colourspace(VIPS_INTERPRETATION_LAST),
374
+ loop(-1),
375
+ tileSize(256),
376
+ tileOverlap(0),
377
+ tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
378
+ tileLayout(VIPS_FOREIGN_DZ_LAYOUT_DZ),
379
+ tileAngle(0),
380
+ tileBackground{ 255.0, 255.0, 255.0, 255.0 },
381
+ tileSkipBlanks(-1),
382
+ tileDepth(VIPS_FOREIGN_DZ_DEPTH_LAST) {}
383
+ };
384
+
385
+ #endif // SRC_PIPELINE_H_
package/src/sharp.cc ADDED
@@ -0,0 +1,40 @@
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ #include <mutex> // NOLINT(build/c++11)
5
+
6
+ #include <napi.h>
7
+ #include <vips/vips8>
8
+
9
+ #include "common.h"
10
+ #include "metadata.h"
11
+ #include "pipeline.h"
12
+ #include "utilities.h"
13
+ #include "stats.h"
14
+
15
+ Napi::Object init(Napi::Env env, Napi::Object exports) {
16
+ static std::once_flag sharp_vips_init_once;
17
+ std::call_once(sharp_vips_init_once, []() {
18
+ vips_init("sharp");
19
+ });
20
+
21
+ g_log_set_handler("VIPS", static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING),
22
+ static_cast<GLogFunc>(sharp::VipsWarningCallback), nullptr);
23
+
24
+ // Methods available to JavaScript
25
+ exports.Set("metadata", Napi::Function::New(env, metadata));
26
+ exports.Set("pipeline", Napi::Function::New(env, pipeline));
27
+ exports.Set("cache", Napi::Function::New(env, cache));
28
+ exports.Set("concurrency", Napi::Function::New(env, concurrency));
29
+ exports.Set("counters", Napi::Function::New(env, counters));
30
+ exports.Set("simd", Napi::Function::New(env, simd));
31
+ exports.Set("libvipsVersion", Napi::Function::New(env, libvipsVersion));
32
+ exports.Set("format", Napi::Function::New(env, format));
33
+ exports.Set("block", Napi::Function::New(env, block));
34
+ exports.Set("_maxColourDistance", Napi::Function::New(env, _maxColourDistance));
35
+ exports.Set("_isUsingJemalloc", Napi::Function::New(env, _isUsingJemalloc));
36
+ exports.Set("stats", Napi::Function::New(env, stats));
37
+ return exports;
38
+ }
39
+
40
+ NODE_API_MODULE(sharp, init)
package/src/stats.cc ADDED
@@ -0,0 +1,183 @@
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ #include <numeric>
5
+ #include <vector>
6
+ #include <iostream>
7
+
8
+ #include <napi.h>
9
+ #include <vips/vips8>
10
+
11
+ #include "common.h"
12
+ #include "stats.h"
13
+
14
+ class StatsWorker : public Napi::AsyncWorker {
15
+ public:
16
+ StatsWorker(Napi::Function callback, StatsBaton *baton, Napi::Function debuglog) :
17
+ Napi::AsyncWorker(callback), baton(baton), debuglog(Napi::Persistent(debuglog)) {}
18
+ ~StatsWorker() {}
19
+
20
+ const int STAT_MIN_INDEX = 0;
21
+ const int STAT_MAX_INDEX = 1;
22
+ const int STAT_SUM_INDEX = 2;
23
+ const int STAT_SQ_SUM_INDEX = 3;
24
+ const int STAT_MEAN_INDEX = 4;
25
+ const int STAT_STDEV_INDEX = 5;
26
+ const int STAT_MINX_INDEX = 6;
27
+ const int STAT_MINY_INDEX = 7;
28
+ const int STAT_MAXX_INDEX = 8;
29
+ const int STAT_MAXY_INDEX = 9;
30
+
31
+ void Execute() {
32
+ // Decrement queued task counter
33
+ sharp::counterQueue--;
34
+
35
+ vips::VImage image;
36
+ sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
37
+ try {
38
+ std::tie(image, imageType) = OpenInput(baton->input);
39
+ } catch (vips::VError const &err) {
40
+ (baton->err).append(err.what());
41
+ }
42
+ if (imageType != sharp::ImageType::UNKNOWN) {
43
+ try {
44
+ vips::VImage stats = image.stats();
45
+ int const bands = image.bands();
46
+ for (int b = 1; b <= bands; b++) {
47
+ ChannelStats cStats(
48
+ static_cast<int>(stats.getpoint(STAT_MIN_INDEX, b).front()),
49
+ static_cast<int>(stats.getpoint(STAT_MAX_INDEX, b).front()),
50
+ stats.getpoint(STAT_SUM_INDEX, b).front(),
51
+ stats.getpoint(STAT_SQ_SUM_INDEX, b).front(),
52
+ stats.getpoint(STAT_MEAN_INDEX, b).front(),
53
+ stats.getpoint(STAT_STDEV_INDEX, b).front(),
54
+ static_cast<int>(stats.getpoint(STAT_MINX_INDEX, b).front()),
55
+ static_cast<int>(stats.getpoint(STAT_MINY_INDEX, b).front()),
56
+ static_cast<int>(stats.getpoint(STAT_MAXX_INDEX, b).front()),
57
+ static_cast<int>(stats.getpoint(STAT_MAXY_INDEX, b).front()));
58
+ baton->channelStats.push_back(cStats);
59
+ }
60
+ // Image is not opaque when alpha layer is present and contains a non-mamixa value
61
+ if (sharp::HasAlpha(image)) {
62
+ double const minAlpha = static_cast<double>(stats.getpoint(STAT_MIN_INDEX, bands).front());
63
+ if (minAlpha != sharp::MaximumImageAlpha(image.interpretation())) {
64
+ baton->isOpaque = false;
65
+ }
66
+ }
67
+ // Convert to greyscale
68
+ vips::VImage greyscale = image.colourspace(VIPS_INTERPRETATION_B_W)[0];
69
+ // Estimate entropy via histogram of greyscale value frequency
70
+ baton->entropy = std::abs(greyscale.hist_find().hist_entropy());
71
+ // Estimate sharpness via standard deviation of greyscale laplacian
72
+ if (image.width() > 1 || image.height() > 1) {
73
+ VImage laplacian = VImage::new_matrixv(3, 3,
74
+ 0.0, 1.0, 0.0,
75
+ 1.0, -4.0, 1.0,
76
+ 0.0, 1.0, 0.0);
77
+ laplacian.set("scale", 9.0);
78
+ baton->sharpness = greyscale.conv(laplacian).deviate();
79
+ }
80
+ // Most dominant sRGB colour via 4096-bin 3D histogram
81
+ vips::VImage hist = sharp::RemoveAlpha(image)
82
+ .colourspace(VIPS_INTERPRETATION_sRGB)
83
+ .hist_find_ndim(VImage::option()->set("bins", 16));
84
+ std::complex<double> maxpos = hist.maxpos();
85
+ int const dx = static_cast<int>(std::real(maxpos));
86
+ int const dy = static_cast<int>(std::imag(maxpos));
87
+ std::vector<double> pel = hist(dx, dy);
88
+ int const dz = std::distance(pel.begin(), std::find(pel.begin(), pel.end(), hist.max()));
89
+ baton->dominantRed = dx * 16 + 8;
90
+ baton->dominantGreen = dy * 16 + 8;
91
+ baton->dominantBlue = dz * 16 + 8;
92
+ } catch (vips::VError const &err) {
93
+ (baton->err).append(err.what());
94
+ }
95
+ }
96
+
97
+ // Clean up
98
+ vips_error_clear();
99
+ vips_thread_shutdown();
100
+ }
101
+
102
+ void OnOK() {
103
+ Napi::Env env = Env();
104
+ Napi::HandleScope scope(env);
105
+
106
+ // Handle warnings
107
+ std::string warning = sharp::VipsWarningPop();
108
+ while (!warning.empty()) {
109
+ debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
110
+ warning = sharp::VipsWarningPop();
111
+ }
112
+
113
+ if (baton->err.empty()) {
114
+ // Stats Object
115
+ Napi::Object info = Napi::Object::New(env);
116
+ Napi::Array channels = Napi::Array::New(env);
117
+
118
+ std::vector<ChannelStats>::iterator it;
119
+ int i = 0;
120
+ for (it = baton->channelStats.begin(); it < baton->channelStats.end(); it++, i++) {
121
+ Napi::Object channelStat = Napi::Object::New(env);
122
+ channelStat.Set("min", it->min);
123
+ channelStat.Set("max", it->max);
124
+ channelStat.Set("sum", it->sum);
125
+ channelStat.Set("squaresSum", it->squaresSum);
126
+ channelStat.Set("mean", it->mean);
127
+ channelStat.Set("stdev", it->stdev);
128
+ channelStat.Set("minX", it->minX);
129
+ channelStat.Set("minY", it->minY);
130
+ channelStat.Set("maxX", it->maxX);
131
+ channelStat.Set("maxY", it->maxY);
132
+ channels.Set(i, channelStat);
133
+ }
134
+
135
+ info.Set("channels", channels);
136
+ info.Set("isOpaque", baton->isOpaque);
137
+ info.Set("entropy", baton->entropy);
138
+ info.Set("sharpness", baton->sharpness);
139
+ Napi::Object dominant = Napi::Object::New(env);
140
+ dominant.Set("r", baton->dominantRed);
141
+ dominant.Set("g", baton->dominantGreen);
142
+ dominant.Set("b", baton->dominantBlue);
143
+ info.Set("dominant", dominant);
144
+ Callback().Call(Receiver().Value(), { env.Null(), info });
145
+ } else {
146
+ Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
147
+ }
148
+
149
+ delete baton->input;
150
+ delete baton;
151
+ }
152
+
153
+ private:
154
+ StatsBaton* baton;
155
+ Napi::FunctionReference debuglog;
156
+ };
157
+
158
+ /*
159
+ stats(options, callback)
160
+ */
161
+ Napi::Value stats(const Napi::CallbackInfo& info) {
162
+ // V8 objects are converted to non-V8 types held in the baton struct
163
+ StatsBaton *baton = new StatsBaton;
164
+ Napi::Object options = info[size_t(0)].As<Napi::Object>();
165
+
166
+ // Input
167
+ baton->input = sharp::CreateInputDescriptor(options.Get("input").As<Napi::Object>());
168
+ baton->input->access = VIPS_ACCESS_RANDOM;
169
+
170
+ // Function to notify of libvips warnings
171
+ Napi::Function debuglog = options.Get("debuglog").As<Napi::Function>();
172
+
173
+ // Join queue for worker thread
174
+ Napi::Function callback = info[size_t(1)].As<Napi::Function>();
175
+ StatsWorker *worker = new StatsWorker(callback, baton, debuglog);
176
+ worker->Receiver().Set("options", options);
177
+ worker->Queue();
178
+
179
+ // Increment queued task counter
180
+ sharp::counterQueue++;
181
+
182
+ return info.Env().Undefined();
183
+ }
package/src/stats.h ADDED
@@ -0,0 +1,59 @@
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ #ifndef SRC_STATS_H_
5
+ #define SRC_STATS_H_
6
+
7
+ #include <string>
8
+ #include <napi.h>
9
+
10
+ #include "./common.h"
11
+
12
+ struct ChannelStats {
13
+ // stats per channel
14
+ int min;
15
+ int max;
16
+ double sum;
17
+ double squaresSum;
18
+ double mean;
19
+ double stdev;
20
+ int minX;
21
+ int minY;
22
+ int maxX;
23
+ int maxY;
24
+
25
+ ChannelStats(int minVal, int maxVal, double sumVal, double squaresSumVal,
26
+ double meanVal, double stdevVal, int minXVal, int minYVal, int maxXVal, int maxYVal):
27
+ min(minVal), max(maxVal), sum(sumVal), squaresSum(squaresSumVal),
28
+ mean(meanVal), stdev(stdevVal), minX(minXVal), minY(minYVal), maxX(maxXVal), maxY(maxYVal) {}
29
+ };
30
+
31
+ struct StatsBaton {
32
+ // Input
33
+ sharp::InputDescriptor *input;
34
+
35
+ // Output
36
+ std::vector<ChannelStats> channelStats;
37
+ bool isOpaque;
38
+ double entropy;
39
+ double sharpness;
40
+ int dominantRed;
41
+ int dominantGreen;
42
+ int dominantBlue;
43
+
44
+ std::string err;
45
+
46
+ StatsBaton():
47
+ input(nullptr),
48
+ isOpaque(true),
49
+ entropy(0.0),
50
+ sharpness(0.0),
51
+ dominantRed(0),
52
+ dominantGreen(0),
53
+ dominantBlue(0)
54
+ {}
55
+ };
56
+
57
+ Napi::Value stats(const Napi::CallbackInfo& info);
58
+
59
+ #endif // SRC_STATS_H_