Skip to content

Commit 29537c1

Browse files
committed
Improve thread safety with copy-on-write for metadata #1986
1 parent 8f8b2a1 commit 29537c1

File tree

4 files changed

+29
-18
lines changed

4 files changed

+29
-18
lines changed

docs/changelog.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
Requires libvips v8.8.1.
66

7+
#### v0.23.4 - TBD
8+
9+
* Improve thread safety by using copy-on-write when updating metadata.
10+
[#1986](https://github.com/lovell/sharp/issues/1986)
11+
712
#### v0.23.3 - 17<sup>th</sup> November 2019
813

914
* Ensure `trim` operation supports images contained in the alpha channel.

src/common.cc

+16-10
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ namespace sharp {
277277
}
278278
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
279279
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
280-
SetDensity(image, descriptor->density);
280+
image = SetDensity(image, descriptor->density);
281281
}
282282
} catch (vips::VError const &err) {
283283
throw vips::VError(std::string("Input buffer has corrupt header: ") + err.what());
@@ -323,7 +323,7 @@ namespace sharp {
323323
}
324324
image = VImage::new_from_file(descriptor->file.data(), option);
325325
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
326-
SetDensity(image, descriptor->density);
326+
image = SetDensity(image, descriptor->density);
327327
}
328328
} catch (vips::VError const &err) {
329329
throw vips::VError(std::string("Input file has corrupt header: ") + err.what());
@@ -370,15 +370,19 @@ namespace sharp {
370370
/*
371371
Set EXIF Orientation of image.
372372
*/
373-
void SetExifOrientation(VImage image, int const orientation) {
374-
image.set(VIPS_META_ORIENTATION, orientation);
373+
VImage SetExifOrientation(VImage image, int const orientation) {
374+
VImage copy = image.copy();
375+
copy.set(VIPS_META_ORIENTATION, orientation);
376+
return copy;
375377
}
376378

377379
/*
378380
Remove EXIF Orientation from image.
379381
*/
380-
void RemoveExifOrientation(VImage image) {
381-
vips_image_remove(image.get_image(), VIPS_META_ORIENTATION);
382+
VImage RemoveExifOrientation(VImage image) {
383+
VImage copy = image.copy();
384+
copy.remove(VIPS_META_ORIENTATION);
385+
return copy;
382386
}
383387

384388
/*
@@ -398,11 +402,13 @@ namespace sharp {
398402
/*
399403
Set pixels/mm resolution based on a pixels/inch density.
400404
*/
401-
void SetDensity(VImage image, const double density) {
405+
VImage SetDensity(VImage image, const double density) {
402406
const double pixelsPerMm = density / 25.4;
403-
image.set("Xres", pixelsPerMm);
404-
image.set("Yres", pixelsPerMm);
405-
image.set(VIPS_META_RESOLUTION_UNIT, "in");
407+
VImage copy = image.copy();
408+
copy.set("Xres", pixelsPerMm);
409+
copy.set("Yres", pixelsPerMm);
410+
copy.set(VIPS_META_RESOLUTION_UNIT, "in");
411+
return copy;
406412
}
407413

408414
/*

src/common.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,12 @@ namespace sharp {
175175
/*
176176
Set EXIF Orientation of image.
177177
*/
178-
void SetExifOrientation(VImage image, int const orientation);
178+
VImage SetExifOrientation(VImage image, int const orientation);
179179

180180
/*
181181
Remove EXIF Orientation from image.
182182
*/
183-
void RemoveExifOrientation(VImage image);
183+
VImage RemoveExifOrientation(VImage image);
184184

185185
/*
186186
Does this image have a non-default density?
@@ -195,7 +195,7 @@ namespace sharp {
195195
/*
196196
Set pixels/mm resolution based on a pixels/inch density.
197197
*/
198-
void SetDensity(VImage image, const double density);
198+
VImage SetDensity(VImage image, const double density);
199199

200200
/*
201201
Check the proposed format supports the current dimensions.

src/pipeline.cc

+5-5
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class PipelineWorker : public Nan::AsyncWorker {
104104
if (baton->rotateBeforePreExtract) {
105105
if (rotation != VIPS_ANGLE_D0) {
106106
image = image.rot(rotation);
107-
sharp::RemoveExifOrientation(image);
107+
image = sharp::RemoveExifOrientation(image);
108108
}
109109
if (baton->rotationAngle != 0.0) {
110110
std::vector<double> background;
@@ -404,20 +404,20 @@ class PipelineWorker : public Nan::AsyncWorker {
404404
// Rotate post-extract 90-angle
405405
if (!baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) {
406406
image = image.rot(rotation);
407-
sharp::RemoveExifOrientation(image);
407+
image = sharp::RemoveExifOrientation(image);
408408
}
409409

410410

411411
// Flip (mirror about Y axis)
412412
if (baton->flip) {
413413
image = image.flip(VIPS_DIRECTION_VERTICAL);
414-
sharp::RemoveExifOrientation(image);
414+
image = sharp::RemoveExifOrientation(image);
415415
}
416416

417417
// Flop (mirror about X axis)
418418
if (baton->flop) {
419419
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
420-
sharp::RemoveExifOrientation(image);
420+
image = sharp::RemoveExifOrientation(image);
421421
}
422422

423423
// Join additional color channels to the image
@@ -700,7 +700,7 @@ class PipelineWorker : public Nan::AsyncWorker {
700700

701701
// Override EXIF Orientation tag
702702
if (baton->withMetadata && baton->withMetadataOrientation != -1) {
703-
sharp::SetExifOrientation(image, baton->withMetadataOrientation);
703+
image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
704704
}
705705

706706
// Number of channels used in output image

0 commit comments

Comments
 (0)