sharp 0.20.8 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/binding.gyp +5 -0
- package/docs/api-colour.md +1 -19
- package/docs/api-input.md +5 -2
- package/docs/api-operation.md +40 -115
- package/docs/api-resize.md +159 -109
- package/docs/api-utility.md +4 -7
- package/docs/changelog.md +41 -0
- package/docs/index.md +5 -4
- package/docs/install.md +18 -38
- package/docs/performance.md +14 -21
- package/install/libvips.js +21 -20
- package/lib/colour.js +34 -15
- package/lib/constructor.js +15 -39
- package/lib/input.js +5 -2
- package/lib/libvips.js +7 -1
- package/lib/operation.js +27 -118
- package/lib/platform.js +4 -1
- package/lib/resize.js +308 -104
- package/lib/utility.js +5 -8
- package/package.json +12 -11
- package/src/common.cc +45 -8
- package/src/common.h +9 -7
- package/src/libvips/cplusplus/VImage.cpp +95 -95
- package/src/libvips/cplusplus/vips-operators.cpp +268 -185
- package/src/metadata.cc +15 -0
- package/src/metadata.h +3 -0
- package/src/operations.cc +15 -48
- package/src/operations.h +1 -1
- package/src/pipeline.cc +39 -80
- package/src/pipeline.h +19 -13
- package/src/utilities.cc +1 -1
package/src/metadata.cc
CHANGED
|
@@ -62,6 +62,12 @@ class MetadataWorker : public Nan::AsyncWorker {
|
|
|
62
62
|
if (sharp::HasDensity(image)) {
|
|
63
63
|
baton->density = sharp::GetDensity(image);
|
|
64
64
|
}
|
|
65
|
+
if (image.get_typeof("jpeg-chroma-subsample") == VIPS_TYPE_REF_STRING) {
|
|
66
|
+
baton->chromaSubsampling = image.get_string("jpeg-chroma-subsample");
|
|
67
|
+
}
|
|
68
|
+
if (image.get_typeof("interlaced") == G_TYPE_INT) {
|
|
69
|
+
baton->isProgressive = image.get_int("interlaced") == 1;
|
|
70
|
+
}
|
|
65
71
|
baton->hasProfile = sharp::HasProfile(image);
|
|
66
72
|
// Derived attributes
|
|
67
73
|
baton->hasAlpha = sharp::HasAlpha(image);
|
|
@@ -117,6 +123,9 @@ class MetadataWorker : public Nan::AsyncWorker {
|
|
|
117
123
|
// Metadata Object
|
|
118
124
|
v8::Local<v8::Object> info = New<v8::Object>();
|
|
119
125
|
Set(info, New("format").ToLocalChecked(), New<v8::String>(baton->format).ToLocalChecked());
|
|
126
|
+
if (baton->input->bufferLength > 0) {
|
|
127
|
+
Set(info, New("size").ToLocalChecked(), New<v8::Uint32>(static_cast<uint32_t>(baton->input->bufferLength)));
|
|
128
|
+
}
|
|
120
129
|
Set(info, New("width").ToLocalChecked(), New<v8::Uint32>(baton->width));
|
|
121
130
|
Set(info, New("height").ToLocalChecked(), New<v8::Uint32>(baton->height));
|
|
122
131
|
Set(info, New("space").ToLocalChecked(), New<v8::String>(baton->space).ToLocalChecked());
|
|
@@ -125,6 +134,12 @@ class MetadataWorker : public Nan::AsyncWorker {
|
|
|
125
134
|
if (baton->density > 0) {
|
|
126
135
|
Set(info, New("density").ToLocalChecked(), New<v8::Uint32>(baton->density));
|
|
127
136
|
}
|
|
137
|
+
if (!baton->chromaSubsampling.empty()) {
|
|
138
|
+
Set(info,
|
|
139
|
+
New("chromaSubsampling").ToLocalChecked(),
|
|
140
|
+
New<v8::String>(baton->chromaSubsampling).ToLocalChecked());
|
|
141
|
+
}
|
|
142
|
+
Set(info, New("isProgressive").ToLocalChecked(), New<v8::Boolean>(baton->isProgressive));
|
|
128
143
|
Set(info, New("hasProfile").ToLocalChecked(), New<v8::Boolean>(baton->hasProfile));
|
|
129
144
|
Set(info, New("hasAlpha").ToLocalChecked(), New<v8::Boolean>(baton->hasAlpha));
|
|
130
145
|
if (baton->orientation > 0) {
|
package/src/metadata.h
CHANGED
|
@@ -31,6 +31,8 @@ struct MetadataBaton {
|
|
|
31
31
|
int channels;
|
|
32
32
|
std::string depth;
|
|
33
33
|
int density;
|
|
34
|
+
std::string chromaSubsampling;
|
|
35
|
+
bool isProgressive;
|
|
34
36
|
bool hasProfile;
|
|
35
37
|
bool hasAlpha;
|
|
36
38
|
int orientation;
|
|
@@ -50,6 +52,7 @@ struct MetadataBaton {
|
|
|
50
52
|
height(0),
|
|
51
53
|
channels(0),
|
|
52
54
|
density(0),
|
|
55
|
+
isProgressive(false),
|
|
53
56
|
hasProfile(false),
|
|
54
57
|
hasAlpha(false),
|
|
55
58
|
orientation(0),
|
package/src/operations.cc
CHANGED
|
@@ -78,7 +78,7 @@ namespace sharp {
|
|
|
78
78
|
//
|
|
79
79
|
// References:
|
|
80
80
|
// - http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
|
|
81
|
-
// - https://github.com/
|
|
81
|
+
// - https://github.com/libvips/ruby-vips/issues/28#issuecomment-9014826
|
|
82
82
|
//
|
|
83
83
|
// out_a = src_a + dst_a * (1 - src_a)
|
|
84
84
|
// ^^^^^^^^^^^
|
|
@@ -324,55 +324,22 @@ namespace sharp {
|
|
|
324
324
|
return image.boolean(imageR, boolean);
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
// we need to smooth the image, subtract the background from every pixel, take
|
|
343
|
-
// the absolute value of the difference, then threshold
|
|
344
|
-
VImage mask = (image.median(3) - background).abs() > (max * tolerance / 100);
|
|
345
|
-
|
|
346
|
-
// sum mask rows and columns, then search for the first non-zero sum in each
|
|
347
|
-
// direction
|
|
348
|
-
VImage rows;
|
|
349
|
-
VImage columns = mask.project(&rows);
|
|
350
|
-
|
|
351
|
-
VImage profileLeftV;
|
|
352
|
-
VImage profileLeftH = columns.profile(&profileLeftV);
|
|
353
|
-
|
|
354
|
-
VImage profileRightV;
|
|
355
|
-
VImage profileRightH = columns.fliphor().profile(&profileRightV);
|
|
356
|
-
|
|
357
|
-
VImage profileTopV;
|
|
358
|
-
VImage profileTopH = rows.profile(&profileTopV);
|
|
359
|
-
|
|
360
|
-
VImage profileBottomV;
|
|
361
|
-
VImage profileBottomH = rows.flipver().profile(&profileBottomV);
|
|
362
|
-
|
|
363
|
-
int left = static_cast<int>(floor(profileLeftV.min()));
|
|
364
|
-
int right = columns.width() - static_cast<int>(floor(profileRightV.min()));
|
|
365
|
-
int top = static_cast<int>(floor(profileTopH.min()));
|
|
366
|
-
int bottom = rows.height() - static_cast<int>(floor(profileBottomH.min()));
|
|
367
|
-
|
|
368
|
-
int width = right - left;
|
|
369
|
-
int height = bottom - top;
|
|
370
|
-
|
|
371
|
-
if (width <= 0 || height <= 0) {
|
|
327
|
+
/*
|
|
328
|
+
Trim an image
|
|
329
|
+
*/
|
|
330
|
+
VImage Trim(VImage image, double const threshold) {
|
|
331
|
+
// Top-left pixel provides the background colour
|
|
332
|
+
VImage background = image.extract_area(0, 0, 1, 1);
|
|
333
|
+
if (HasAlpha(background)) {
|
|
334
|
+
background = background.flatten();
|
|
335
|
+
}
|
|
336
|
+
int top, width, height;
|
|
337
|
+
int const left = image.find_trim(&top, &width, &height, VImage::option()
|
|
338
|
+
->set("background", background(0, 0))
|
|
339
|
+
->set("threshold", threshold));
|
|
340
|
+
if (width == 0 || height == 0) {
|
|
372
341
|
throw VError("Unexpected error while trimming. Try to lower the tolerance");
|
|
373
342
|
}
|
|
374
|
-
|
|
375
|
-
// and now crop the original image
|
|
376
343
|
return image.extract_area(left, top, width, height);
|
|
377
344
|
}
|
|
378
345
|
|
package/src/operations.h
CHANGED
package/src/pipeline.cc
CHANGED
|
@@ -100,8 +100,10 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// Trim
|
|
103
|
-
if (baton->
|
|
104
|
-
image = sharp::Trim(image, baton->
|
|
103
|
+
if (baton->trimThreshold > 0.0) {
|
|
104
|
+
image = sharp::Trim(image, baton->trimThreshold);
|
|
105
|
+
baton->trimOffsetLeft = image.xoffset();
|
|
106
|
+
baton->trimOffsetTop = image.yoffset();
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
// Pre extraction
|
|
@@ -233,7 +235,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
233
235
|
if (
|
|
234
236
|
xshrink == yshrink && xshrink >= 2 * shrink_on_load_factor &&
|
|
235
237
|
(inputImageType == ImageType::JPEG || inputImageType == ImageType::WEBP) &&
|
|
236
|
-
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->
|
|
238
|
+
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0
|
|
237
239
|
) {
|
|
238
240
|
if (xshrink >= 8 * shrink_on_load_factor) {
|
|
239
241
|
xfactor = xfactor / 8;
|
|
@@ -318,9 +320,9 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
318
320
|
double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
|
319
321
|
// Background colour
|
|
320
322
|
std::vector<double> background {
|
|
321
|
-
baton->
|
|
322
|
-
baton->
|
|
323
|
-
baton->
|
|
323
|
+
baton->flattenBackground[0] * multiplier,
|
|
324
|
+
baton->flattenBackground[1] * multiplier,
|
|
325
|
+
baton->flattenBackground[2] * multiplier
|
|
324
326
|
};
|
|
325
327
|
image = image.flatten(VImage::option()
|
|
326
328
|
->set("background", background));
|
|
@@ -421,35 +423,8 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
421
423
|
// Crop/embed
|
|
422
424
|
if (image.width() != baton->width || image.height() != baton->height) {
|
|
423
425
|
if (baton->canvas == Canvas::EMBED) {
|
|
424
|
-
// Scale up 8-bit values to match 16-bit input image
|
|
425
|
-
double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
|
426
|
-
// Create background colour
|
|
427
426
|
std::vector<double> background;
|
|
428
|
-
|
|
429
|
-
background = {
|
|
430
|
-
multiplier * baton->background[0],
|
|
431
|
-
multiplier * baton->background[1],
|
|
432
|
-
multiplier * baton->background[2]
|
|
433
|
-
};
|
|
434
|
-
} else {
|
|
435
|
-
// Convert sRGB to greyscale
|
|
436
|
-
background = { multiplier * (
|
|
437
|
-
0.2126 * baton->background[0] +
|
|
438
|
-
0.7152 * baton->background[1] +
|
|
439
|
-
0.0722 * baton->background[2])
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
// Add alpha channel to background colour
|
|
443
|
-
if (baton->background[3] < 255.0 || HasAlpha(image)) {
|
|
444
|
-
background.push_back(baton->background[3] * multiplier);
|
|
445
|
-
}
|
|
446
|
-
// Ensure background colour uses correct colourspace
|
|
447
|
-
background = sharp::GetRgbaAsColourspace(background, image.interpretation());
|
|
448
|
-
// Add non-transparent alpha channel, if required
|
|
449
|
-
if (baton->background[3] < 255.0 && !HasAlpha(image)) {
|
|
450
|
-
image = image.bandjoin(
|
|
451
|
-
VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier));
|
|
452
|
-
}
|
|
427
|
+
std::tie(image, background) = sharp::ApplyAlpha(image, baton->resizeBackground);
|
|
453
428
|
|
|
454
429
|
// Embed
|
|
455
430
|
|
|
@@ -463,7 +438,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
463
438
|
int width = std::max(image.width(), baton->width);
|
|
464
439
|
int height = std::max(image.height(), baton->height);
|
|
465
440
|
std::tie(left, top) = sharp::CalculateEmbedPosition(
|
|
466
|
-
image.width(), image.height(), baton->width, baton->height, baton->
|
|
441
|
+
image.width(), image.height(), baton->width, baton->height, baton->position);
|
|
467
442
|
|
|
468
443
|
image = image.embed(left, top, width, height, VImage::option()
|
|
469
444
|
->set("extend", VIPS_EXTEND_BACKGROUND)
|
|
@@ -474,12 +449,12 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
474
449
|
(image.width() > baton->width || image.height() > baton->height)
|
|
475
450
|
) {
|
|
476
451
|
// Crop/max/min
|
|
477
|
-
if (baton->
|
|
452
|
+
if (baton->position < 9) {
|
|
478
453
|
// Gravity-based crop
|
|
479
454
|
int left;
|
|
480
455
|
int top;
|
|
481
456
|
std::tie(left, top) = sharp::CalculateCrop(
|
|
482
|
-
image.width(), image.height(), baton->width, baton->height, baton->
|
|
457
|
+
image.width(), image.height(), baton->width, baton->height, baton->position);
|
|
483
458
|
int width = std::min(image.width(), baton->width);
|
|
484
459
|
int height = std::min(image.height(), baton->height);
|
|
485
460
|
image = image.extract_area(left, top, width, height);
|
|
@@ -495,7 +470,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
495
470
|
->set("access", baton->accessMethod)
|
|
496
471
|
->set("threaded", TRUE));
|
|
497
472
|
image = image.smartcrop(baton->width, baton->height, VImage::option()
|
|
498
|
-
->set("interesting", baton->
|
|
473
|
+
->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION));
|
|
499
474
|
baton->hasCropOffset = true;
|
|
500
475
|
baton->cropOffsetLeft = static_cast<int>(image.xoffset());
|
|
501
476
|
baton->cropOffsetTop = static_cast<int>(image.yoffset());
|
|
@@ -503,6 +478,13 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
503
478
|
}
|
|
504
479
|
}
|
|
505
480
|
|
|
481
|
+
// Rotate by degree
|
|
482
|
+
if (baton->rotationAngle != 0.0) {
|
|
483
|
+
std::vector<double> background;
|
|
484
|
+
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground);
|
|
485
|
+
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
|
|
486
|
+
}
|
|
487
|
+
|
|
506
488
|
// Post extraction
|
|
507
489
|
if (baton->topOffsetPost != -1) {
|
|
508
490
|
image = image.extract_area(
|
|
@@ -511,35 +493,9 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
511
493
|
|
|
512
494
|
// Extend edges
|
|
513
495
|
if (baton->extendTop > 0 || baton->extendBottom > 0 || baton->extendLeft > 0 || baton->extendRight > 0) {
|
|
514
|
-
// Scale up 8-bit values to match 16-bit input image
|
|
515
|
-
double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
|
516
|
-
// Create background colour
|
|
517
496
|
std::vector<double> background;
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
multiplier * baton->background[0],
|
|
521
|
-
multiplier * baton->background[1],
|
|
522
|
-
multiplier * baton->background[2]
|
|
523
|
-
};
|
|
524
|
-
} else {
|
|
525
|
-
// Convert sRGB to greyscale
|
|
526
|
-
background = { multiplier * (
|
|
527
|
-
0.2126 * baton->background[0] +
|
|
528
|
-
0.7152 * baton->background[1] +
|
|
529
|
-
0.0722 * baton->background[2])
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
// Add alpha channel to background colour
|
|
533
|
-
if (baton->background[3] < 255.0 || HasAlpha(image)) {
|
|
534
|
-
background.push_back(baton->background[3] * multiplier);
|
|
535
|
-
}
|
|
536
|
-
// Ensure background colour uses correct colourspace
|
|
537
|
-
background = sharp::GetRgbaAsColourspace(background, image.interpretation());
|
|
538
|
-
// Add non-transparent alpha channel, if required
|
|
539
|
-
if (baton->background[3] < 255.0 && !HasAlpha(image)) {
|
|
540
|
-
image = image.bandjoin(
|
|
541
|
-
VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier));
|
|
542
|
-
}
|
|
497
|
+
std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground);
|
|
498
|
+
|
|
543
499
|
// Embed
|
|
544
500
|
baton->width = image.width() + baton->extendLeft + baton->extendRight;
|
|
545
501
|
baton->height = image.height() + baton->extendTop + baton->extendBottom;
|
|
@@ -894,10 +850,6 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
894
850
|
if (baton->tiffCompression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) {
|
|
895
851
|
sharp::AssertImageTypeDimensions(image, ImageType::JPEG);
|
|
896
852
|
}
|
|
897
|
-
// Cast pixel values to float, if required
|
|
898
|
-
if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {
|
|
899
|
-
image = image.cast(VIPS_FORMAT_FLOAT);
|
|
900
|
-
}
|
|
901
853
|
image.tiffsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
902
854
|
->set("strip", !baton->withMetadata)
|
|
903
855
|
->set("Q", baton->tiffQuality)
|
|
@@ -1016,6 +968,12 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|
|
1016
968
|
Set(info, New("cropOffsetTop").ToLocalChecked(),
|
|
1017
969
|
New<v8::Int32>(static_cast<int32_t>(baton->cropOffsetTop)));
|
|
1018
970
|
}
|
|
971
|
+
if (baton->trimThreshold > 0.0) {
|
|
972
|
+
Set(info, New("trimOffsetLeft").ToLocalChecked(),
|
|
973
|
+
New<v8::Int32>(static_cast<int32_t>(baton->trimOffsetLeft)));
|
|
974
|
+
Set(info, New("trimOffsetTop").ToLocalChecked(),
|
|
975
|
+
New<v8::Int32>(static_cast<int32_t>(baton->trimOffsetTop)));
|
|
976
|
+
}
|
|
1019
977
|
|
|
1020
978
|
if (baton->bufferOutLength > 0) {
|
|
1021
979
|
// Pass ownership of output data to Buffer instance
|
|
@@ -1147,6 +1105,7 @@ NAN_METHOD(pipeline) {
|
|
|
1147
1105
|
using sharp::AttrTo;
|
|
1148
1106
|
using sharp::AttrAs;
|
|
1149
1107
|
using sharp::AttrAsStr;
|
|
1108
|
+
using sharp::AttrAsRgba;
|
|
1150
1109
|
using sharp::CreateInputDescriptor;
|
|
1151
1110
|
|
|
1152
1111
|
// Input Buffers must not undergo GC compaction during processing
|
|
@@ -1190,11 +1149,6 @@ NAN_METHOD(pipeline) {
|
|
|
1190
1149
|
} else if (canvas == "ignore_aspect") {
|
|
1191
1150
|
baton->canvas = Canvas::IGNORE_ASPECT;
|
|
1192
1151
|
}
|
|
1193
|
-
// Background colour
|
|
1194
|
-
v8::Local<v8::Object> background = AttrAs<v8::Object>(options, "background");
|
|
1195
|
-
for (unsigned int i = 0; i < 4; i++) {
|
|
1196
|
-
baton->background[i] = AttrTo<double>(background, i);
|
|
1197
|
-
}
|
|
1198
1152
|
// Tint chroma
|
|
1199
1153
|
baton->tintA = AttrTo<double>(options, "tintA");
|
|
1200
1154
|
baton->tintB = AttrTo<double>(options, "tintB");
|
|
@@ -1209,8 +1163,8 @@ NAN_METHOD(pipeline) {
|
|
|
1209
1163
|
}
|
|
1210
1164
|
// Resize options
|
|
1211
1165
|
baton->withoutEnlargement = AttrTo<bool>(options, "withoutEnlargement");
|
|
1212
|
-
baton->
|
|
1213
|
-
baton->
|
|
1166
|
+
baton->position = AttrTo<int32_t>(options, "position");
|
|
1167
|
+
baton->resizeBackground = AttrAsRgba(options, "resizeBackground");
|
|
1214
1168
|
baton->kernel = AttrAsStr(options, "kernel");
|
|
1215
1169
|
baton->fastShrinkOnLoad = AttrTo<bool>(options, "fastShrinkOnLoad");
|
|
1216
1170
|
// Join Channel Options
|
|
@@ -1228,6 +1182,7 @@ NAN_METHOD(pipeline) {
|
|
|
1228
1182
|
}
|
|
1229
1183
|
// Operators
|
|
1230
1184
|
baton->flatten = AttrTo<bool>(options, "flatten");
|
|
1185
|
+
baton->flattenBackground = AttrAsRgba(options, "flattenBackground");
|
|
1231
1186
|
baton->negate = AttrTo<bool>(options, "negate");
|
|
1232
1187
|
baton->blurSigma = AttrTo<double>(options, "blurSigma");
|
|
1233
1188
|
baton->medianSize = AttrTo<uint32_t>(options, "medianSize");
|
|
@@ -1236,7 +1191,7 @@ NAN_METHOD(pipeline) {
|
|
|
1236
1191
|
baton->sharpenJagged = AttrTo<double>(options, "sharpenJagged");
|
|
1237
1192
|
baton->threshold = AttrTo<int32_t>(options, "threshold");
|
|
1238
1193
|
baton->thresholdGrayscale = AttrTo<bool>(options, "thresholdGrayscale");
|
|
1239
|
-
baton->
|
|
1194
|
+
baton->trimThreshold = AttrTo<double>(options, "trimThreshold");
|
|
1240
1195
|
baton->gamma = AttrTo<double>(options, "gamma");
|
|
1241
1196
|
baton->linearA = AttrTo<double>(options, "linearA");
|
|
1242
1197
|
baton->linearB = AttrTo<double>(options, "linearB");
|
|
@@ -1244,6 +1199,8 @@ NAN_METHOD(pipeline) {
|
|
|
1244
1199
|
baton->normalise = AttrTo<bool>(options, "normalise");
|
|
1245
1200
|
baton->useExifOrientation = AttrTo<bool>(options, "useExifOrientation");
|
|
1246
1201
|
baton->angle = AttrTo<int32_t>(options, "angle");
|
|
1202
|
+
baton->rotationAngle = AttrTo<double>(options, "rotationAngle");
|
|
1203
|
+
baton->rotationBackground = AttrAsRgba(options, "rotationBackground");
|
|
1247
1204
|
baton->rotateBeforePreExtract = AttrTo<bool>(options, "rotateBeforePreExtract");
|
|
1248
1205
|
baton->flip = AttrTo<bool>(options, "flip");
|
|
1249
1206
|
baton->flop = AttrTo<bool>(options, "flop");
|
|
@@ -1251,7 +1208,9 @@ NAN_METHOD(pipeline) {
|
|
|
1251
1208
|
baton->extendBottom = AttrTo<int32_t>(options, "extendBottom");
|
|
1252
1209
|
baton->extendLeft = AttrTo<int32_t>(options, "extendLeft");
|
|
1253
1210
|
baton->extendRight = AttrTo<int32_t>(options, "extendRight");
|
|
1211
|
+
baton->extendBackground = AttrAsRgba(options, "extendBackground");
|
|
1254
1212
|
baton->extractChannel = AttrTo<int32_t>(options, "extractChannel");
|
|
1213
|
+
|
|
1255
1214
|
baton->removeAlpha = AttrTo<bool>(options, "removeAlpha");
|
|
1256
1215
|
if (HasAttr(options, "boolean")) {
|
|
1257
1216
|
baton->boolean = CreateInputDescriptor(AttrAs<v8::Object>(options, "boolean"), buffersToPersist);
|
|
@@ -1342,8 +1301,8 @@ NAN_METHOD(pipeline) {
|
|
|
1342
1301
|
}
|
|
1343
1302
|
// Force random access for certain operations
|
|
1344
1303
|
if (baton->accessMethod == VIPS_ACCESS_SEQUENTIAL && (
|
|
1345
|
-
baton->
|
|
1346
|
-
baton->
|
|
1304
|
+
baton->trimThreshold > 0.0 || baton->normalise ||
|
|
1305
|
+
baton->position == 16 || baton->position == 17)) {
|
|
1347
1306
|
baton->accessMethod = VIPS_ACCESS_RANDOM;
|
|
1348
1307
|
}
|
|
1349
1308
|
|
package/src/pipeline.h
CHANGED
|
@@ -61,18 +61,18 @@ struct PipelineBaton {
|
|
|
61
61
|
int height;
|
|
62
62
|
int channels;
|
|
63
63
|
Canvas canvas;
|
|
64
|
-
int
|
|
65
|
-
|
|
64
|
+
int position;
|
|
65
|
+
std::vector<double> resizeBackground;
|
|
66
66
|
bool hasCropOffset;
|
|
67
67
|
int cropOffsetLeft;
|
|
68
68
|
int cropOffsetTop;
|
|
69
69
|
bool premultiplied;
|
|
70
70
|
std::string kernel;
|
|
71
71
|
bool fastShrinkOnLoad;
|
|
72
|
-
double background[4];
|
|
73
72
|
double tintA;
|
|
74
73
|
double tintB;
|
|
75
74
|
bool flatten;
|
|
75
|
+
std::vector<double> flattenBackground;
|
|
76
76
|
bool negate;
|
|
77
77
|
double blurSigma;
|
|
78
78
|
int medianSize;
|
|
@@ -81,7 +81,9 @@ struct PipelineBaton {
|
|
|
81
81
|
double sharpenJagged;
|
|
82
82
|
int threshold;
|
|
83
83
|
bool thresholdGrayscale;
|
|
84
|
-
|
|
84
|
+
double trimThreshold;
|
|
85
|
+
int trimOffsetLeft;
|
|
86
|
+
int trimOffsetTop;
|
|
85
87
|
double linearA;
|
|
86
88
|
double linearB;
|
|
87
89
|
double gamma;
|
|
@@ -89,6 +91,8 @@ struct PipelineBaton {
|
|
|
89
91
|
bool normalise;
|
|
90
92
|
bool useExifOrientation;
|
|
91
93
|
int angle;
|
|
94
|
+
double rotationAngle;
|
|
95
|
+
std::vector<double> rotationBackground;
|
|
92
96
|
bool rotateBeforePreExtract;
|
|
93
97
|
bool flip;
|
|
94
98
|
bool flop;
|
|
@@ -96,6 +100,7 @@ struct PipelineBaton {
|
|
|
96
100
|
int extendBottom;
|
|
97
101
|
int extendLeft;
|
|
98
102
|
int extendRight;
|
|
103
|
+
std::vector<double> extendBackground;
|
|
99
104
|
bool withoutEnlargement;
|
|
100
105
|
VipsAccess accessMethod;
|
|
101
106
|
int jpegQuality;
|
|
@@ -155,8 +160,8 @@ struct PipelineBaton {
|
|
|
155
160
|
topOffsetPost(-1),
|
|
156
161
|
channels(0),
|
|
157
162
|
canvas(Canvas::CROP),
|
|
158
|
-
|
|
159
|
-
|
|
163
|
+
position(0),
|
|
164
|
+
resizeBackground{ 0.0, 0.0, 0.0, 255.0 },
|
|
160
165
|
hasCropOffset(false),
|
|
161
166
|
cropOffsetLeft(0),
|
|
162
167
|
cropOffsetTop(0),
|
|
@@ -164,6 +169,7 @@ struct PipelineBaton {
|
|
|
164
169
|
tintA(128.0),
|
|
165
170
|
tintB(128.0),
|
|
166
171
|
flatten(false),
|
|
172
|
+
flattenBackground{ 0.0, 0.0, 0.0 },
|
|
167
173
|
negate(false),
|
|
168
174
|
blurSigma(0.0),
|
|
169
175
|
medianSize(0),
|
|
@@ -172,7 +178,9 @@ struct PipelineBaton {
|
|
|
172
178
|
sharpenJagged(2.0),
|
|
173
179
|
threshold(0),
|
|
174
180
|
thresholdGrayscale(true),
|
|
175
|
-
|
|
181
|
+
trimThreshold(0.0),
|
|
182
|
+
trimOffsetLeft(0),
|
|
183
|
+
trimOffsetTop(0),
|
|
176
184
|
linearA(1.0),
|
|
177
185
|
linearB(0.0),
|
|
178
186
|
gamma(0.0),
|
|
@@ -180,12 +188,15 @@ struct PipelineBaton {
|
|
|
180
188
|
normalise(false),
|
|
181
189
|
useExifOrientation(false),
|
|
182
190
|
angle(0),
|
|
191
|
+
rotationAngle(0.0),
|
|
192
|
+
rotationBackground{ 0.0, 0.0, 0.0, 255.0 },
|
|
183
193
|
flip(false),
|
|
184
194
|
flop(false),
|
|
185
195
|
extendTop(0),
|
|
186
196
|
extendBottom(0),
|
|
187
197
|
extendLeft(0),
|
|
188
198
|
extendRight(0),
|
|
199
|
+
extendBackground{ 0.0, 0.0, 0.0, 255.0 },
|
|
189
200
|
withoutEnlargement(false),
|
|
190
201
|
jpegQuality(80),
|
|
191
202
|
jpegProgressive(false),
|
|
@@ -222,12 +233,7 @@ struct PipelineBaton {
|
|
|
222
233
|
tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
|
|
223
234
|
tileLayout(VIPS_FOREIGN_DZ_LAYOUT_DZ),
|
|
224
235
|
tileAngle(0),
|
|
225
|
-
tileDepth(VIPS_FOREIGN_DZ_DEPTH_LAST){
|
|
226
|
-
background[0] = 0.0;
|
|
227
|
-
background[1] = 0.0;
|
|
228
|
-
background[2] = 0.0;
|
|
229
|
-
background[3] = 255.0;
|
|
230
|
-
}
|
|
236
|
+
tileDepth(VIPS_FOREIGN_DZ_DEPTH_LAST) {}
|
|
231
237
|
};
|
|
232
238
|
|
|
233
239
|
#endif // SRC_PIPELINE_H_
|
package/src/utilities.cc
CHANGED