/*
*/
/*
Copyright (C) 2014 Ferrero Andrea
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/*
These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/
*/
#include
#include "file_util.hh"
#include "operation.hh"
#include "layer.hh"
#include "../operations/image_to_map.hh"
//#include "../vips/vips_layer.h"
static int _phf_operation_serial_id = 0;
int
vips_layer( int n, VipsImage **out,
PF::ProcessorBase* proc,
VipsImage* imap, VipsImage* omap,
VipsDemandStyle demand_hint,
int width, int height, int nbands, int sid, ... );
void PF::OperationConfigUI::open()
{
get_layer()->get_processor()->get_par()->save_properties(initial_params);
}
PF::OpParBase::OpParBase(): output_caching_enabled(false),
render_mode(PF_RENDER_PREVIEW),
map_flag( false ),
editing_flag( false ),
modified_flag(false),
intensity("intensity",this,1),
grey_target_channel("grey_target_channel",this,-1,"Grey","Grey"),
rgb_target_channel("rgb_target_channel",this,-1,"RGB","RGB"),
lab_target_channel("lab_target_channel",this,-1,"Lab","Lab"),
cmyk_target_channel("cmyk_target_channel",this,-1,"CMYK","CMYK"),
mask_enabled("mask_enabled",this,true),
file_format_version( PF_FILE_VERSION ),
enable_padding( "enable_padding", this, false ), test_padding(64)
{
//blend_mode.set_internal(true);
intensity.set_internal(true);
//opacity.set_internal(true);
grey_target_channel.set_internal(true);
rgb_target_channel.set_internal(true);
lab_target_channel.set_internal(true);
cmyk_target_channel.set_internal(true);
processor = NULL;
//out = NULL;
config_ui = NULL;
//blend_mode = PF_BLEND_PASSTHROUGH;
//blend_mode = PF_BLEND_NORMAL;
//blend_mode.set_enum_value( PF_BLEND_PASSTHROUGH );
demand_hint = VIPS_DEMAND_STYLE_ANY;
bands = 1;
xsize = 100; ysize = 100;
rgb_target_channel.add_enum_value(0,"R","R");
rgb_target_channel.add_enum_value(1,"G","G");
rgb_target_channel.add_enum_value(2,"B","B");
lab_target_channel.add_enum_value(0,"L","L");
lab_target_channel.add_enum_value(1,"a","a");
lab_target_channel.add_enum_value(2,"b","b");
cmyk_target_channel.add_enum_value(0,"C","C");
cmyk_target_channel.add_enum_value(1,"M","M");
cmyk_target_channel.add_enum_value(2,"Y","Y");
cmyk_target_channel.add_enum_value(3,"K","K");
to_map = NULL;
//PF::PropertyBase* prop;
//prop = new PF::Property("intensity",&intensity);
}
PF::OpParBase::~OpParBase()
{
//for(unsigned int i = 0; i < outvec.size(); i++ ) {
// PF_UNREF( outvec[i], "~OpParBase(): previous outputs unref" );
//}
//#ifndef NDEBUG
//std::cout<<"~OpParBase(): deleting operation "<<(void*)this<<" ("<::iterator pi;
// Look into mapped properties first
for(pi = mapped_properties.begin(); pi != mapped_properties.end(); pi++) {
//std::cout<<"(*pi)->get_name(): "<<(*pi)->get_name()<<" name: "<get_name() == name ) return( *pi );
}
// If nothing is found, look into our own properties
for(pi = properties.begin(); pi != properties.end(); pi++) {
//std::cout<<"(*pi)->get_name(): "<<(*pi)->get_name()<<" name: "<get_name() == name ) return( *pi );
}
return NULL;
}
void PF::OpParBase::save_properties(std::list& plist)
{
std::list::iterator pi;
for(pi = mapped_properties.begin(); pi != mapped_properties.end(); pi++) {
std::string str = (*pi)->get_str();
plist.push_back(str);
}
for(pi = properties.begin(); pi != properties.end(); pi++) {
std::string str = (*pi)->get_str();
plist.push_back(str);
}
}
void PF::OpParBase::restore_properties(const std::list& plist)
{
std::list::iterator pi;
std::list::const_iterator si;
for(pi = mapped_properties.begin(), si = plist.begin();
(pi != mapped_properties.end()) && (si != plist.end());
pi++, si++) {
(*pi)->set_str(*si);
}
for(pi = properties.begin();
(pi != properties.end()) && (si != plist.end());
pi++, si++) {
(*pi)->set_str(*si);
}
}
void PF::OpParBase::compute_padding( VipsImage* full_res, unsigned int id, unsigned int level )
{
int p = enable_padding.get() ? test_padding : 0;
set_padding( p, id );
}
void PF::OpParBase::modified()
{
//std::cout<<"OpParBase::modified() called for "<::iterator pi;
for(pi = mapped_properties.begin();
pi != mapped_properties.end();
pi++) {
(*pi)->clear_modified();
}
for(pi = properties.begin();
pi != properties.end();
pi++) {
(*pi)->clear_modified();
}
}
void PF::OpParBase::set_image_hints(int w, int h, VipsInterpretation interpr)
{
xsize = w;
ysize = h;
coding = VIPS_CODING_NONE;
interpretation = interpr;
}
void PF::OpParBase::set_image_hints(int w, int h, colorspace_t cs)
{
xsize = w;
ysize = h;
coding = VIPS_CODING_NONE;
switch(cs) {
case PF_COLORSPACE_GRAYSCALE:
interpretation = VIPS_INTERPRETATION_B_W; break;
case PF_COLORSPACE_RGB:
interpretation = VIPS_INTERPRETATION_RGB; break;
case PF_COLORSPACE_LAB:
interpretation = VIPS_INTERPRETATION_LAB; break;
case PF_COLORSPACE_CMYK:
interpretation = VIPS_INTERPRETATION_CMYK; break;
default:
interpretation = VIPS_INTERPRETATION_MULTIBAND; break;
}
}
bool PF::OpParBase::import_settings( OpParBase* pin )
{
if( !pin ) {
std::cout<<"OpParBase::import_settings(): pin = NULL"<& propin = pin->get_properties();
std::list::iterator pi=propin.begin(), pj=properties.begin();
for( ; pi != propin.end(); pi++, pj++ ) {
if( !(*pj)->import( *pi ) ) {
std::cout<<"OpParBase::import_settings(): failed to import values for property \""<<(*pj)->get_name()<<"\""<get_name()<<"\" se to "<<(*pj)->get_str()<& mpropin = pin->get_mapped_properties();
std::list::iterator mpi=mpropin.begin(), mpj=mapped_properties.begin();
for( ; mpi != mpropin.end(); mpi++, mpj++ ) {
if( !(*mpj)->import( *mpi ) ) {
std::cout<<"OpParBase::import_settings(): failed to import values for property \""<<(*mpj)->get_name()<<"\""<is_map() );
//std::cout<<"OpParBase["<is_editing()<<")"<is_editing() );
//set_demand_hint( pin->get_demand_hint() );
//set_image_hints( pin->get_xsize(), pin->get_ysize(),
// pin->get_interpretation() );
//set_nbands( pin->get_nbands() );
//set_coding( pin->get_coding() );
//set_format( pin->get_format() );
return true;
}
VipsImage* PF::OpParBase::build(std::vector& in, int first,
VipsImage* imap, VipsImage* omap, unsigned int& level)
{
VipsImage* outnew = NULL;
VipsImage* invec[100];
unsigned int n = 0;
for(unsigned int i = 0; i < in.size(); i++) {
if( !in[i] ) continue;
invec[n] = in[i];
n++;
}
if(n > 100) n = 100;
#ifndef NDEBUG
//std::cout<<"OpParBase::build("<ref_count< PF::OpParBase::build_many(std::vector& in, int first,
VipsImage* imap, VipsImage* omap, unsigned int& level)
{
std::vector result;
VipsImage* out = build( in, first, imap, omap, level );
//std::cout<<"OpParBase::build_many(): padding="<Xsize*2/tw;
VipsAccess acc = VIPS_ACCESS_RANDOM;
int threaded = 1, persistent = 0;
if( vips_tilecache(out, &cached,
"tile_width", tw, "tile_height", th, "max_tiles", nt,
"access", acc, "threaded", threaded, "persistent", persistent, NULL) ) {
std::cout<<"GaussBlurPar::build(): vips_tilecache() failed."< PF::OpParBase::build_many_internal(std::vector& in, int first,
VipsImage* imap, VipsImage* omap, unsigned int& level)
{
std::vector in_temp;
if( true && convert_inputs_on_map_build() && is_map() && interpretation == VIPS_INTERPRETATION_B_W ) {
if( !to_map ) to_map = new_image_to_map();
std::vector in_temp2;
std::vector* in_ptr = in_temp.empty() ? &in : &in_temp;
for(unsigned int i = 0; i < in_ptr->size(); i++) {
VipsImage* img = (*in_ptr)[i];
if( img == NULL || img->Type == interpretation ) {
in_temp2.push_back(img);
std::cout<<"OpParBase::build_many_internal: op_type="< in2; in2.push_back(img);
std::cout<<"OpParBase::build_many_internal: to_map="<get_par();
to_map_op->set_format(get_format());
//to_map_op->set_image_hints(img);
//to_map_op->grayscale_image( img->Xsize, img->Ysize );
VipsImage* bwimg = to_map_op->build(in2, 0, NULL, NULL, level);
std::cout<<"OpParBase::build_many_internal: bwimg built"< result;
if( in_temp.empty() )
result = build_many( in, first, imap, omap, level );
else
result = build_many( in_temp, first, imap, omap, level );
#ifndef NDEBUG
std::cout<<"OpParBase::build_many_internal(): filling hierarchy with padding "< result_cached;
for( unsigned int i = 0; i < result.size(); i++ ) {
bool is_dup = false;
VipsImage* out = result[i];
for( unsigned int j = 0; j < in.size(); j++ ) {
if( out == in[j] ) {
is_dup = true;
break;
}
}
if( is_dup ) {
result_cached.push_back( out );
continue;
}
int p = get_output_padding( i );
if( p > 32 || needs_caching() ) {
VipsAccess acc = VIPS_ACCESS_RANDOM;
int threaded = 1, persistent = 1;
VipsImage* cached;
std::cout<<"OpParBase::build_many_internal(): adding tilecache for output image #"
<* in_ptr = in_temp.empty() ? &in : &in_temp;
for(unsigned int i = 0; i < in_ptr->size(); i++) {
VipsImage* img = (*in_ptr)[i];
PF_UNREF( img, "build_many_internal: img unref" );
std::cout<<"OpParBase::build_many_internal: op_type="<& in,
VipsImage* imap, VipsImage* omap, std::vector& out)
{
for( unsigned int i = 0; i < out.size(); i++ ) {
bool is_dup = false;
for( unsigned int j = 0; j < in.size(); j++ ) {
if( out[i] == in[j] ) {
is_dup = true;
break;
}
}
if( is_dup ) continue;
#ifndef NDEBUG
if( get_padding() > 0 ) {
std::cout<<"OpParBase::fill_image_hierarchy(): filling hierarchy for image "< maps;
if( imap ) maps.push_back(imap);
if( omap ) maps.push_back(omap);
if( !maps.empty() ) PF::image_hierarchy_fill( out[i], 0, maps );
}
}
bool PF::OpParBase::save( std::ostream& ostr, int level )
{
for(int i = 0; i < level; i++) ostr<<" ";
ostr<<""<::iterator pi = properties.begin();
pi != properties.end(); pi++ ) {
if( (*pi)->is_persistent() == false ) continue;
std::string pvalue = (*pi)->get_str();
for(int i = 0; i < level+1; i++) ostr<<" ";
ostr<<"get_name()<<"\" value=\"";
//(*pi)->to_stream( ostr );
ostr<"<"<::iterator pi = mapped_properties.begin();
pi != mapped_properties.end(); pi++ ) {
if( (*pi)->is_persistent() == false ) continue;
std::string pvalue = (*pi)->get_str();
for(int i = 0; i < level+1; i++) ostr<<" ";
ostr<<"get_name()<<"\" value=\"";
//(*pi)->to_stream( ostr );
ostr<"<"<"<Xsize;
int Ysize = out->Ysize;
int bands = out->Bands;
VipsBandFormat fmt = out->BandFmt;
VipsCoding coding = out->Coding;
VipsInterpretation type = out->Type;
gdouble xres = out->Xres;
gdouble yres = out->Yres;
VipsImage* invec[2] = {in, NULL};
vips__image_copy_fields_array( out, invec );
vips_image_init_fields( out,
Xsize, Ysize, bands, fmt,
coding, type, xres, yres
);
return 0;
}
void PF::print_embedded_profile( VipsImage* image )
{
PF::ICCProfile* icc_data = PF::get_icc_profile( image );
if(icc_data) {
cmsHPROFILE in_profile = icc_data->get_profile();
if( in_profile ) {
char tstr[1024];
cmsGetProfileInfoASCII(in_profile, cmsInfoDescription, "en", "US", tstr, 1024);
std::cout<<"\""<