sharp 0.20.8 → 0.21.3

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/src/metadata.cc CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -62,6 +62,21 @@ 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
+ }
71
+ if (image.get_typeof("palette-bit-depth") == G_TYPE_INT) {
72
+ baton->paletteBitDepth = image.get_int("palette-bit-depth");
73
+ }
74
+ if (image.get_typeof(VIPS_META_N_PAGES) == G_TYPE_INT) {
75
+ baton->pages = image.get_int(VIPS_META_N_PAGES);
76
+ }
77
+ if (image.get_typeof(VIPS_META_PAGE_HEIGHT) == G_TYPE_INT) {
78
+ baton->pageHeight = image.get_int(VIPS_META_PAGE_HEIGHT);
79
+ }
65
80
  baton->hasProfile = sharp::HasProfile(image);
66
81
  // Derived attributes
67
82
  baton->hasAlpha = sharp::HasAlpha(image);
@@ -117,6 +132,9 @@ class MetadataWorker : public Nan::AsyncWorker {
117
132
  // Metadata Object
118
133
  v8::Local<v8::Object> info = New<v8::Object>();
119
134
  Set(info, New("format").ToLocalChecked(), New<v8::String>(baton->format).ToLocalChecked());
135
+ if (baton->input->bufferLength > 0) {
136
+ Set(info, New("size").ToLocalChecked(), New<v8::Uint32>(static_cast<uint32_t>(baton->input->bufferLength)));
137
+ }
120
138
  Set(info, New("width").ToLocalChecked(), New<v8::Uint32>(baton->width));
121
139
  Set(info, New("height").ToLocalChecked(), New<v8::Uint32>(baton->height));
122
140
  Set(info, New("space").ToLocalChecked(), New<v8::String>(baton->space).ToLocalChecked());
@@ -125,6 +143,21 @@ class MetadataWorker : public Nan::AsyncWorker {
125
143
  if (baton->density > 0) {
126
144
  Set(info, New("density").ToLocalChecked(), New<v8::Uint32>(baton->density));
127
145
  }
146
+ if (!baton->chromaSubsampling.empty()) {
147
+ Set(info,
148
+ New("chromaSubsampling").ToLocalChecked(),
149
+ New<v8::String>(baton->chromaSubsampling).ToLocalChecked());
150
+ }
151
+ Set(info, New("isProgressive").ToLocalChecked(), New<v8::Boolean>(baton->isProgressive));
152
+ if (baton->paletteBitDepth > 0) {
153
+ Set(info, New("paletteBitDepth").ToLocalChecked(), New<v8::Uint32>(baton->paletteBitDepth));
154
+ }
155
+ if (baton->pages > 0) {
156
+ Set(info, New("pages").ToLocalChecked(), New<v8::Uint32>(baton->pages));
157
+ }
158
+ if (baton->pageHeight > 0) {
159
+ Set(info, New("pageHeight").ToLocalChecked(), New<v8::Uint32>(baton->pageHeight));
160
+ }
128
161
  Set(info, New("hasProfile").ToLocalChecked(), New<v8::Boolean>(baton->hasProfile));
129
162
  Set(info, New("hasAlpha").ToLocalChecked(), New<v8::Boolean>(baton->hasAlpha));
130
163
  if (baton->orientation > 0) {
package/src/metadata.h CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -31,6 +31,11 @@ struct MetadataBaton {
31
31
  int channels;
32
32
  std::string depth;
33
33
  int density;
34
+ std::string chromaSubsampling;
35
+ bool isProgressive;
36
+ int paletteBitDepth;
37
+ int pages;
38
+ int pageHeight;
34
39
  bool hasProfile;
35
40
  bool hasAlpha;
36
41
  int orientation;
@@ -50,6 +55,10 @@ struct MetadataBaton {
50
55
  height(0),
51
56
  channels(0),
52
57
  density(0),
58
+ isProgressive(false),
59
+ paletteBitDepth(0),
60
+ pages(0),
61
+ pageHeight(0),
53
62
  hasProfile(false),
54
63
  hasAlpha(false),
55
64
  orientation(0),
package/src/operations.cc CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -38,6 +38,18 @@ namespace sharp {
38
38
  return image;
39
39
  }
40
40
 
41
+ /*
42
+ Ensures alpha channel, if missing.
43
+ */
44
+ VImage EnsureAlpha(VImage image) {
45
+ if (!HasAlpha(image)) {
46
+ std::vector<double> alpha;
47
+ alpha.push_back(sharp::MaximumImageAlpha(image.interpretation()));
48
+ image = image.bandjoin_const(alpha);
49
+ }
50
+ return image;
51
+ }
52
+
41
53
  /*
42
54
  Composite overlayImage over image at given position
43
55
  Assumes alpha channels are already premultiplied and will be unpremultiplied after
@@ -78,7 +90,7 @@ namespace sharp {
78
90
  //
79
91
  // References:
80
92
  // - http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
81
- // - https://github.com/jcupitt/ruby-vips/issues/28#issuecomment-9014826
93
+ // - https://github.com/libvips/ruby-vips/issues/28#issuecomment-9014826
82
94
  //
83
95
  // out_a = src_a + dst_a * (1 - src_a)
84
96
  // ^^^^^^^^^^^
@@ -278,6 +290,25 @@ namespace sharp {
278
290
  return image.conv(kernel);
279
291
  }
280
292
 
293
+ /*
294
+ * Recomb with a Matrix of the given bands/channel size.
295
+ * Eg. RGB will be a 3x3 matrix.
296
+ */
297
+ VImage Recomb(VImage image, std::unique_ptr<double[]> const &matrix) {
298
+ double *m = matrix.get();
299
+ return image
300
+ .colourspace(VIPS_INTERPRETATION_sRGB)
301
+ .recomb(image.bands() == 3
302
+ ? VImage::new_from_memory(
303
+ m, 9 * sizeof(double), 3, 3, 1, VIPS_FORMAT_DOUBLE
304
+ )
305
+ : VImage::new_matrixv(4, 4,
306
+ m[0], m[1], m[2], 0.0,
307
+ m[3], m[4], m[5], 0.0,
308
+ m[6], m[7], m[8], 0.0,
309
+ 0.0, 0.0, 0.0, 1.0));
310
+ }
311
+
281
312
  /*
282
313
  * Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.
283
314
  */
@@ -324,55 +355,22 @@ namespace sharp {
324
355
  return image.boolean(imageR, boolean);
325
356
  }
326
357
 
327
- VImage Trim(VImage image, int const tolerance) {
328
- using sharp::MaximumImageAlpha;
329
- // An equivalent of ImageMagick's -trim in C++ ... automatically remove
330
- // "boring" image edges.
331
-
332
- // We use .project to sum the rows and columns of a 0/255 mask image, the first
333
- // non-zero row or column is the object edge. We make the mask image with an
334
- // amount-different-from-background image plus a threshold.
335
-
336
- // find the value of the pixel at (0, 0) ... we will search for all pixels
337
- // significantly different from this
338
- std::vector<double> background = image(0, 0);
339
-
340
- double const max = MaximumImageAlpha(image.interpretation());
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) {
358
+ /*
359
+ Trim an image
360
+ */
361
+ VImage Trim(VImage image, double const threshold) {
362
+ // Top-left pixel provides the background colour
363
+ VImage background = image.extract_area(0, 0, 1, 1);
364
+ if (HasAlpha(background)) {
365
+ background = background.flatten();
366
+ }
367
+ int top, width, height;
368
+ int const left = image.find_trim(&top, &width, &height, VImage::option()
369
+ ->set("background", background(0, 0))
370
+ ->set("threshold", threshold));
371
+ if (width == 0 || height == 0) {
372
372
  throw VError("Unexpected error while trimming. Try to lower the tolerance");
373
373
  }
374
-
375
- // and now crop the original image
376
374
  return image.extract_area(left, top, width, height);
377
375
  }
378
376
 
package/src/operations.h CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -30,6 +30,11 @@ namespace sharp {
30
30
  */
31
31
  VImage RemoveAlpha(VImage image);
32
32
 
33
+ /*
34
+ Ensures alpha channel, if missing.
35
+ */
36
+ VImage EnsureAlpha(VImage image);
37
+
33
38
  /*
34
39
  Alpha composite src over dst with given gravity.
35
40
  Assumes alpha channels are already premultiplied and will be unpremultiplied after.
@@ -100,13 +105,19 @@ namespace sharp {
100
105
  /*
101
106
  Trim an image
102
107
  */
103
- VImage Trim(VImage image, int const tolerance);
108
+ VImage Trim(VImage image, double const threshold);
104
109
 
105
110
  /*
106
111
  * Linear adjustment (a * in + b)
107
112
  */
108
113
  VImage Linear(VImage image, double const a, double const b);
109
114
 
115
+ /*
116
+ * Recomb with a Matrix of the given bands/channel size.
117
+ * Eg. RGB will be a 3x3 matrix.
118
+ */
119
+ VImage Recomb(VImage image, std::unique_ptr<double[]> const &matrix);
120
+
110
121
  } // namespace sharp
111
122
 
112
123
  #endif // SRC_OPERATIONS_H_