1 /* base class for all PhotoFlow layer operations 2 */ 3 4 /* 5 6 Copyright (C) 2014 Ferrero Andrea 7 8 This program is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 22 */ 23 24 /* 25 26 These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/ 27 28 */ 29 30 31 #ifndef OPERATION_H 32 #define OPERATION_H 33 34 #include <math.h> 35 #include <float.h> 36 #include <unistd.h> 37 38 #include <string> 39 #include <list> 40 #include <vector> 41 #include <iostream> 42 #include <fstream> 43 44 #include <vips/vips.h> 45 //#include <vips/vips> 46 47 #include "pftypes.hh" 48 #include "format_info.hh" 49 #include "property.hh" 50 #include "color.hh" 51 #include "image_hierarchy.hh" 52 #include "photoflow.hh" 53 54 55 56 #define OP_TEMPLATE_DEF \ 57 typename T, class BLENDER, PF::colorspace_t CS, \ 58 int CHMIN, int CHMAX, \ 59 bool has_imap, bool has_omap, bool PREVIEW 60 61 #define OP_TEMPLATE_IMP \ 62 T, BLENDER, CS, CHMIN, CHMAX, has_imap, has_omap, PREVIEW 63 64 #define OP_TEMPLATE_DEF_BLENDER_SPEC \ 65 typename T, PF::colorspace_t CS, int CHMIN, int CHMAX, \ 66 bool has_imap, bool has_omap, bool PREVIEW 67 68 #define OP_TEMPLATE_IMP_BLENDER_SPEC(BLENDER_SPEC) \ 69 T, BLENDER_SPEC< T, CS, CHMIN, CHMAX, has_omap >, CS, CHMIN, CHMAX, has_imap, has_omap, PREVIEW 70 71 72 #define OP_TEMPLATE_DEF_TYPE_SPEC \ 73 class BLENDER, PF::colorspace_t CS, int CHMIN, int CHMAX, \ 74 bool has_imap, bool has_omap, bool PREVIEW 75 76 #define OP_TEMPLATE_IMP_TYPE_SPEC(TYPE_SPEC) \ 77 TYPE_SPEC, BLENDER, CS, CHMIN, CHMAX, has_imap, has_omap, PREVIEW 78 79 80 #define OP_TEMPLATE_DEF_CS_SPEC \ 81 typename T, class BLENDER, int CHMIN, int CHMAX, \ 82 bool has_imap, bool has_omap, bool PREVIEW 83 84 #define OP_TEMPLATE_IMP_CS_SPEC(CS_SPEC) \ 85 T, BLENDER, CS_SPEC, CHMIN, CHMAX, has_imap, has_omap, PREVIEW 86 87 88 89 #define OP_TEMPLATE_DEF_PREVIEW_SPEC \ 90 typename T, class BLENDER, PF::colorspace_t CS, int CHMIN, int CHMAX, \ 91 bool has_imap, bool has_omap 92 93 #define OP_TEMPLATE_IMP_PREVIEW_SPEC(PREVIEW_SPEC) \ 94 T, BLENDER, CS, CHMIN, CHMAX, has_imap, has_omap, PREVIEW_SPEC 95 96 97 #define PF_OUPUT_CACHE_TS 128 98 99 100 101 namespace PF 102 { 103 104 class ProcessorBase; 105 class Layer; 106 107 template<typename T> 108 class PixelMatrix 109 { 110 T* data; 111 T** rows; 112 T** ptr; 113 int w, h, co, ro; 114 public: PixelMatrix()115 PixelMatrix(): data(NULL), w(0), h(0), ptr(NULL), rows(NULL) {} PixelMatrix(T * buf,int width,int height,int rowstride,int roffs,int coffs)116 PixelMatrix(T* buf, int width, int height, int rowstride, int roffs, int coffs): 117 data(NULL), w(width), h(height), ro(roffs), co(coffs) 118 { 119 ptr = new T*[h]; 120 rows = ptr - roffs; 121 for(int i = 0; i < height; i++) { 122 ptr[i] = buf - coffs; 123 buf += rowstride; 124 } 125 //std::cout<<"Initialized pixel matrix from buf="<<buf<<" "<<w<<"x"<<h<<"+"<<coffs<<","<<roffs<<std::endl; 126 } PixelMatrix(int width,int height,int roffs=0,int coffs=0)127 PixelMatrix(int width, int height, int roffs=0, int coffs=0): 128 data(NULL), w(width), h(height), ro(roffs), co(coffs), ptr(NULL), rows(NULL) 129 { 130 data = new T[w*h]; 131 int rowstride = w; 132 T* buf = data; 133 ptr = new T*[h]; 134 rows = ptr - roffs; 135 for(int i = 0; i < height; i++) { 136 ptr[i] = buf - coffs; 137 buf += rowstride; 138 } 139 //std::cout<<"Initialized pixel matrix "<<w<<"x"<<h<<"+"<<coffs<<","<<roffs<<std::endl; 140 } PixelMatrix(const PixelMatrix & m)141 PixelMatrix(const PixelMatrix& m): 142 data(NULL), w(0), h(0) 143 { 144 w = m.width(); 145 h = m.height(); 146 ro = m.roffs(); 147 co = m.coffs(); 148 data = new T[w*h]; 149 int rowstride = w; 150 T* buf = data; 151 ptr = new T*[h]; 152 rows = ptr - ro; 153 for(int i = 0; i < h; i++) { 154 ptr[i] = buf - co; 155 memcpy(buf, m[i] + co, sizeof(T)*w); 156 buf += rowstride; 157 } 158 //std::cout<<"Initialized pixel matrix "<<w<<"x"<<h<<"+"<<coffs<<","<<roffs<<std::endl; 159 } ~PixelMatrix()160 ~PixelMatrix() 161 { 162 if(data) delete[] data; 163 if(ptr) delete[] ptr; 164 } 165 operator =(const PixelMatrix & m)166 PixelMatrix& operator =(const PixelMatrix& m) 167 { 168 if(data) delete[] data; 169 if(ptr) delete[] ptr; 170 171 w = m.width(); 172 h = m.height(); 173 ro = m.roffs(); 174 co = m.coffs(); 175 data = new T[w*h]; 176 int rowstride = w; 177 T* buf = data; 178 ptr = new T*[h]; 179 rows = ptr - ro; 180 for(int i = 0; i < h; i++) { 181 ptr[i] = buf - co; 182 memcpy(buf, m[i] + co, sizeof(T)*w); 183 buf += rowstride; 184 } 185 186 return(*this); 187 //std::cout<<"Initialized pixel matrix "<<w<<"x"<<h<<"+"<<coffs<<","<<roffs<<std::endl; 188 } 189 resize(int width,int height,int roffs=0,int coffs=0)190 void resize(int width, int height, int roffs=0, int coffs=0) 191 { 192 if(data) delete[] data; 193 if(ptr) delete[] ptr; 194 195 w = width; 196 h = height; 197 ro = roffs; 198 co = coffs; 199 data = new T[w*h]; 200 int rowstride = w; 201 T* buf = data; 202 ptr = new T*[h]; 203 rows = ptr - roffs; 204 for(int i = 0; i < height; i++) { 205 ptr[i] = buf - coffs; 206 buf += rowstride; 207 } 208 //std::cout<<"Initialized pixel matrix "<<w<<"x"<<h<<"+"<<coffs<<","<<roffs<<std::endl; 209 } 210 211 // use as pointer to T** operator T**()212 operator T**() { return rows; } get_rows()213 T** get_rows() { return rows; } operator [](int id) const214 T* operator[](int id) const { return rows[id]; } width() const215 int width() const { return w; } height() const216 int height() const { return h; } roffs() const217 int roffs() const { return ro; } coffs() const218 int coffs() const { return co; } 219 }; 220 221 222 223 224 class OperationConfigUI 225 { 226 std::list<std::string> initial_params; 227 228 Layer* layer; 229 230 public: 231 OperationConfigUI(Layer * l)232 OperationConfigUI( Layer* l ): layer( l ) {} ~OperationConfigUI()233 virtual ~OperationConfigUI() {} 234 get_layer()235 Layer* get_layer() { return layer; } 236 //void set_layer( Layer* l ) { layer = l; } 237 238 virtual void open() = 0; 239 virtual void init() = 0; 240 virtual void update() = 0; do_update()241 virtual void do_update() { update(); } 242 virtual void update_properties() = 0; 243 }; 244 245 /* Base class for all operation parameter implementations 246 */ 247 class OpParBase: public sigc::trackable 248 { 249 VipsDemandStyle demand_hint; 250 251 std::string type; 252 253 ProcessorBase* processor; 254 ProcessorBase* to_map; 255 256 OperationConfigUI* config_ui; 257 258 // Requested image fields 259 int xsize; 260 int ysize; 261 int bands; 262 VipsBandFormat format; 263 VipsCoding coding; 264 VipsInterpretation interpretation; 265 266 // Padding required by the operation when processing input images 267 std::vector<int> input_paddings; 268 // Total padding requested to the output of the operation by all the 269 // child operations in the pipeline 270 std::vector<int> output_paddings; 271 bool output_caching_enabled; 272 273 rendermode_t render_mode; 274 275 bool map_flag; 276 277 bool editing_flag; 278 279 bool modified_flag; 280 281 std::string default_name; 282 283 std::list<PropertyBase*> mapped_properties; 284 std::list<PropertyBase*> properties; 285 286 Property<float> intensity; 287 288 PropertyBase grey_target_channel; 289 PropertyBase rgb_target_channel; 290 PropertyBase lab_target_channel; 291 PropertyBase cmyk_target_channel; 292 293 Property<bool> mask_enabled; 294 295 int file_format_version; 296 297 Property<bool> enable_padding; 298 int test_padding; 299 300 public: 301 sigc::signal<void> signal_modified; 302 303 OpParBase(); 304 virtual ~OpParBase(); 305 get_type()306 std::string get_type() { return type; } set_type(std::string str)307 void set_type( std::string str ) { type = str; } 308 get_properties()309 std::list<PropertyBase*>& get_properties() { return properties; } get_mapped_properties()310 std::list<PropertyBase*>& get_mapped_properties() { return mapped_properties; } add_property(PropertyBase * p)311 void add_property( PropertyBase* p ) 312 { 313 properties.push_back(p); 314 p->signal_modified.connect(sigc::mem_fun(this, &OpParBase::modified) ); 315 } map_property(PropertyBase * p)316 void map_property( PropertyBase* p ) { 317 if( p->is_internal() ) 318 return; 319 mapped_properties.push_back(p); 320 p->signal_modified.connect(sigc::mem_fun(this, &OpParBase::modified) ); 321 } map_properties(std::list<PropertyBase * > pl)322 void map_properties( std::list<PropertyBase*> pl ) 323 { 324 mapped_properties.insert( mapped_properties.end(), 325 pl.begin(), pl.end() ); 326 for( std::list<PropertyBase*>::iterator i = pl.begin(); 327 i != pl.end(); i++ ) 328 (*i)->signal_modified.connect(sigc::mem_fun(this, &OpParBase::modified) ); 329 } 330 void save_properties(std::list<std::string>& plist); 331 void restore_properties(const std::list<std::string>& plist); 332 set_property(std::string pname,const T & newval)333 template<typename T> bool set_property(std::string pname, const T& newval) 334 { 335 PF::PropertyBase* prop = get_property(pname); 336 if( !prop ) return false; 337 prop->update( newval ); 338 return true; 339 } 340 341 342 virtual bool import_settings( OpParBase* pin ); 343 // update properties of sub-operations propagate_settings()344 virtual void propagate_settings() {} 345 set_processor(ProcessorBase * p)346 void set_processor(ProcessorBase* p) { processor = p; } get_processor()347 ProcessorBase* get_processor() { return processor; } 348 set_demand_hint(VipsDemandStyle val)349 void set_demand_hint(VipsDemandStyle val) { demand_hint = val; } get_demand_hint()350 VipsDemandStyle get_demand_hint() { return demand_hint; } 351 set_intensity(float val)352 void set_intensity(float val) { intensity.set(val); } get_intensity()353 float get_intensity() { return intensity.get(); } 354 is_map()355 bool is_map() { return map_flag; } set_map_flag(bool flag)356 void set_map_flag( bool flag ) { map_flag = flag; } 357 is_editing_locked()358 virtual bool is_editing_locked() { return false; } is_editing()359 bool is_editing() { return( editing_flag || is_editing_locked() ); } set_editing_flag(bool flag)360 void set_editing_flag( bool flag ) { editing_flag = flag; } 361 get_mask_enabled()362 bool get_mask_enabled() { return mask_enabled.get(); } set_mask_enabled(bool val)363 void set_mask_enabled( bool val ) { mask_enabled.update(val); } 364 convert_inputs_on_map_build()365 virtual bool convert_inputs_on_map_build() { return true; } 366 is_modified()367 bool is_modified() { return modified_flag; } set_modified()368 void set_modified() { modified_flag = true; } 369 void clear_modified(); 370 virtual void modified(); 371 372 get_default_name()373 std::string get_default_name() { return default_name; } set_default_name(std::string n)374 void set_default_name( std::string n ) { default_name = n; } 375 set_file_format_version(int v)376 void set_file_format_version(int v) { file_format_version = v; } get_file_format_version()377 int get_file_format_version() { return file_format_version; } 378 379 get_rgb_target_channel()380 int get_rgb_target_channel() 381 { 382 if( !(rgb_target_channel.get_enum_value().second.first.empty()) ) 383 return( rgb_target_channel.get_enum_value().first ); 384 else 385 return -1; 386 } 387 get_lab_target_channel()388 int get_lab_target_channel() 389 { 390 if( !(lab_target_channel.get_enum_value().second.first.empty()) ) 391 return( lab_target_channel.get_enum_value().first ); 392 else 393 return -1; 394 } 395 get_cmyk_target_channel()396 int get_cmyk_target_channel() 397 { 398 if( !(cmyk_target_channel.get_enum_value().second.first.empty()) ) 399 return( cmyk_target_channel.get_enum_value().first ); 400 else 401 return -1; 402 } 403 404 /* Function to derive the output area from the input area 405 */ transform(const VipsRect * rin,VipsRect * rout,int)406 virtual void transform(const VipsRect* rin, VipsRect* rout, int /*id*/) 407 { 408 int p = enable_padding.get() ? test_padding : 0; 409 rout->left = rin->left+p; 410 rout->top = rin->top+p; 411 rout->width = rin->width-p*2; 412 rout->height = rin->height-p*2; 413 } 414 415 /* Function to derive the area to be read from input images, 416 based on the requested output area 417 */ transform_inv(const VipsRect * rout,VipsRect * rin,int)418 virtual void transform_inv(const VipsRect* rout, VipsRect* rin, int /*id*/) 419 { 420 int p = enable_padding.get() ? test_padding : 0; 421 rin->left = rout->left-p; 422 rin->top = rout->top-p; 423 rin->width = rout->width+p*2; 424 rin->height = rout->height+p*2; 425 } 426 427 has_intensity()428 virtual bool has_intensity() { return true; } has_opacity()429 virtual bool has_opacity() { return true; } has_target_channel()430 virtual bool has_target_channel() { return false; } needs_input()431 virtual bool needs_input() { return true; } needs_caching()432 virtual bool needs_caching() { return false; } init_hidden()433 virtual bool init_hidden() { return false; } 434 435 // whether the operation returns an input image at a given zoom level 436 // id is the output image index is_noop(VipsImage * full_res,unsigned int id,unsigned int level)437 virtual bool is_noop( VipsImage* full_res, unsigned int id, unsigned int level ) 438 { 439 return false; 440 } 441 virtual void compute_padding( VipsImage* full_res, unsigned int id, unsigned int level ); set_padding(int p,unsigned int id)442 void set_padding( int p, unsigned int id ) 443 { 444 for( unsigned int i = input_paddings.size(); i <= id; i++ ) input_paddings.push_back(0); 445 input_paddings[id] = p; 446 } get_padding(unsigned int id=0)447 int get_padding( unsigned int id = 0 ) 448 { 449 return( (input_paddings.size()>id) ? input_paddings[id] : 0 ); 450 } get_output_padding(unsigned int id=0)451 int get_output_padding( unsigned int id = 0 ) 452 { 453 return( (output_paddings.size()>id) ? output_paddings[id] : 0 ); 454 } set_output_padding(int p,unsigned int id=0)455 bool set_output_padding( int p, unsigned int id = 0 ) 456 { 457 for( unsigned int i = output_paddings.size(); i <= id; i++ ) output_paddings.push_back(0); 458 if( output_paddings[id] < p ) { 459 output_paddings[id] = p; 460 return true; 461 } 462 return false; 463 } reset_output_padding()464 void reset_output_padding() { output_paddings.clear(); } set_output_caching(bool flag)465 void set_output_caching(bool flag) { output_caching_enabled = flag; } get_output_caching()466 bool get_output_caching() { return output_caching_enabled; } get_test_padding()467 virtual int get_test_padding() { return 0; } 468 469 // get the real zoom level for a given requested level get_real_level(unsigned int level)470 virtual unsigned int get_real_level(unsigned int level) { return level; } 471 // when the image is built at a zoom level different from the requested one, 472 // wether the image should be shrunk during the blending phasse or not do_shirnk_on_blend()473 virtual bool do_shirnk_on_blend() { return false; } 474 475 // return the number of output images. Equal to 1 in most cases get_output_num()476 virtual int get_output_num() { return 1; } 477 get_render_mode()478 rendermode_t get_render_mode() { return render_mode; } set_render_mode(rendermode_t m)479 void set_render_mode(rendermode_t m) { render_mode = m; } 480 481 // called after all properties have been loaded from .pfi file finalize()482 virtual void finalize() {} 483 pre_build(rendermode_t)484 virtual void pre_build( rendermode_t /*mode*/ ) {} 485 486 virtual VipsImage* build(std::vector<VipsImage*>& in, int first, 487 VipsImage* imap, VipsImage* omap, unsigned int& level); 488 virtual std::vector<VipsImage*> build_many(std::vector<VipsImage*>& in, int first, 489 VipsImage* imap, VipsImage* omap, unsigned int& level); 490 std::vector<VipsImage*> build_many_internal(std::vector<VipsImage*>& in, int first, 491 VipsImage* imap, VipsImage* omap, unsigned int& level); 492 virtual void fill_image_hierarchy(std::vector<VipsImage*>& in, 493 VipsImage* imap, VipsImage* omap, std::vector<VipsImage*>& out); 494 495 496 PropertyBase* get_property(std::string name); 497 set_property_value(std::string name,const T & newval)498 template<typename T> bool set_property_value(std::string name, const T& newval) 499 { 500 PropertyBase* prop = get_property(name); 501 if( !prop ) return false; 502 prop->update( newval ); 503 return true; 504 } 505 506 507 get_config_ui()508 OperationConfigUI* get_config_ui() { return config_ui; } set_config_ui(OperationConfigUI * ui)509 void set_config_ui( OperationConfigUI* ui ) { config_ui = ui; } 510 set_image_dimensions(int w,int h)511 void set_image_dimensions(int w, int h) 512 { 513 xsize = w; ysize = h; 514 } get_xsize()515 int get_xsize() { return xsize; } get_ysize()516 int get_ysize() { return ysize; } get_nbands()517 int get_nbands() { return bands; } set_nbands(int n)518 void set_nbands( int n ) { bands = n; } get_interpretation()519 VipsInterpretation get_interpretation() { return interpretation; } get_colorspace()520 colorspace_t get_colorspace() { return( PF::convert_colorspace( get_interpretation() ) ); } accepts_colorspace(colorspace_t)521 virtual bool accepts_colorspace(colorspace_t) { return true; } get_format()522 VipsBandFormat get_format() { return format; } set_format(VipsBandFormat fmt)523 virtual void set_format( VipsBandFormat fmt ) { format = fmt; } get_coding()524 VipsCoding get_coding() { return coding; } set_coding(VipsCoding c)525 void set_coding( VipsCoding c ) { coding = c; } 526 set_image_hints(OpParBase * op)527 virtual void set_image_hints( OpParBase* op ) 528 { 529 if( !op ) return; 530 set_image_hints( op->get_xsize(), op->get_ysize(), 531 op->get_interpretation() ); 532 bands = op->get_nbands(); 533 rgb_target_channel.set_enum_value(op->get_rgb_target_channel()); 534 lab_target_channel.set_enum_value(op->get_lab_target_channel()); 535 cmyk_target_channel.set_enum_value(op->get_cmyk_target_channel()); 536 set_demand_hint( op->get_demand_hint() ); 537 set_map_flag( op->is_map() ); 538 set_coding( op->get_coding() ); 539 set_format( op->get_format() ); 540 set_render_mode( op->get_render_mode() ); 541 } 542 set_image_hints(VipsImage * img)543 virtual void set_image_hints( VipsImage* img ) 544 { 545 if( !img ) return; 546 set_image_hints( img->Xsize, img->Ysize, 547 img->Type ); 548 bands = img->Bands; 549 } 550 551 void set_image_hints(int w, int h, VipsInterpretation interpr); 552 void set_image_hints(int w, int h, colorspace_t cs); 553 grayscale_image(int w,int h)554 void grayscale_image(int w, int h) 555 { 556 xsize = w; ysize = h; 557 bands = 1; interpretation = VIPS_INTERPRETATION_B_W; 558 coding = VIPS_CODING_NONE; 559 } 560 rgb_image(int w,int h)561 void rgb_image(int w, int h) 562 { 563 xsize = w; ysize = h; 564 bands = 3; interpretation = VIPS_INTERPRETATION_RGB; 565 coding = VIPS_CODING_NONE; 566 } 567 lab_image(int w,int h)568 void lab_image(int w, int h) 569 { 570 xsize = w; ysize = h; 571 bands = 3; interpretation = VIPS_INTERPRETATION_LAB; 572 coding = VIPS_CODING_NONE; 573 } 574 cmyk_image(int w,int h)575 void cmyk_image(int w, int h) 576 { 577 xsize = w; ysize = h; 578 bands = 4; interpretation = VIPS_INTERPRETATION_CMYK; 579 coding = VIPS_CODING_NONE; 580 } 581 multiband_image(int w,int h,int b)582 void multiband_image(int w, int h, int b) 583 { 584 xsize = w; ysize = h; 585 bands = b; interpretation = VIPS_INTERPRETATION_MULTIBAND; 586 coding = VIPS_CODING_NONE; 587 } 588 print()589 virtual void print() {} 590 bool save( std::ostream& ostr, int level ); 591 }; 592 593 594 /* Base parameters for all transform operations 595 * 596 * A transform operation can only replace the input image, 597 * (ex. icc transform or image rescaling), so intensity or opacity maps are useless 598 */ 599 class OpParTransform: public OpParBase 600 { 601 public: has_intensity()602 virtual bool has_intensity() { return false; } has_opacity()603 virtual bool has_opacity() { return false; } 604 }; 605 606 607 608 template<class T, bool has_imap> 609 class IntensityProc 610 { 611 public: get_intensity(float & intensity,T * & p,int & x)612 float get_intensity(float& intensity, T*& p, int& x) 613 { 614 //std::cout<<"IntensityProc<T,true>::get_intensity(): "<<(intensity*p[x]/(FormatInfo<T>::MAX-FormatInfo<T>::MIN))<<std::endl; 615 return(intensity*(p[x++]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE)); 616 } 617 }; 618 619 620 621 template<class T> 622 class IntensityProc<T,false> 623 { 624 public: get_intensity(float & intensity,T * &,int &)625 float get_intensity(float& intensity, T*& /*p*/, int& /*x*/) 626 { 627 //std::cout<<"IntensityProc<T,false>::get_intensity()"<<std::endl; 628 return(intensity); 629 } 630 }; 631 632 633 634 template<typename T, colorspace_t colorspace, int CHMIN, int CHMAX, bool has_omap> 635 class BlendBase 636 { 637 public: 638 T* pmap; init_line(VipsRegion * omap,int left,int top)639 void init_line(VipsRegion* omap, int left, int top) { pmap = (T*)VIPS_REGION_ADDR( omap, left, top ); } 640 }; 641 642 643 template<typename T, colorspace_t colorspace, int CHMIN, int CHMAX > 644 class BlendBase<T, colorspace, CHMIN, CHMAX, false> 645 { 646 public: 647 T* pmap; init_line(VipsRegion *,int,int)648 void init_line(VipsRegion* /*omap*/, int /*left*/, int /*top*/) { } 649 }; 650 651 652 653 654 #include "blend_passthrough.hh" 655 #include "blend_normal.hh" 656 #include "blend_add.hh" 657 #include "blend_subtract.hh" 658 #include "blend_grain_extract.hh" 659 #include "blend_grain_merge.hh" 660 #include "blend_multiply.hh" 661 #include "blend_divide.hh" 662 #include "blend_screen.hh" 663 #include "blend_lighten.hh" 664 #include "blend_darken.hh" 665 #include "blend_overlay.hh" 666 #include "blend_soft_light.hh" 667 #include "blend_hard_light.hh" 668 #include "blend_vivid_light.hh" 669 #include "blend_luminosity.hh" 670 #include "blend_luminance.hh" 671 #include "blend_color.hh" 672 #include "blend_exclusion.hh" 673 #include "blend_lch.hh" 674 675 int vips_copy_metadata( VipsImage* in, VipsImage* out ); 676 677 void print_embedded_profile( VipsImage* img ); 678 }; 679 680 681 //int vips_pflayer( VipsImage **in, VipsImage* imap, VipsImage* omap, VipsImage **out, int n, 682 // PF::OperationBase* op, ... ); 683 684 685 #endif 686