sharp 0.27.1 → 0.30.5

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/operations.cc CHANGED
@@ -92,6 +92,13 @@ namespace sharp {
92
92
  return image;
93
93
  }
94
94
 
95
+ /*
96
+ * Contrast limiting adapative histogram equalization (CLAHE)
97
+ */
98
+ VImage Clahe(VImage image, int const width, int const height, int const maxSlope) {
99
+ return image.hist_local(width, height, VImage::option()->set("max_slope", maxSlope));
100
+ }
101
+
95
102
  /*
96
103
  * Gamma encoding/decoding
97
104
  */
@@ -105,6 +112,19 @@ namespace sharp {
105
112
  }
106
113
  }
107
114
 
115
+ /**
116
+ * Produce the "negative" of the image.
117
+ */
118
+ VImage Negate(VImage image, bool const negateAlpha) {
119
+ if (HasAlpha(image) && !negateAlpha) {
120
+ // Separate alpha channel
121
+ VImage alpha = image[image.bands() - 1];
122
+ return RemoveAlpha(image).invert().bandjoin(alpha);
123
+ } else {
124
+ return image.invert();
125
+ }
126
+ }
127
+
108
128
  /*
109
129
  * Gaussian blur. Use sigma of -1.0 for fast blur.
110
130
  */
@@ -149,8 +169,8 @@ namespace sharp {
149
169
  */
150
170
  VImage Recomb(VImage image, std::unique_ptr<double[]> const &matrix) {
151
171
  double *m = matrix.get();
172
+ image = image.colourspace(VIPS_INTERPRETATION_sRGB);
152
173
  return image
153
- .colourspace(VIPS_INTERPRETATION_sRGB)
154
174
  .recomb(image.bands() == 3
155
175
  ? VImage::new_from_memory(
156
176
  m, 9 * sizeof(double), 3, 3, 1, VIPS_FORMAT_DOUBLE
@@ -162,7 +182,8 @@ namespace sharp {
162
182
  0.0, 0.0, 0.0, 1.0));
163
183
  }
164
184
 
165
- VImage Modulate(VImage image, double const brightness, double const saturation, int const hue) {
185
+ VImage Modulate(VImage image, double const brightness, double const saturation,
186
+ int const hue, double const lightness) {
166
187
  if (HasAlpha(image)) {
167
188
  // Separate alpha channel
168
189
  VImage alpha = image[image.bands() - 1];
@@ -170,7 +191,7 @@ namespace sharp {
170
191
  .colourspace(VIPS_INTERPRETATION_LCH)
171
192
  .linear(
172
193
  { brightness, saturation, 1},
173
- { 0.0, 0.0, static_cast<double>(hue) }
194
+ { lightness, 0.0, static_cast<double>(hue) }
174
195
  )
175
196
  .colourspace(VIPS_INTERPRETATION_sRGB)
176
197
  .bandjoin(alpha);
@@ -179,7 +200,7 @@ namespace sharp {
179
200
  .colourspace(VIPS_INTERPRETATION_LCH)
180
201
  .linear(
181
202
  { brightness, saturation, 1 },
182
- { 0.0, 0.0, static_cast<double>(hue) }
203
+ { lightness, 0.0, static_cast<double>(hue) }
183
204
  )
184
205
  .colourspace(VIPS_INTERPRETATION_sRGB);
185
206
  }
@@ -188,7 +209,8 @@ namespace sharp {
188
209
  /*
189
210
  * Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.
190
211
  */
191
- VImage Sharpen(VImage image, double const sigma, double const flat, double const jagged) {
212
+ VImage Sharpen(VImage image, double const sigma, double const m1, double const m2,
213
+ double const x1, double const y2, double const y3) {
192
214
  if (sigma == -1.0) {
193
215
  // Fast, mild sharpen
194
216
  VImage sharpen = VImage::new_matrixv(3, 3,
@@ -203,8 +225,14 @@ namespace sharp {
203
225
  if (colourspaceBeforeSharpen == VIPS_INTERPRETATION_RGB) {
204
226
  colourspaceBeforeSharpen = VIPS_INTERPRETATION_sRGB;
205
227
  }
206
- return image.sharpen(
207
- VImage::option()->set("sigma", sigma)->set("m1", flat)->set("m2", jagged))
228
+ return image
229
+ .sharpen(VImage::option()
230
+ ->set("sigma", sigma)
231
+ ->set("m1", m1)
232
+ ->set("m2", m2)
233
+ ->set("x1", x1)
234
+ ->set("y2", y2)
235
+ ->set("y3", y3))
208
236
  .colourspace(colourspaceBeforeSharpen);
209
237
  }
210
238
  }
@@ -275,4 +303,110 @@ namespace sharp {
275
303
  return image.linear(a, b);
276
304
  }
277
305
  }
306
+
307
+ /*
308
+ * Ensure the image is in a given colourspace
309
+ */
310
+ VImage EnsureColourspace(VImage image, VipsInterpretation colourspace) {
311
+ if (colourspace != VIPS_INTERPRETATION_LAST && image.interpretation() != colourspace) {
312
+ image = image.colourspace(colourspace,
313
+ VImage::option()->set("source_space", image.interpretation()));
314
+ }
315
+ return image;
316
+ }
317
+
318
+ /*
319
+ * Split and crop each frame, reassemble, and update pageHeight.
320
+ */
321
+ VImage CropMultiPage(VImage image, int left, int top, int width, int height,
322
+ int nPages, int *pageHeight) {
323
+ if (top == 0 && height == *pageHeight) {
324
+ // Fast path; no need to adjust the height of the multi-page image
325
+ return image.extract_area(left, 0, width, image.height());
326
+ } else {
327
+ std::vector<VImage> pages;
328
+ pages.reserve(nPages);
329
+
330
+ // Split the image into cropped frames
331
+ for (int i = 0; i < nPages; i++) {
332
+ pages.push_back(
333
+ image.extract_area(left, *pageHeight * i + top, width, height));
334
+ }
335
+
336
+ // Reassemble the frames into a tall, thin image
337
+ VImage assembled = VImage::arrayjoin(pages,
338
+ VImage::option()->set("across", 1));
339
+
340
+ // Update the page height
341
+ *pageHeight = height;
342
+
343
+ return assembled;
344
+ }
345
+ }
346
+
347
+ /*
348
+ * Split into frames, embed each frame, reassemble, and update pageHeight.
349
+ */
350
+ VImage EmbedMultiPage(VImage image, int left, int top, int width, int height,
351
+ std::vector<double> background, int nPages, int *pageHeight) {
352
+ if (top == 0 && height == *pageHeight) {
353
+ // Fast path; no need to adjust the height of the multi-page image
354
+ return image.embed(left, 0, width, image.height(), VImage::option()
355
+ ->set("extend", VIPS_EXTEND_BACKGROUND)
356
+ ->set("background", background));
357
+ } else if (left == 0 && width == image.width()) {
358
+ // Fast path; no need to adjust the width of the multi-page image
359
+ std::vector<VImage> pages;
360
+ pages.reserve(nPages);
361
+
362
+ // Rearrange the tall image into a vertical grid
363
+ image = image.grid(*pageHeight, nPages, 1);
364
+
365
+ // Do the embed on the wide image
366
+ image = image.embed(0, top, image.width(), height, VImage::option()
367
+ ->set("extend", VIPS_EXTEND_BACKGROUND)
368
+ ->set("background", background));
369
+
370
+ // Split the wide image into frames
371
+ for (int i = 0; i < nPages; i++) {
372
+ pages.push_back(
373
+ image.extract_area(width * i, 0, width, height));
374
+ }
375
+
376
+ // Reassemble the frames into a tall, thin image
377
+ VImage assembled = VImage::arrayjoin(pages,
378
+ VImage::option()->set("across", 1));
379
+
380
+ // Update the page height
381
+ *pageHeight = height;
382
+
383
+ return assembled;
384
+ } else {
385
+ std::vector<VImage> pages;
386
+ pages.reserve(nPages);
387
+
388
+ // Split the image into frames
389
+ for (int i = 0; i < nPages; i++) {
390
+ pages.push_back(
391
+ image.extract_area(0, *pageHeight * i, image.width(), *pageHeight));
392
+ }
393
+
394
+ // Embed each frame in the target size
395
+ for (int i = 0; i < nPages; i++) {
396
+ pages[i] = pages[i].embed(left, top, width, height, VImage::option()
397
+ ->set("extend", VIPS_EXTEND_BACKGROUND)
398
+ ->set("background", background));
399
+ }
400
+
401
+ // Reassemble the frames into a tall, thin image
402
+ VImage assembled = VImage::arrayjoin(pages,
403
+ VImage::option()->set("across", 1));
404
+
405
+ // Update the page height
406
+ *pageHeight = height;
407
+
408
+ return assembled;
409
+ }
410
+ }
411
+
278
412
  } // namespace sharp
package/src/operations.h CHANGED
@@ -35,11 +35,21 @@ namespace sharp {
35
35
  */
36
36
  VImage Normalise(VImage image);
37
37
 
38
+ /*
39
+ * Contrast limiting adapative histogram equalization (CLAHE)
40
+ */
41
+ VImage Clahe(VImage image, int const width, int const height, int const maxSlope);
42
+
38
43
  /*
39
44
  * Gamma encoding/decoding
40
45
  */
41
46
  VImage Gamma(VImage image, double const exponent);
42
47
 
48
+ /*
49
+ * Produce the "negative" of the image.
50
+ */
51
+ VImage Negate(VImage image, bool const negateAlpha);
52
+
43
53
  /*
44
54
  * Gaussian blur. Use sigma of -1.0 for fast blur.
45
55
  */
@@ -54,7 +64,8 @@ namespace sharp {
54
64
  /*
55
65
  * Sharpen flat and jagged areas. Use sigma of -1.0 for fast sharpen.
56
66
  */
57
- VImage Sharpen(VImage image, double const sigma, double const flat, double const jagged);
67
+ VImage Sharpen(VImage image, double const sigma, double const m1, double const m2,
68
+ double const x1, double const y2, double const y3);
58
69
 
59
70
  /*
60
71
  Threshold an image
@@ -88,9 +99,27 @@ namespace sharp {
88
99
  VImage Recomb(VImage image, std::unique_ptr<double[]> const &matrix);
89
100
 
90
101
  /*
91
- * Modulate brightness, saturation and hue
102
+ * Modulate brightness, saturation, hue and lightness
103
+ */
104
+ VImage Modulate(VImage image, double const brightness, double const saturation,
105
+ int const hue, double const lightness);
106
+
107
+ /*
108
+ * Ensure the image is in a given colourspace
109
+ */
110
+ VImage EnsureColourspace(VImage image, VipsInterpretation colourspace);
111
+
112
+ /*
113
+ * Split and crop each frame, reassemble, and update pageHeight.
114
+ */
115
+ VImage CropMultiPage(VImage image, int left, int top, int width, int height,
116
+ int nPages, int *pageHeight);
117
+
118
+ /*
119
+ * Split into frames, embed each frame, reassemble, and update pageHeight.
92
120
  */
93
- VImage Modulate(VImage image, double const brightness, double const saturation, int const hue);
121
+ VImage EmbedMultiPage(VImage image, int left, int top, int width, int height,
122
+ std::vector<double> background, int nPages, int *pageHeight);
94
123
 
95
124
  } // namespace sharp
96
125