sharp 0.23.3 → 0.23.4

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/docs/api-input.md CHANGED
@@ -44,6 +44,7 @@ A `Promise` is returned when `callback` is not provided.
44
44
  - `icc`: Buffer containing raw [ICC][3] profile data, if present
45
45
  - `iptc`: Buffer containing raw IPTC data, if present
46
46
  - `xmp`: Buffer containing raw XMP data, if present
47
+ - `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
47
48
 
48
49
  ### Parameters
49
50
 
package/docs/changelog.md CHANGED
@@ -4,6 +4,16 @@
4
4
 
5
5
  Requires libvips v8.8.1.
6
6
 
7
+ #### v0.23.4 - 5<sup>th</sup> December 2019
8
+
9
+ * Handle zero-length Buffer objects when using Node.js v13.2.0+.
10
+
11
+ * Expose raw TIFFTAG_PHOTOSHOP metadata.
12
+ [#1600](https://github.com/lovell/sharp/issues/1600)
13
+
14
+ * Improve thread safety by using copy-on-write when updating metadata.
15
+ [#1986](https://github.com/lovell/sharp/issues/1986)
16
+
7
17
  #### v0.23.3 - 17<sup>th</sup> November 2019
8
18
 
9
19
  * Ensure `trim` operation supports images contained in the alpha channel.
package/docs/install.md CHANGED
@@ -106,6 +106,8 @@ Only 64-bit (x64) `node.exe` is supported.
106
106
 
107
107
  ### FreeBSD
108
108
 
109
+ [![FreeBSD Build Status](https://api.cirrus-ci.com/github/lovell/sharp.svg)](https://cirrus-ci.com/github/lovell/sharp)
110
+
109
111
  libvips must be installed before `npm install` is run.
110
112
 
111
113
  This can be achieved via package or ports:
@@ -126,6 +128,9 @@ https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=193528
126
128
  Set [NODE_MODULES_CACHE](https://devcenter.heroku.com/articles/nodejs-support#cache-behavior)
127
129
  to `false` when using the `yarn` package manager.
128
130
 
131
+ To reduce the effects of memory fragmentation, add the
132
+ [jemalloc buildpack](https://github.com/gaffneyc/heroku-buildpack-jemalloc).
133
+
129
134
  ### Docker
130
135
 
131
136
  [Marc Bachmann](https://github.com/marcbachmann) maintains an
package/lib/input.js CHANGED
@@ -207,6 +207,7 @@ function clone () {
207
207
  * - `icc`: Buffer containing raw [ICC](https://www.npmjs.com/package/icc) profile data, if present
208
208
  * - `iptc`: Buffer containing raw IPTC data, if present
209
209
  * - `xmp`: Buffer containing raw XMP data, if present
210
+ * - `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
210
211
  *
211
212
  * @example
212
213
  * const image = sharp(inputJpg);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sharp",
3
3
  "description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
4
- "version": "0.23.3",
4
+ "version": "0.23.4",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://github.com/lovell/sharp",
7
7
  "contributors": [
@@ -125,7 +125,7 @@
125
125
  "icc": "^1.0.0",
126
126
  "license-checker": "^25.0.1",
127
127
  "mocha": "^6.2.2",
128
- "mock-fs": "^4.10.3",
128
+ "mock-fs": "^4.10.4",
129
129
  "nyc": "^14.1.1",
130
130
  "prebuild": "^9.1.1",
131
131
  "prebuild-ci": "^3.1.0",
package/src/common.cc CHANGED
@@ -58,6 +58,7 @@ namespace sharp {
58
58
  v8::Local<v8::Object> buffer = AttrAs<v8::Object>(input, "buffer");
59
59
  descriptor->bufferLength = node::Buffer::Length(buffer);
60
60
  descriptor->buffer = node::Buffer::Data(buffer);
61
+ descriptor->isBuffer = TRUE;
61
62
  buffersToPersist.push_back(buffer);
62
63
  }
63
64
  descriptor->failOnError = AttrTo<bool>(input, "failOnError");
@@ -246,7 +247,7 @@ namespace sharp {
246
247
  std::tuple<VImage, ImageType> OpenInput(InputDescriptor *descriptor, VipsAccess accessMethod) {
247
248
  VImage image;
248
249
  ImageType imageType;
249
- if (descriptor->buffer != nullptr) {
250
+ if (descriptor->isBuffer) {
250
251
  if (descriptor->rawChannels > 0) {
251
252
  // Raw, uncompressed pixel data
252
253
  image = VImage::new_from_memory(descriptor->buffer, descriptor->bufferLength,
@@ -277,7 +278,7 @@ namespace sharp {
277
278
  }
278
279
  image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
279
280
  if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
280
- SetDensity(image, descriptor->density);
281
+ image = SetDensity(image, descriptor->density);
281
282
  }
282
283
  } catch (vips::VError const &err) {
283
284
  throw vips::VError(std::string("Input buffer has corrupt header: ") + err.what());
@@ -323,7 +324,7 @@ namespace sharp {
323
324
  }
324
325
  image = VImage::new_from_file(descriptor->file.data(), option);
325
326
  if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
326
- SetDensity(image, descriptor->density);
327
+ image = SetDensity(image, descriptor->density);
327
328
  }
328
329
  } catch (vips::VError const &err) {
329
330
  throw vips::VError(std::string("Input file has corrupt header: ") + err.what());
@@ -370,15 +371,19 @@ namespace sharp {
370
371
  /*
371
372
  Set EXIF Orientation of image.
372
373
  */
373
- void SetExifOrientation(VImage image, int const orientation) {
374
- image.set(VIPS_META_ORIENTATION, orientation);
374
+ VImage SetExifOrientation(VImage image, int const orientation) {
375
+ VImage copy = image.copy();
376
+ copy.set(VIPS_META_ORIENTATION, orientation);
377
+ return copy;
375
378
  }
376
379
 
377
380
  /*
378
381
  Remove EXIF Orientation from image.
379
382
  */
380
- void RemoveExifOrientation(VImage image) {
381
- vips_image_remove(image.get_image(), VIPS_META_ORIENTATION);
383
+ VImage RemoveExifOrientation(VImage image) {
384
+ VImage copy = image.copy();
385
+ copy.remove(VIPS_META_ORIENTATION);
386
+ return copy;
382
387
  }
383
388
 
384
389
  /*
@@ -398,11 +403,13 @@ namespace sharp {
398
403
  /*
399
404
  Set pixels/mm resolution based on a pixels/inch density.
400
405
  */
401
- void SetDensity(VImage image, const double density) {
406
+ VImage SetDensity(VImage image, const double density) {
402
407
  const double pixelsPerMm = density / 25.4;
403
- image.set("Xres", pixelsPerMm);
404
- image.set("Yres", pixelsPerMm);
405
- image.set(VIPS_META_RESOLUTION_UNIT, "in");
408
+ VImage copy = image.copy();
409
+ copy.set("Xres", pixelsPerMm);
410
+ copy.set("Yres", pixelsPerMm);
411
+ copy.set(VIPS_META_RESOLUTION_UNIT, "in");
412
+ return copy;
406
413
  }
407
414
 
408
415
  /*
package/src/common.h CHANGED
@@ -49,6 +49,7 @@ namespace sharp {
49
49
  char *buffer;
50
50
  bool failOnError;
51
51
  size_t bufferLength;
52
+ bool isBuffer;
52
53
  double density;
53
54
  int rawChannels;
54
55
  int rawWidth;
@@ -64,6 +65,7 @@ namespace sharp {
64
65
  buffer(nullptr),
65
66
  failOnError(TRUE),
66
67
  bufferLength(0),
68
+ isBuffer(FALSE),
67
69
  density(72.0),
68
70
  rawChannels(0),
69
71
  rawWidth(0),
@@ -175,12 +177,12 @@ namespace sharp {
175
177
  /*
176
178
  Set EXIF Orientation of image.
177
179
  */
178
- void SetExifOrientation(VImage image, int const orientation);
180
+ VImage SetExifOrientation(VImage image, int const orientation);
179
181
 
180
182
  /*
181
183
  Remove EXIF Orientation from image.
182
184
  */
183
- void RemoveExifOrientation(VImage image);
185
+ VImage RemoveExifOrientation(VImage image);
184
186
 
185
187
  /*
186
188
  Does this image have a non-default density?
@@ -195,7 +197,7 @@ namespace sharp {
195
197
  /*
196
198
  Set pixels/mm resolution based on a pixels/inch density.
197
199
  */
198
- void SetDensity(VImage image, const double density);
200
+ VImage SetDensity(VImage image, const double density);
199
201
 
200
202
  /*
201
203
  Check the proposed format supports the current dimensions.
package/src/metadata.cc CHANGED
@@ -116,6 +116,14 @@ class MetadataWorker : public Nan::AsyncWorker {
116
116
  memcpy(baton->xmp, xmp, xmpLength);
117
117
  baton->xmpLength = xmpLength;
118
118
  }
119
+ // TIFFTAG_PHOTOSHOP
120
+ if (image.get_typeof(VIPS_META_PHOTOSHOP_NAME) == VIPS_TYPE_BLOB) {
121
+ size_t tifftagPhotoshopLength;
122
+ void const *tifftagPhotoshop = image.get_blob(VIPS_META_PHOTOSHOP_NAME, &tifftagPhotoshopLength);
123
+ baton->tifftagPhotoshop = static_cast<char *>(g_malloc(tifftagPhotoshopLength));
124
+ memcpy(baton->tifftagPhotoshop, tifftagPhotoshop, tifftagPhotoshopLength);
125
+ baton->tifftagPhotoshopLength = tifftagPhotoshopLength;
126
+ }
119
127
  }
120
128
 
121
129
  // Clean up
@@ -189,6 +197,12 @@ class MetadataWorker : public Nan::AsyncWorker {
189
197
  New("xmp").ToLocalChecked(),
190
198
  Nan::NewBuffer(baton->xmp, baton->xmpLength, sharp::FreeCallback, nullptr).ToLocalChecked());
191
199
  }
200
+ if (baton->tifftagPhotoshopLength > 0) {
201
+ Set(info,
202
+ New("tifftagPhotoshop").ToLocalChecked(),
203
+ Nan::NewBuffer(baton->tifftagPhotoshop, baton->tifftagPhotoshopLength, sharp::FreeCallback, nullptr)
204
+ .ToLocalChecked());
205
+ }
192
206
  argv[1] = info;
193
207
  }
194
208
 
package/src/metadata.h CHANGED
@@ -48,6 +48,8 @@ struct MetadataBaton {
48
48
  size_t iptcLength;
49
49
  char *xmp;
50
50
  size_t xmpLength;
51
+ char *tifftagPhotoshop;
52
+ size_t tifftagPhotoshopLength;
51
53
  std::string err;
52
54
 
53
55
  MetadataBaton():
@@ -71,7 +73,9 @@ struct MetadataBaton {
71
73
  iptc(nullptr),
72
74
  iptcLength(0),
73
75
  xmp(nullptr),
74
- xmpLength(0) {}
76
+ xmpLength(0),
77
+ tifftagPhotoshop(nullptr),
78
+ tifftagPhotoshopLength(0) {}
75
79
  };
76
80
 
77
81
  NAN_METHOD(metadata);
package/src/pipeline.cc CHANGED
@@ -104,7 +104,7 @@ class PipelineWorker : public Nan::AsyncWorker {
104
104
  if (baton->rotateBeforePreExtract) {
105
105
  if (rotation != VIPS_ANGLE_D0) {
106
106
  image = image.rot(rotation);
107
- sharp::RemoveExifOrientation(image);
107
+ image = sharp::RemoveExifOrientation(image);
108
108
  }
109
109
  if (baton->rotationAngle != 0.0) {
110
110
  std::vector<double> background;
@@ -404,20 +404,20 @@ class PipelineWorker : public Nan::AsyncWorker {
404
404
  // Rotate post-extract 90-angle
405
405
  if (!baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) {
406
406
  image = image.rot(rotation);
407
- sharp::RemoveExifOrientation(image);
407
+ image = sharp::RemoveExifOrientation(image);
408
408
  }
409
409
 
410
410
 
411
411
  // Flip (mirror about Y axis)
412
412
  if (baton->flip) {
413
413
  image = image.flip(VIPS_DIRECTION_VERTICAL);
414
- sharp::RemoveExifOrientation(image);
414
+ image = sharp::RemoveExifOrientation(image);
415
415
  }
416
416
 
417
417
  // Flop (mirror about X axis)
418
418
  if (baton->flop) {
419
419
  image = image.flip(VIPS_DIRECTION_HORIZONTAL);
420
- sharp::RemoveExifOrientation(image);
420
+ image = sharp::RemoveExifOrientation(image);
421
421
  }
422
422
 
423
423
  // Join additional color channels to the image
@@ -700,7 +700,7 @@ class PipelineWorker : public Nan::AsyncWorker {
700
700
 
701
701
  // Override EXIF Orientation tag
702
702
  if (baton->withMetadata && baton->withMetadataOrientation != -1) {
703
- sharp::SetExifOrientation(image, baton->withMetadataOrientation);
703
+ image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
704
704
  }
705
705
 
706
706
  // Number of channels used in output image