sharp 0.17.2 → 0.18.2

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.
@@ -1,5 +1,5 @@
1
1
  // bodies for vips operations
2
- // Thu 18 Aug 16:01:57 BST 2016
2
+ // Mon 13 Mar 13:22:17 GMT 2017
3
3
  // this file is generated automatically, do not edit!
4
4
 
5
5
  void VImage::system( char * cmd_format , VOption *options )
@@ -231,7 +231,7 @@ VImage VImage::round( VipsOperationRound round , VOption *options )
231
231
  return( out );
232
232
  }
233
233
 
234
- VImage VImage::relational_const( std::vector<double> c , VipsOperationRelational relational , VOption *options )
234
+ VImage VImage::relational_const( VipsOperationRelational relational , std::vector<double> c , VOption *options )
235
235
  {
236
236
  VImage out;
237
237
 
@@ -239,8 +239,8 @@ VImage VImage::relational_const( std::vector<double> c , VipsOperationRelational
239
239
  (options ? options : VImage::option()) ->
240
240
  set( "in", *this ) ->
241
241
  set( "out", &out ) ->
242
- set( "c", c ) ->
243
- set( "relational", relational ) );
242
+ set( "relational", relational ) ->
243
+ set( "c", c ) );
244
244
 
245
245
  return( out );
246
246
  }
@@ -258,7 +258,7 @@ VImage VImage::remainder_const( std::vector<double> c , VOption *options )
258
258
  return( out );
259
259
  }
260
260
 
261
- VImage VImage::boolean_const( std::vector<double> c , VipsOperationBoolean boolean , VOption *options )
261
+ VImage VImage::boolean_const( VipsOperationBoolean boolean , std::vector<double> c , VOption *options )
262
262
  {
263
263
  VImage out;
264
264
 
@@ -266,13 +266,13 @@ VImage VImage::boolean_const( std::vector<double> c , VipsOperationBoolean boole
266
266
  (options ? options : VImage::option()) ->
267
267
  set( "in", *this ) ->
268
268
  set( "out", &out ) ->
269
- set( "c", c ) ->
270
- set( "boolean", boolean ) );
269
+ set( "boolean", boolean ) ->
270
+ set( "c", c ) );
271
271
 
272
272
  return( out );
273
273
  }
274
274
 
275
- VImage VImage::math2_const( std::vector<double> c , VipsOperationMath2 math2 , VOption *options )
275
+ VImage VImage::math2_const( VipsOperationMath2 math2 , std::vector<double> c , VOption *options )
276
276
  {
277
277
  VImage out;
278
278
 
@@ -280,8 +280,8 @@ VImage VImage::math2_const( std::vector<double> c , VipsOperationMath2 math2 , V
280
280
  (options ? options : VImage::option()) ->
281
281
  set( "in", *this ) ->
282
282
  set( "out", &out ) ->
283
- set( "c", c ) ->
284
- set( "math2", math2 ) );
283
+ set( "math2", math2 ) ->
284
+ set( "c", c ) );
285
285
 
286
286
  return( out );
287
287
  }
@@ -493,8 +493,8 @@ VImage VImage::copy( VOption *options )
493
493
 
494
494
  call( "copy" ,
495
495
  (options ? options : VImage::option()) ->
496
- set( "out", &out ) ->
497
- set( "in", *this ) );
496
+ set( "in", *this ) ->
497
+ set( "out", &out ) );
498
498
 
499
499
  return( out );
500
500
  }
@@ -505,8 +505,8 @@ VImage VImage::tilecache( VOption *options )
505
505
 
506
506
  call( "tilecache" ,
507
507
  (options ? options : VImage::option()) ->
508
- set( "out", &out ) ->
509
- set( "in", *this ) );
508
+ set( "in", *this ) ->
509
+ set( "out", &out ) );
510
510
 
511
511
  return( out );
512
512
  }
@@ -517,8 +517,8 @@ VImage VImage::linecache( VOption *options )
517
517
 
518
518
  call( "linecache" ,
519
519
  (options ? options : VImage::option()) ->
520
- set( "out", &out ) ->
521
- set( "in", *this ) );
520
+ set( "in", *this ) ->
521
+ set( "out", &out ) );
522
522
 
523
523
  return( out );
524
524
  }
@@ -529,8 +529,8 @@ VImage VImage::sequential( VOption *options )
529
529
 
530
530
  call( "sequential" ,
531
531
  (options ? options : VImage::option()) ->
532
- set( "out", &out ) ->
533
- set( "in", *this ) );
532
+ set( "in", *this ) ->
533
+ set( "out", &out ) );
534
534
 
535
535
  return( out );
536
536
  }
@@ -541,8 +541,8 @@ VImage VImage::cache( VOption *options )
541
541
 
542
542
  call( "cache" ,
543
543
  (options ? options : VImage::option()) ->
544
- set( "out", &out ) ->
545
- set( "in", *this ) );
544
+ set( "in", *this ) ->
545
+ set( "out", &out ) );
546
546
 
547
547
  return( out );
548
548
  }
@@ -569,8 +569,8 @@ VImage VImage::flip( VipsDirection direction , VOption *options )
569
569
 
570
570
  call( "flip" ,
571
571
  (options ? options : VImage::option()) ->
572
- set( "out", &out ) ->
573
572
  set( "in", *this ) ->
573
+ set( "out", &out ) ->
574
574
  set( "direction", direction ) );
575
575
 
576
576
  return( out );
@@ -633,6 +633,20 @@ VImage VImage::extract_area( int left , int top , int width , int height , VOpti
633
633
  return( out );
634
634
  }
635
635
 
636
+ VImage VImage::smartcrop( int width , int height , VOption *options )
637
+ {
638
+ VImage out;
639
+
640
+ call( "smartcrop" ,
641
+ (options ? options : VImage::option()) ->
642
+ set( "input", *this ) ->
643
+ set( "out", &out ) ->
644
+ set( "width", width ) ->
645
+ set( "height", height ) );
646
+
647
+ return( out );
648
+ }
649
+
636
650
  VImage VImage::extract_band( int band , VOption *options )
637
651
  {
638
652
  VImage out;
@@ -728,8 +742,8 @@ VImage VImage::cast( VipsBandFormat format , VOption *options )
728
742
 
729
743
  call( "cast" ,
730
744
  (options ? options : VImage::option()) ->
731
- set( "out", &out ) ->
732
745
  set( "in", *this ) ->
746
+ set( "out", &out ) ->
733
747
  set( "format", format ) );
734
748
 
735
749
  return( out );
@@ -741,8 +755,8 @@ VImage VImage::rot( VipsAngle angle , VOption *options )
741
755
 
742
756
  call( "rot" ,
743
757
  (options ? options : VImage::option()) ->
744
- set( "out", &out ) ->
745
758
  set( "in", *this ) ->
759
+ set( "out", &out ) ->
746
760
  set( "angle", angle ) );
747
761
 
748
762
  return( out );
@@ -754,8 +768,8 @@ VImage VImage::rot45( VOption *options )
754
768
 
755
769
  call( "rot45" ,
756
770
  (options ? options : VImage::option()) ->
757
- set( "out", &out ) ->
758
- set( "in", *this ) );
771
+ set( "in", *this ) ->
772
+ set( "out", &out ) );
759
773
 
760
774
  return( out );
761
775
  }
@@ -766,8 +780,8 @@ VImage VImage::autorot( VOption *options )
766
780
 
767
781
  call( "autorot" ,
768
782
  (options ? options : VImage::option()) ->
769
- set( "out", &out ) ->
770
- set( "in", *this ) );
783
+ set( "in", *this ) ->
784
+ set( "out", &out ) );
771
785
 
772
786
  return( out );
773
787
  }
@@ -805,8 +819,8 @@ VImage VImage::bandfold( VOption *options )
805
819
 
806
820
  call( "bandfold" ,
807
821
  (options ? options : VImage::option()) ->
808
- set( "out", &out ) ->
809
- set( "in", *this ) );
822
+ set( "in", *this ) ->
823
+ set( "out", &out ) );
810
824
 
811
825
  return( out );
812
826
  }
@@ -817,8 +831,8 @@ VImage VImage::bandunfold( VOption *options )
817
831
 
818
832
  call( "bandunfold" ,
819
833
  (options ? options : VImage::option()) ->
820
- set( "out", &out ) ->
821
- set( "in", *this ) );
834
+ set( "in", *this ) ->
835
+ set( "out", &out ) );
822
836
 
823
837
  return( out );
824
838
  }
@@ -829,8 +843,8 @@ VImage VImage::flatten( VOption *options )
829
843
 
830
844
  call( "flatten" ,
831
845
  (options ? options : VImage::option()) ->
832
- set( "out", &out ) ->
833
- set( "in", *this ) );
846
+ set( "in", *this ) ->
847
+ set( "out", &out ) );
834
848
 
835
849
  return( out );
836
850
  }
@@ -841,8 +855,8 @@ VImage VImage::premultiply( VOption *options )
841
855
 
842
856
  call( "premultiply" ,
843
857
  (options ? options : VImage::option()) ->
844
- set( "out", &out ) ->
845
- set( "in", *this ) );
858
+ set( "in", *this ) ->
859
+ set( "out", &out ) );
846
860
 
847
861
  return( out );
848
862
  }
@@ -853,8 +867,8 @@ VImage VImage::unpremultiply( VOption *options )
853
867
 
854
868
  call( "unpremultiply" ,
855
869
  (options ? options : VImage::option()) ->
856
- set( "out", &out ) ->
857
- set( "in", *this ) );
870
+ set( "in", *this ) ->
871
+ set( "out", &out ) );
858
872
 
859
873
  return( out );
860
874
  }
@@ -865,8 +879,8 @@ VImage VImage::grid( int tile_height , int across , int down , VOption *options
865
879
 
866
880
  call( "grid" ,
867
881
  (options ? options : VImage::option()) ->
868
- set( "out", &out ) ->
869
882
  set( "in", *this ) ->
883
+ set( "out", &out ) ->
870
884
  set( "tile-height", tile_height ) ->
871
885
  set( "across", across ) ->
872
886
  set( "down", down ) );
@@ -880,8 +894,8 @@ VImage VImage::scale( VOption *options )
880
894
 
881
895
  call( "scale" ,
882
896
  (options ? options : VImage::option()) ->
883
- set( "out", &out ) ->
884
- set( "in", *this ) );
897
+ set( "in", *this ) ->
898
+ set( "out", &out ) );
885
899
 
886
900
  return( out );
887
901
  }
@@ -892,8 +906,8 @@ VImage VImage::wrap( VOption *options )
892
906
 
893
907
  call( "wrap" ,
894
908
  (options ? options : VImage::option()) ->
895
- set( "out", &out ) ->
896
- set( "in", *this ) );
909
+ set( "in", *this ) ->
910
+ set( "out", &out ) );
897
911
 
898
912
  return( out );
899
913
  }
@@ -944,8 +958,8 @@ VImage VImage::byteswap( VOption *options )
944
958
 
945
959
  call( "byteswap" ,
946
960
  (options ? options : VImage::option()) ->
947
- set( "out", &out ) ->
948
- set( "in", *this ) );
961
+ set( "in", *this ) ->
962
+ set( "out", &out ) );
949
963
 
950
964
  return( out );
951
965
  }
@@ -1757,6 +1771,18 @@ void VImage::dzsave( char * filename , VOption *options )
1757
1771
  set( "filename", filename ) );
1758
1772
  }
1759
1773
 
1774
+ VipsBlob * VImage::dzsave_buffer( VOption *options )
1775
+ {
1776
+ VipsBlob * buffer;
1777
+
1778
+ call( "dzsave_buffer" ,
1779
+ (options ? options : VImage::option()) ->
1780
+ set( "in", *this ) ->
1781
+ set( "buffer", &buffer ) );
1782
+
1783
+ return( buffer );
1784
+ }
1785
+
1760
1786
  void VImage::pngsave( char * filename , VOption *options )
1761
1787
  {
1762
1788
  call( "pngsave" ,
@@ -1832,6 +1858,18 @@ void VImage::tiffsave( char * filename , VOption *options )
1832
1858
  set( "filename", filename ) );
1833
1859
  }
1834
1860
 
1861
+ VipsBlob * VImage::tiffsave_buffer( VOption *options )
1862
+ {
1863
+ VipsBlob * buffer;
1864
+
1865
+ call( "tiffsave_buffer" ,
1866
+ (options ? options : VImage::option()) ->
1867
+ set( "in", *this ) ->
1868
+ set( "buffer", &buffer ) );
1869
+
1870
+ return( buffer );
1871
+ }
1872
+
1835
1873
  void VImage::fitssave( char * filename , VOption *options )
1836
1874
  {
1837
1875
  call( "fitssave" ,
@@ -1840,6 +1878,32 @@ void VImage::fitssave( char * filename , VOption *options )
1840
1878
  set( "filename", filename ) );
1841
1879
  }
1842
1880
 
1881
+ VImage VImage::thumbnail( char * filename , int width , VOption *options )
1882
+ {
1883
+ VImage out;
1884
+
1885
+ call( "thumbnail" ,
1886
+ (options ? options : VImage::option()) ->
1887
+ set( "filename", filename ) ->
1888
+ set( "out", &out ) ->
1889
+ set( "width", width ) );
1890
+
1891
+ return( out );
1892
+ }
1893
+
1894
+ VImage VImage::thumbnail_buffer( VipsBlob * buffer , int width , VOption *options )
1895
+ {
1896
+ VImage out;
1897
+
1898
+ call( "thumbnail_buffer" ,
1899
+ (options ? options : VImage::option()) ->
1900
+ set( "buffer", buffer ) ->
1901
+ set( "out", &out ) ->
1902
+ set( "width", width ) );
1903
+
1904
+ return( out );
1905
+ }
1906
+
1843
1907
  VImage VImage::mapim( VImage index , VOption *options )
1844
1908
  {
1845
1909
  VImage out;
package/src/metadata.cc CHANGED
@@ -25,9 +25,10 @@
25
25
  class MetadataWorker : public Nan::AsyncWorker {
26
26
  public:
27
27
  MetadataWorker(
28
- Nan::Callback *callback, MetadataBaton *baton,
29
- std::vector<v8::Local<v8::Object>> const buffersToPersist)
30
- : Nan::AsyncWorker(callback), baton(baton), buffersToPersist(buffersToPersist) {
28
+ Nan::Callback *callback, MetadataBaton *baton, Nan::Callback *debuglog,
29
+ std::vector<v8::Local<v8::Object>> const buffersToPersist) :
30
+ Nan::AsyncWorker(callback), baton(baton), debuglog(debuglog),
31
+ buffersToPersist(buffersToPersist) {
31
32
  // Protect Buffer objects from GC, keyed on index
32
33
  std::accumulate(buffersToPersist.begin(), buffersToPersist.end(), 0,
33
34
  [this](uint32_t index, v8::Local<v8::Object> const buffer) -> uint32_t {
@@ -56,6 +57,7 @@ class MetadataWorker : public Nan::AsyncWorker {
56
57
  baton->height = image.height();
57
58
  baton->space = vips_enum_nick(VIPS_TYPE_INTERPRETATION, image.interpretation());
58
59
  baton->channels = image.bands();
60
+ baton->depth = vips_enum_nick(VIPS_TYPE_BAND_FORMAT, image.format());
59
61
  if (sharp::HasDensity(image)) {
60
62
  baton->density = sharp::GetDensity(image);
61
63
  }
@@ -102,6 +104,7 @@ class MetadataWorker : public Nan::AsyncWorker {
102
104
  Set(info, New("height").ToLocalChecked(), New<v8::Uint32>(baton->height));
103
105
  Set(info, New("space").ToLocalChecked(), New<v8::String>(baton->space).ToLocalChecked());
104
106
  Set(info, New("channels").ToLocalChecked(), New<v8::Uint32>(baton->channels));
107
+ Set(info, New("depth").ToLocalChecked(), New<v8::String>(baton->depth).ToLocalChecked());
105
108
  if (baton->density > 0) {
106
109
  Set(info, New("density").ToLocalChecked(), New<v8::Uint32>(baton->density));
107
110
  }
@@ -132,12 +135,21 @@ class MetadataWorker : public Nan::AsyncWorker {
132
135
  delete baton->input;
133
136
  delete baton;
134
137
 
138
+ // Handle warnings
139
+ std::string warning = sharp::VipsWarningPop();
140
+ while (!warning.empty()) {
141
+ v8::Local<v8::Value> message[1] = { New(warning).ToLocalChecked() };
142
+ debuglog->Call(1, message);
143
+ warning = sharp::VipsWarningPop();
144
+ }
145
+
135
146
  // Return to JavaScript
136
147
  callback->Call(2, argv);
137
148
  }
138
149
 
139
150
  private:
140
151
  MetadataBaton* baton;
152
+ Nan::Callback *debuglog;
141
153
  std::vector<v8::Local<v8::Object>> buffersToPersist;
142
154
  };
143
155
 
@@ -155,9 +167,12 @@ NAN_METHOD(metadata) {
155
167
  // Input
156
168
  baton->input = sharp::CreateInputDescriptor(sharp::AttrAs<v8::Object>(options, "input"), buffersToPersist);
157
169
 
170
+ // Function to notify of libvips warnings
171
+ Nan::Callback *debuglog = new Nan::Callback(sharp::AttrAs<v8::Function>(options, "debuglog"));
172
+
158
173
  // Join queue for worker thread
159
174
  Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());
160
- Nan::AsyncQueueWorker(new MetadataWorker(callback, baton, buffersToPersist));
175
+ Nan::AsyncQueueWorker(new MetadataWorker(callback, baton, debuglog, buffersToPersist));
161
176
 
162
177
  // Increment queued task counter
163
178
  g_atomic_int_inc(&sharp::counterQueue);
package/src/metadata.h CHANGED
@@ -29,6 +29,7 @@ struct MetadataBaton {
29
29
  int height;
30
30
  std::string space;
31
31
  int channels;
32
+ std::string depth;
32
33
  int density;
33
34
  bool hasProfile;
34
35
  bool hasAlpha;
package/src/operations.cc CHANGED
@@ -29,67 +29,32 @@ using vips::VError;
29
29
  namespace sharp {
30
30
 
31
31
  /*
32
- Alpha composite src over dst with given gravity.
33
- Assumes alpha channels are already premultiplied and will be unpremultiplied after.
32
+ Composite overlayImage over image at given position
33
+ Assumes alpha channels are already premultiplied and will be unpremultiplied after
34
34
  */
35
- VImage Composite(VImage src, VImage dst, const int gravity) {
36
- if (IsInputValidForComposition(src, dst)) {
37
- // Enlarge overlay src, if required
38
- if (src.width() < dst.width() || src.height() < dst.height()) {
39
- // Calculate the (left, top) coordinates of the output image within the input image, applying the given gravity.
40
- int left;
41
- int top;
42
- std::tie(left, top) = CalculateCrop(dst.width(), dst.height(), src.width(), src.height(), gravity);
43
- // Embed onto transparent background
44
- std::vector<double> background { 0.0, 0.0, 0.0, 0.0 };
45
- src = src.embed(left, top, dst.width(), dst.height(), VImage::option()
35
+ VImage Composite(VImage image, VImage overlayImage, int const left, int const top) {
36
+ if (HasAlpha(overlayImage)) {
37
+ // Alpha composite
38
+ if (overlayImage.width() < image.width() || overlayImage.height() < image.height()) {
39
+ // Enlarge overlay
40
+ std::vector<double> const background { 0.0, 0.0, 0.0, 0.0 };
41
+ overlayImage = overlayImage.embed(left, top, image.width(), image.height(), VImage::option()
46
42
  ->set("extend", VIPS_EXTEND_BACKGROUND)
47
43
  ->set("background", background));
48
44
  }
49
- return CompositeImage(src, dst);
50
- }
51
- // If the input was not valid for composition the return the input image itself
52
- return dst;
53
- }
54
-
55
- VImage Composite(VImage src, VImage dst, const int x, const int y) {
56
- if (IsInputValidForComposition(src, dst)) {
57
- // Enlarge overlay src, if required
58
- if (src.width() < dst.width() || src.height() < dst.height()) {
59
- // Calculate the (left, top) coordinates of the output image within the input image, applying the given gravity.
60
- int left;
61
- int top;
62
- std::tie(left, top) = CalculateCrop(dst.width(), dst.height(), src.width(), src.height(), x, y);
63
- // Embed onto transparent background
64
- std::vector<double> background { 0.0, 0.0, 0.0, 0.0 };
65
- src = src.embed(left, top, dst.width(), dst.height(), VImage::option()
66
- ->set("extend", VIPS_EXTEND_BACKGROUND)
67
- ->set("background", background));
45
+ return AlphaComposite(image, overlayImage);
46
+ } else {
47
+ if (HasAlpha(image)) {
48
+ // Add alpha channel to overlayImage so channels match
49
+ double const multiplier = sharp::Is16Bit(overlayImage.interpretation()) ? 256.0 : 1.0;
50
+ overlayImage = overlayImage.bandjoin(
51
+ VImage::new_matrix(overlayImage.width(), overlayImage.height()).new_from_image(255 * multiplier));
68
52
  }
69
- return CompositeImage(src, dst);
70
- }
71
- // If the input was not valid for composition the return the input image itself
72
- return dst;
73
- }
74
-
75
- bool IsInputValidForComposition(VImage src, VImage dst) {
76
- using sharp::CalculateCrop;
77
- using sharp::HasAlpha;
78
-
79
- if (!HasAlpha(src)) {
80
- throw VError("Overlay image must have an alpha channel");
81
- }
82
- if (!HasAlpha(dst)) {
83
- throw VError("Image to be overlaid must have an alpha channel");
84
- }
85
- if (src.width() > dst.width() || src.height() > dst.height()) {
86
- throw VError("Overlay image must have same dimensions or smaller");
53
+ return image.insert(overlayImage, left, top);
87
54
  }
88
-
89
- return true;
90
55
  }
91
56
 
92
- VImage CompositeImage(VImage src, VImage dst) {
57
+ VImage AlphaComposite(VImage dst, VImage src) {
93
58
  // Split src into non-alpha and alpha channels
94
59
  VImage srcWithoutAlpha = src.extract_band(0, VImage::option()->set("n", src.bands() - 1));
95
60
  VImage srcAlpha = src[src.bands() - 1] * (1.0 / 255.0);
@@ -302,118 +267,6 @@ namespace sharp {
302
267
  }
303
268
  }
304
269
 
305
- /*
306
- Calculate the Shannon entropy
307
- */
308
- double EntropyStrategy::operator()(VImage image) {
309
- return image.hist_find().hist_entropy();
310
- }
311
-
312
- /*
313
- Calculate the intensity of edges, skin tone and saturation
314
- */
315
- double AttentionStrategy::operator()(VImage image) {
316
- // Flatten RGBA onto a mid-grey background
317
- if (image.bands() == 4 && HasAlpha(image)) {
318
- double const midgrey = sharp::Is16Bit(image.interpretation()) ? 32768.0 : 128.0;
319
- std::vector<double> background { midgrey, midgrey, midgrey };
320
- image = image.flatten(VImage::option()->set("background", background));
321
- }
322
- // Convert to LAB colourspace
323
- VImage lab = image.colourspace(VIPS_INTERPRETATION_LAB);
324
- VImage l = lab[0];
325
- VImage a = lab[1];
326
- VImage b = lab[2];
327
- // Edge detect luminosity with the Sobel operator
328
- VImage sobel = vips::VImage::new_matrixv(3, 3,
329
- -1.0, 0.0, 1.0,
330
- -2.0, 0.0, 2.0,
331
- -1.0, 0.0, 1.0);
332
- VImage edges = l.conv(sobel).abs() + l.conv(sobel.rot90()).abs();
333
- // Skin tone chroma thresholds trained with http://humanae.tumblr.com/
334
- VImage skin = (a >= 3) & (a <= 22) & (b >= 4) & (b <= 31);
335
- // Chroma >~50% saturation
336
- VImage lch = lab.colourspace(VIPS_INTERPRETATION_LCH);
337
- VImage c = lch[1];
338
- VImage saturation = c > 60;
339
- // Find maximum in combined saliency mask
340
- VImage mask = edges + skin + saturation;
341
- return mask.max();
342
- }
343
-
344
- /*
345
- Calculate crop area based on image entropy
346
- */
347
- std::tuple<int, int> Crop(
348
- VImage image, int const outWidth, int const outHeight, std::function<double(VImage)> strategy
349
- ) {
350
- int left = 0;
351
- int top = 0;
352
- int const inWidth = image.width();
353
- int const inHeight = image.height();
354
- if (inWidth > outWidth) {
355
- // Reduce width by repeated removing slices from edge with lowest score
356
- int width = inWidth;
357
- double leftScore = 0.0;
358
- double rightScore = 0.0;
359
- // Max width of each slice
360
- int const maxSliceWidth = static_cast<int>(ceil((inWidth - outWidth) / 8.0));
361
- while (width > outWidth) {
362
- // Width of current slice
363
- int const slice = std::min(width - outWidth, maxSliceWidth);
364
- if (leftScore == 0.0) {
365
- // Update score of left slice
366
- leftScore = strategy(image.extract_area(left, 0, slice, inHeight));
367
- }
368
- if (rightScore == 0.0) {
369
- // Update score of right slice
370
- rightScore = strategy(image.extract_area(width - slice - 1, 0, slice, inHeight));
371
- }
372
- // Keep slice with highest score
373
- if (leftScore >= rightScore) {
374
- // Discard right slice
375
- rightScore = 0.0;
376
- } else {
377
- // Discard left slice
378
- leftScore = 0.0;
379
- left = left + slice;
380
- }
381
- width = width - slice;
382
- }
383
- }
384
- if (inHeight > outHeight) {
385
- // Reduce height by repeated removing slices from edge with lowest score
386
- int height = inHeight;
387
- double topScore = 0.0;
388
- double bottomScore = 0.0;
389
- // Max height of each slice
390
- int const maxSliceHeight = static_cast<int>(ceil((inHeight - outHeight) / 8.0));
391
- while (height > outHeight) {
392
- // Height of current slice
393
- int const slice = std::min(height - outHeight, maxSliceHeight);
394
- if (topScore == 0.0) {
395
- // Update score of top slice
396
- topScore = strategy(image.extract_area(0, top, inWidth, slice));
397
- }
398
- if (bottomScore == 0.0) {
399
- // Update score of bottom slice
400
- bottomScore = strategy(image.extract_area(0, height - slice - 1, inWidth, slice));
401
- }
402
- // Keep slice with highest score
403
- if (topScore >= bottomScore) {
404
- // Discard bottom slice
405
- bottomScore = 0.0;
406
- } else {
407
- // Discard top slice
408
- topScore = 0.0;
409
- top = top + slice;
410
- }
411
- height = height - slice;
412
- }
413
- }
414
- return std::make_tuple(left, top);
415
- }
416
-
417
270
  /*
418
271
  Insert a tile cache to prevent over-computation of any previous operations in the pipeline
419
272
  */
package/src/operations.h CHANGED
@@ -32,20 +32,14 @@ namespace sharp {
32
32
  VImage Composite(VImage src, VImage dst, const int gravity);
33
33
 
34
34
  /*
35
- Alpha composite src over dst with given x and y offsets.
36
- Assumes alpha channels are already premultiplied and will be unpremultiplied after.
35
+ Composite overlayImage over image at given position
37
36
  */
38
- VImage Composite(VImage src, VImage dst, const int x, const int y);
37
+ VImage Composite(VImage image, VImage overlayImage, int const x, int const y);
39
38
 
40
39
  /*
41
- Check if the src and dst Images for composition operation are valid
40
+ Alpha composite overlayImage over image, assumes matching dimensions
42
41
  */
43
- bool IsInputValidForComposition(VImage src, VImage dst);
44
-
45
- /*
46
- Given a valid src and dst, returns the composite of the two images
47
- */
48
- VImage CompositeImage(VImage src, VImage dst);
42
+ VImage AlphaComposite(VImage image, VImage overlayImage);
49
43
 
50
44
  /*
51
45
  Cutout src over dst with given gravity.
@@ -78,22 +72,6 @@ namespace sharp {
78
72
  */
79
73
  VImage Sharpen(VImage image, double const sigma, double const flat, double const jagged);
80
74
 
81
- /*
82
- Crop strategy functors
83
- */
84
- struct EntropyStrategy {
85
- double operator()(VImage image);
86
- };
87
- struct AttentionStrategy {
88
- double operator()(VImage image);
89
- };
90
-
91
- /*
92
- Calculate crop area based on given strategy (Entropy, Attention)
93
- */
94
- std::tuple<int, int> Crop(
95
- VImage image, int const outWidth, int const outHeight, std::function<double(VImage)> strategy);
96
-
97
75
  /*
98
76
  Insert a tile cache to prevent over-computation of any previous operations in the pipeline
99
77
  */