1 /*
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 #include <lcms2.h>
31
32 #include "file_util.hh"
33 #include "operation.hh"
34 #include "layer.hh"
35 #include "../operations/image_to_map.hh"
36 //#include "../vips/vips_layer.h"
37
38 static int _phf_operation_serial_id = 0;
39
40 int
41 vips_layer( int n, VipsImage **out,
42 PF::ProcessorBase* proc,
43 VipsImage* imap, VipsImage* omap,
44 VipsDemandStyle demand_hint,
45 int width, int height, int nbands, int sid, ... );
46
47
48
49
50
open()51 void PF::OperationConfigUI::open()
52 {
53 get_layer()->get_processor()->get_par()->save_properties(initial_params);
54 }
55
56
57
58
OpParBase()59 PF::OpParBase::OpParBase(): output_caching_enabled(false),
60 render_mode(PF_RENDER_PREVIEW),
61 map_flag( false ),
62 editing_flag( false ),
63 modified_flag(false),
64 intensity("intensity",this,1),
65 grey_target_channel("grey_target_channel",this,-1,"Grey","Grey"),
66 rgb_target_channel("rgb_target_channel",this,-1,"RGB","RGB"),
67 lab_target_channel("lab_target_channel",this,-1,"Lab","Lab"),
68 cmyk_target_channel("cmyk_target_channel",this,-1,"CMYK","CMYK"),
69 mask_enabled("mask_enabled",this,true),
70 file_format_version( PF_FILE_VERSION ),
71 enable_padding( "enable_padding", this, false ), test_padding(64)
72 {
73 //blend_mode.set_internal(true);
74 intensity.set_internal(true);
75 //opacity.set_internal(true);
76 grey_target_channel.set_internal(true);
77 rgb_target_channel.set_internal(true);
78 lab_target_channel.set_internal(true);
79 cmyk_target_channel.set_internal(true);
80
81 processor = NULL;
82 //out = NULL;
83 config_ui = NULL;
84 //blend_mode = PF_BLEND_PASSTHROUGH;
85 //blend_mode = PF_BLEND_NORMAL;
86 //blend_mode.set_enum_value( PF_BLEND_PASSTHROUGH );
87 demand_hint = VIPS_DEMAND_STYLE_ANY;
88 bands = 1;
89 xsize = 100; ysize = 100;
90
91 rgb_target_channel.add_enum_value(0,"R","R");
92 rgb_target_channel.add_enum_value(1,"G","G");
93 rgb_target_channel.add_enum_value(2,"B","B");
94
95 lab_target_channel.add_enum_value(0,"L","L");
96 lab_target_channel.add_enum_value(1,"a","a");
97 lab_target_channel.add_enum_value(2,"b","b");
98
99 cmyk_target_channel.add_enum_value(0,"C","C");
100 cmyk_target_channel.add_enum_value(1,"M","M");
101 cmyk_target_channel.add_enum_value(2,"Y","Y");
102 cmyk_target_channel.add_enum_value(3,"K","K");
103
104 to_map = NULL;
105
106 //PF::PropertyBase* prop;
107 //prop = new PF::Property<float>("intensity",&intensity);
108 }
109
110
111
~OpParBase()112 PF::OpParBase::~OpParBase()
113 {
114 //for(unsigned int i = 0; i < outvec.size(); i++ ) {
115 // PF_UNREF( outvec[i], "~OpParBase(): previous outputs unref" );
116 //}
117 //#ifndef NDEBUG
118 //std::cout<<"~OpParBase(): deleting operation "<<(void*)this<<" ("<<get_type()<<")"<<std::endl;
119 //#endif
120 }
121
122
123
get_property(std::string name)124 PF::PropertyBase* PF::OpParBase::get_property(std::string name)
125 {
126 std::list<PropertyBase*>::iterator pi;
127
128 // Look into mapped properties first
129 for(pi = mapped_properties.begin(); pi != mapped_properties.end(); pi++) {
130 //std::cout<<"(*pi)->get_name(): "<<(*pi)->get_name()<<" name: "<<name<<std::endl;
131 if( (*pi)->get_name() == name ) return( *pi );
132 }
133
134 // If nothing is found, look into our own properties
135 for(pi = properties.begin(); pi != properties.end(); pi++) {
136 //std::cout<<"(*pi)->get_name(): "<<(*pi)->get_name()<<" name: "<<name<<std::endl;
137 if( (*pi)->get_name() == name ) return( *pi );
138 }
139 return NULL;
140 }
141
142
save_properties(std::list<std::string> & plist)143 void PF::OpParBase::save_properties(std::list<std::string>& plist)
144 {
145 std::list<PropertyBase*>::iterator pi;
146 for(pi = mapped_properties.begin(); pi != mapped_properties.end(); pi++) {
147 std::string str = (*pi)->get_str();
148 plist.push_back(str);
149 }
150 for(pi = properties.begin(); pi != properties.end(); pi++) {
151 std::string str = (*pi)->get_str();
152 plist.push_back(str);
153 }
154 }
155
156
restore_properties(const std::list<std::string> & plist)157 void PF::OpParBase::restore_properties(const std::list<std::string>& plist)
158 {
159 std::list<PropertyBase*>::iterator pi;
160 std::list<std::string>::const_iterator si;
161 for(pi = mapped_properties.begin(), si = plist.begin();
162 (pi != mapped_properties.end()) && (si != plist.end());
163 pi++, si++) {
164 (*pi)->set_str(*si);
165 }
166 for(pi = properties.begin();
167 (pi != properties.end()) && (si != plist.end());
168 pi++, si++) {
169 (*pi)->set_str(*si);
170 }
171 }
172
173
compute_padding(VipsImage * full_res,unsigned int id,unsigned int level)174 void PF::OpParBase::compute_padding( VipsImage* full_res, unsigned int id, unsigned int level )
175 {
176 int p = enable_padding.get() ? test_padding : 0;
177 set_padding( p, id );
178 }
179
180
modified()181 void PF::OpParBase::modified()
182 {
183 //std::cout<<"OpParBase::modified() called for "<<type<<std::endl;
184 set_modified();
185 //std::cout<<"OpParBase::modified(): emitting signal_modified."<<std::endl;
186 signal_modified.emit();
187 //std::cout<<"OpParBase::modified(): signal_modified emitted."<<std::endl;
188 }
189
190
clear_modified()191 void PF::OpParBase::clear_modified()
192 {
193 modified_flag = false;
194 std::list<PropertyBase*>::iterator pi;
195 for(pi = mapped_properties.begin();
196 pi != mapped_properties.end();
197 pi++) {
198 (*pi)->clear_modified();
199 }
200 for(pi = properties.begin();
201 pi != properties.end();
202 pi++) {
203 (*pi)->clear_modified();
204 }
205 }
206
set_image_hints(int w,int h,VipsInterpretation interpr)207 void PF::OpParBase::set_image_hints(int w, int h, VipsInterpretation interpr)
208 {
209 xsize = w;
210 ysize = h;
211 coding = VIPS_CODING_NONE;
212 interpretation = interpr;
213 }
214
215
216
set_image_hints(int w,int h,colorspace_t cs)217 void PF::OpParBase::set_image_hints(int w, int h, colorspace_t cs)
218 {
219 xsize = w;
220 ysize = h;
221 coding = VIPS_CODING_NONE;
222 switch(cs) {
223 case PF_COLORSPACE_GRAYSCALE:
224 interpretation = VIPS_INTERPRETATION_B_W; break;
225 case PF_COLORSPACE_RGB:
226 interpretation = VIPS_INTERPRETATION_RGB; break;
227 case PF_COLORSPACE_LAB:
228 interpretation = VIPS_INTERPRETATION_LAB; break;
229 case PF_COLORSPACE_CMYK:
230 interpretation = VIPS_INTERPRETATION_CMYK; break;
231 default:
232 interpretation = VIPS_INTERPRETATION_MULTIBAND; break;
233 }
234 }
235
236
import_settings(OpParBase * pin)237 bool PF::OpParBase::import_settings( OpParBase* pin )
238 {
239 if( !pin ) {
240 std::cout<<"OpParBase::import_settings(): pin = NULL"<<std::endl;
241 return false;
242 }
243
244 std::list<PropertyBase*>& propin = pin->get_properties();
245 std::list<PropertyBase*>::iterator pi=propin.begin(), pj=properties.begin();
246 for( ; pi != propin.end(); pi++, pj++ ) {
247 if( !(*pj)->import( *pi ) ) {
248 std::cout<<"OpParBase::import_settings(): failed to import values for property \""<<(*pj)->get_name()<<"\""<<std::endl;
249 return false;
250 }
251 //std::cout<<"OpParBase::import_settings(): property \""<<(*pj)->get_name()<<"\" se to "<<(*pj)->get_str()<<std::endl;
252 }
253
254 std::list<PropertyBase*>& mpropin = pin->get_mapped_properties();
255 std::list<PropertyBase*>::iterator mpi=mpropin.begin(), mpj=mapped_properties.begin();
256 for( ; mpi != mpropin.end(); mpi++, mpj++ ) {
257 if( !(*mpj)->import( *mpi ) ) {
258 std::cout<<"OpParBase::import_settings(): failed to import values for property \""<<(*mpj)->get_name()<<"\""<<std::endl;
259 return false;
260 }
261 }
262
263 // update properties of sub-operations
264 propagate_settings();
265
266 set_map_flag( pin->is_map() );
267 //std::cout<<"OpParBase["<<get_type()<<"]::import_settings(): set_editing_flag("<<pin->is_editing()<<")"<<std::endl;
268 set_editing_flag( pin->is_editing() );
269 //set_demand_hint( pin->get_demand_hint() );
270 //set_image_hints( pin->get_xsize(), pin->get_ysize(),
271 // pin->get_interpretation() );
272 //set_nbands( pin->get_nbands() );
273 //set_coding( pin->get_coding() );
274 //set_format( pin->get_format() );
275 return true;
276 }
277
278
build(std::vector<VipsImage * > & in,int first,VipsImage * imap,VipsImage * omap,unsigned int & level)279 VipsImage* PF::OpParBase::build(std::vector<VipsImage*>& in, int first,
280 VipsImage* imap, VipsImage* omap, unsigned int& level)
281 {
282 VipsImage* outnew = NULL;
283 VipsImage* invec[100];
284 unsigned int n = 0;
285 for(unsigned int i = 0; i < in.size(); i++) {
286 if( !in[i] ) continue;
287 invec[n] = in[i];
288 n++;
289 }
290 if(n > 100) n = 100;
291 #ifndef NDEBUG
292 //std::cout<<"OpParBase::build("<<get_type()<<"): size = "<<get_xsize()<<"x"<<get_ysize()<<std::endl;
293 std::cout<<"OpParBase::build("<<get_type()<<"): in.size()="<<in.size()<<" n="<<n<<std::endl;
294 #endif
295 if( _phf_operation_serial_id == 0xFFFFFFF ) _phf_operation_serial_id = 0;
296 else _phf_operation_serial_id += 1;
297 switch( n ) {
298 case 0:
299 vips_layer( n, &outnew, processor, imap, omap,
300 get_demand_hint(), get_xsize(), get_ysize(), get_nbands(), _phf_operation_serial_id,
301 NULL );
302 break;
303 case 1:
304 vips_layer( n, &outnew, processor, imap, omap,
305 get_demand_hint(), get_xsize(), get_ysize(), get_nbands(), _phf_operation_serial_id,
306 "in0", invec[0], NULL );
307 break;
308 case 2:
309 vips_layer( n, &outnew, processor, imap, omap,
310 get_demand_hint(), get_xsize(), get_ysize(), get_nbands(), _phf_operation_serial_id,
311 "in0", invec[0], "in1", invec[1], NULL );
312 break;
313 case 3:
314 vips_layer( n, &outnew, processor, imap, omap,
315 get_demand_hint(), get_xsize(), get_ysize(), get_nbands(), _phf_operation_serial_id,
316 "in0", invec[0], "in1", invec[1],
317 "in2", invec[2], NULL );
318 break;
319 case 4:
320 vips_layer( n, &outnew, processor, imap, omap,
321 get_demand_hint(), get_xsize(), get_ysize(), get_nbands(), _phf_operation_serial_id,
322 "in0", invec[0], "in1", invec[1],
323 "in2", invec[2], "in3", invec[3], NULL );
324 break;
325 default:
326 break;
327 }
328
329 #ifndef NDEBUG
330 std::cout<<"OpParBase::build(): type="<<type<<" format="<<get_format()<<std::endl
331 <<"input images:"<<std::endl;
332 for(int i = 0; i < n; i++) {
333 std::cout<<" "<<(void*)invec[i]<<" ref_count="<<G_OBJECT( invec[i] )->ref_count<<std::endl;
334 }
335 std::cout<<"imap: "<<(void*)imap<<std::endl<<"omap: "<<(void*)omap<<std::endl;
336 std::cout<<"out: "<<(void*)outnew<<std::endl<<std::endl;
337 #endif
338
339 //set_image( outnew );
340 #ifndef NDEBUG
341 std::cout<<"OpParBase::build(): outnew refcount ("<<(void*)outnew<<") = "<<G_OBJECT(outnew)->ref_count<<std::endl;
342 #endif
343 return outnew;
344 }
345
346
347
build_many(std::vector<VipsImage * > & in,int first,VipsImage * imap,VipsImage * omap,unsigned int & level)348 std::vector<VipsImage*> PF::OpParBase::build_many(std::vector<VipsImage*>& in, int first,
349 VipsImage* imap, VipsImage* omap, unsigned int& level)
350 {
351 std::vector<VipsImage*> result;
352 VipsImage* out = build( in, first, imap, omap, level );
353 //std::cout<<"OpParBase::build_many(): padding="<<get_padding()<<std::endl;
354
355 VipsImage* cached = out;
356 /*
357 if( out && false && needs_caching() ) {
358 int tw = 64, th = 64;
359 // reserve two complete rows of tiles
360 int nt = out->Xsize*2/tw;
361 VipsAccess acc = VIPS_ACCESS_RANDOM;
362 int threaded = 1, persistent = 0;
363
364 if( vips_tilecache(out, &cached,
365 "tile_width", tw, "tile_height", th, "max_tiles", nt,
366 "access", acc, "threaded", threaded, "persistent", persistent, NULL) ) {
367 std::cout<<"GaussBlurPar::build(): vips_tilecache() failed."<<std::endl;
368 return result;
369 }
370 PF_UNREF( out, "OpParBase::build_many(): out unref" );
371 }
372 */
373 result.push_back( cached );
374 return result;
375 }
376
377
build_many_internal(std::vector<VipsImage * > & in,int first,VipsImage * imap,VipsImage * omap,unsigned int & level)378 std::vector<VipsImage*> PF::OpParBase::build_many_internal(std::vector<VipsImage*>& in, int first,
379 VipsImage* imap, VipsImage* omap, unsigned int& level)
380 {
381 std::vector<VipsImage*> in_temp;
382
383 if( true && convert_inputs_on_map_build() && is_map() && interpretation == VIPS_INTERPRETATION_B_W ) {
384 if( !to_map ) to_map = new_image_to_map();
385 std::vector<VipsImage*> in_temp2;
386 std::vector<VipsImage*>* in_ptr = in_temp.empty() ? &in : &in_temp;
387 for(unsigned int i = 0; i < in_ptr->size(); i++) {
388 VipsImage* img = (*in_ptr)[i];
389 if( img == NULL || img->Type == interpretation ) {
390 in_temp2.push_back(img);
391 std::cout<<"OpParBase::build_many_internal: op_type="<<get_type()<<" in_temp2.push_back("<<img<<")"<<std::endl;
392 PF_REF( img, "build_many_internal: img ref" );
393 } else {
394 std::vector<VipsImage*> in2; in2.push_back(img);
395 std::cout<<"OpParBase::build_many_internal: to_map="<<to_map<<std::endl;
396 PF::OpParBase* to_map_op = to_map->get_par();
397 to_map_op->set_format(get_format());
398 //to_map_op->set_image_hints(img);
399 //to_map_op->grayscale_image( img->Xsize, img->Ysize );
400 VipsImage* bwimg = to_map_op->build(in2, 0, NULL, NULL, level);
401 std::cout<<"OpParBase::build_many_internal: bwimg built"<<std::endl;
402 in_temp2.push_back(bwimg);
403 //PF_UNREF( img, "build_many_internal: img unref" );
404 }
405 }
406 in_temp = in_temp2;
407 }
408
409 std::vector<VipsImage*> result;
410 if( in_temp.empty() )
411 result = build_many( in, first, imap, omap, level );
412 else
413 result = build_many( in_temp, first, imap, omap, level );
414
415 #ifndef NDEBUG
416 std::cout<<"OpParBase::build_many_internal(): filling hierarchy with padding "<<get_padding()<<std::endl;
417 #endif
418 if( in_temp.empty() )
419 fill_image_hierarchy( in, imap, omap, result );
420 else
421 fill_image_hierarchy( in_temp, imap, omap, result );
422
423 // add output caching if needed
424 if( output_caching_enabled ) {
425
426 std::vector<VipsImage*> result_cached;
427 for( unsigned int i = 0; i < result.size(); i++ ) {
428 bool is_dup = false;
429 VipsImage* out = result[i];
430 for( unsigned int j = 0; j < in.size(); j++ ) {
431 if( out == in[j] ) {
432 is_dup = true;
433 break;
434 }
435 }
436 if( is_dup ) {
437 result_cached.push_back( out );
438 continue;
439 }
440
441 int p = get_output_padding( i );
442 if( p > 32 || needs_caching() ) {
443 VipsAccess acc = VIPS_ACCESS_RANDOM;
444 int threaded = 1, persistent = 1;
445 VipsImage* cached;
446 std::cout<<"OpParBase::build_many_internal(): adding tilecache for output image #"
447 <<i<<", padding="<<p<<std::endl;
448 if( !phf_tilecache(out, &cached,
449 "access", acc, "threaded", threaded,
450 "persistent", persistent, NULL) ) {
451 result_cached.push_back( cached );
452 PF_UNREF( out, "OpParBase::build_many_internal(): out unref" );
453 std::cout<<"OpParBase::build_many_internal(): added tilecache for output image #"
454 <<i<<", padding="<<p<<std::endl;
455 } else {
456 std::cout<<"OpParBase::build_many_internal(): phf_tilecache() failed."<<std::endl;
457 result_cached.push_back( out );
458 }
459 } else {
460 result_cached.push_back( out );
461 }
462 }
463 result = result_cached;
464 }
465
466 if( true && convert_inputs_on_map_build() && is_map() && interpretation == VIPS_INTERPRETATION_B_W ) {
467 std::vector<VipsImage*>* in_ptr = in_temp.empty() ? &in : &in_temp;
468 for(unsigned int i = 0; i < in_ptr->size(); i++) {
469 VipsImage* img = (*in_ptr)[i];
470 PF_UNREF( img, "build_many_internal: img unref" );
471 std::cout<<"OpParBase::build_many_internal: op_type="<<get_type()<<" "<<img<<" unref"<<std::endl;
472 }
473 }
474
475 //for(unsigned int i = 0; i < outvec.size(); i++ ) {
476 // PF_UNREF( outvec[i], "OpParBase::build_many_internal(): previous outputs unref" );
477 //}
478 //outvec = result;
479
480 return result;
481 }
482
483
fill_image_hierarchy(std::vector<VipsImage * > & in,VipsImage * imap,VipsImage * omap,std::vector<VipsImage * > & out)484 void PF::OpParBase::fill_image_hierarchy(std::vector<VipsImage*>& in,
485 VipsImage* imap, VipsImage* omap, std::vector<VipsImage*>& out)
486 {
487 for( unsigned int i = 0; i < out.size(); i++ ) {
488 bool is_dup = false;
489 for( unsigned int j = 0; j < in.size(); j++ ) {
490 if( out[i] == in[j] ) {
491 is_dup = true;
492 break;
493 }
494 }
495 if( is_dup ) continue;
496
497 #ifndef NDEBUG
498 if( get_padding() > 0 ) {
499 std::cout<<"OpParBase::fill_image_hierarchy(): filling hierarchy for image "<<i<<"("<<out[i]<<") with padding "<<get_padding()<<std::endl;
500 }
501 #endif
502 PF::image_hierarchy_fill( out[i], get_padding(), in );
503 std::vector<VipsImage*> maps;
504 if( imap ) maps.push_back(imap);
505 if( omap ) maps.push_back(omap);
506 if( !maps.empty() ) PF::image_hierarchy_fill( out[i], 0, maps );
507 }
508 }
509
510
save(std::ostream & ostr,int level)511 bool PF::OpParBase::save( std::ostream& ostr, int level )
512 {
513 for(int i = 0; i < level; i++) ostr<<" ";
514 ostr<<"<operation type=\""<<get_type()<<"\">"<<std::endl;
515
516 for( std::list<PropertyBase*>::iterator pi = properties.begin();
517 pi != properties.end(); pi++ ) {
518 if( (*pi)->is_persistent() == false ) continue;
519 std::string pvalue = (*pi)->get_str();
520 for(int i = 0; i < level+1; i++) ostr<<" ";
521 ostr<<"<property name=\""<<(*pi)->get_name()<<"\" value=\"";
522 //(*pi)->to_stream( ostr );
523 ostr<<PF::pf_escape_xml(pvalue);
524 ostr<<"\">"<<std::endl;
525 for(int i = 0; i < level+1; i++) ostr<<" ";
526 ostr<<"</property>"<<std::endl;
527 }
528
529 for( std::list<PropertyBase*>::iterator pi = mapped_properties.begin();
530 pi != mapped_properties.end(); pi++ ) {
531 if( (*pi)->is_persistent() == false ) continue;
532 std::string pvalue = (*pi)->get_str();
533 for(int i = 0; i < level+1; i++) ostr<<" ";
534 ostr<<"<property name=\""<<(*pi)->get_name()<<"\" value=\"";
535 //(*pi)->to_stream( ostr );
536 ostr<<PF::pf_escape_xml(pvalue);
537 ostr<<"\">"<<std::endl;
538 for(int i = 0; i < level+1; i++) ostr<<" ";
539 ostr<<"</property>"<<std::endl;
540 }
541
542 for(int i = 0; i < level; i++) ostr<<" ";
543 ostr<<"</operation>"<<std::endl;
544
545 return true;
546 }
547
548
vips_copy_metadata(VipsImage * in,VipsImage * out)549 int PF::vips_copy_metadata( VipsImage* in, VipsImage* out )
550 {
551 if( !out ) return 0;
552 int Xsize = out->Xsize;
553 int Ysize = out->Ysize;
554 int bands = out->Bands;
555 VipsBandFormat fmt = out->BandFmt;
556 VipsCoding coding = out->Coding;
557 VipsInterpretation type = out->Type;
558 gdouble xres = out->Xres;
559 gdouble yres = out->Yres;
560 VipsImage* invec[2] = {in, NULL};
561 vips__image_copy_fields_array( out, invec );
562 vips_image_init_fields( out,
563 Xsize, Ysize, bands, fmt,
564 coding, type, xres, yres
565 );
566 return 0;
567 }
568
569
570
print_embedded_profile(VipsImage * image)571 void PF::print_embedded_profile( VipsImage* image )
572 {
573 PF::ICCProfile* icc_data = PF::get_icc_profile( image );
574 if(icc_data) {
575 cmsHPROFILE in_profile = icc_data->get_profile();
576 if( in_profile ) {
577 char tstr[1024];
578 cmsGetProfileInfoASCII(in_profile, cmsInfoDescription, "en", "US", tstr, 1024);
579 std::cout<<"\""<<tstr<<"\", ";
580 //cmsCloseProfile( in_profile );
581 //return;
582 //} else {
583 // std::cout<<"Cannot open profile from memory."<<std::endl;
584 }
585 }
586
587 void *data;
588 size_t data_length;
589 if( !PF_VIPS_IMAGE_GET_BLOB( image, VIPS_META_ICC_NAME, &data, &data_length ) ) {
590 cmsHPROFILE in_profile = cmsOpenProfileFromMem( data, data_length );
591 if( in_profile ) {
592 char tstr[1024];
593 cmsGetProfileInfoASCII(in_profile, cmsInfoDescription, "en", "US", tstr, 1024);
594 std::cout<<"\""<<tstr<<"\""<<std::endl;
595 cmsCloseProfile( in_profile );
596 return;
597 }
598 std::cout<<"Cannot open profile from memory."<<std::endl;
599 }
600 std::cout<<"Embedded ICC profile not found."<<std::endl;
601 }
602
603
604
605
vivid_light_f(float nbottom,float ntop)606 float PF::vivid_light_f(float nbottom, float ntop)
607 {
608 //nbottom = 50.0f/255.0f;
609 //ntop = 200.0f/255.0f;
610 float nvivid;
611 if( ntop <= 0.5 )
612 nvivid = PF::color_burn( nbottom, ntop*2.0f );
613 else
614 nvivid = PF::color_dodge( nbottom, ntop*2.0f-1.0f );
615
616 //std::cout<<"vivid_light=("<<nbottom*255<<","<<ntop*255<<")="<<nvivid*255.0f<<std::endl;
617 return nvivid;
618 }
619