1 /* 2 3 */ 4 5 /* 6 7 Copyright (C) 2014 Ferrero Andrea 8 9 This program is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21 22 23 */ 24 25 /* 26 27 These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/ 28 29 */ 30 31 #ifndef PF_IMAGE_HH 32 #define PF_IMAGE_HH 33 34 #include <stdlib.h> 35 #include <sigc++/sigc++.h> 36 37 //#include <gexiv2/gexiv2-metadata.h> 38 39 #include "condition.hh" 40 41 #include "layermanager.hh" 42 #include "pipeline.hh" 43 44 #define CACHE_PIPELINE_ID 0 45 #define PREVIEW_PIPELINE_ID 1 46 #define HISTOGRAM_PIPELINE_ID 2 47 48 49 50 51 52 namespace PF 53 { 54 55 56 enum export_format_t 57 { 58 EXPORT_FORMAT_JPEG, 59 EXPORT_FORMAT_TIFF_8, 60 EXPORT_FORMAT_TIFF_16, 61 EXPORT_FORMAT_TIFF_32f, 62 EXPORT_FORMAT_EXR_16f, 63 EXPORT_FORMAT_EXR_32f 64 }; 65 66 struct ImageBuffer 67 { 68 float* buf; 69 int width, height; 70 //GExiv2Metadata* exif_buf; 71 void* iccdata; 72 size_t iccsize; 73 TRC_type trc_type; 74 }; 75 76 77 struct image_export_opt_t 78 { 79 int jpeg_quality; 80 bool jpeg_chroma_subsampling; 81 int jpeg_quant_table; 82 int tiff_format; 83 bool tiff_compress; 84 int exr_format; 85 export_size_t size; 86 int width, height; 87 scale_interpolation_t interpolator; 88 bool sharpen_enabled; 89 float sharpen_radius; 90 float sharpen_amount; 91 profile_type_t profile_type; 92 TRC_type trc_type; 93 cmsUInt32Number intent; 94 bool bpc; 95 Glib::ustring custom_profile_name; 96 }; 97 98 99 class Image: public sigc::trackable 100 { 101 LayerManager layer_manager; 102 std::vector<Pipeline*> pipelines; 103 104 // Flag indicating whether the update should be preformed asynchronously 105 bool async; 106 107 // Flag indicating whether the pipelines have to be re-built 108 bool modified_flag; 109 110 // Flag indicating whether there is a re-building ongoing 111 bool rebuilding; 112 113 bool loaded; 114 115 // Current file name associated to this image 116 // It corresponds to the file specified in the 117 // most recent "open" or "save" action 118 std::string file_name; 119 120 // Name of the backup file used to save the current 121 // editing parameters so that they can be restored 122 // in case of a program crash 123 std::string backup_file_name; 124 125 bool disable_update; 126 127 GMutex* image_mutex; 128 //GCond* rebuild_done; 129 PF::Condition rebuild_cond; 130 131 bool force_synced_update; 132 133 //GMutex* export_mutex; 134 //GCond* export_done; 135 Condition export_cond; 136 bool export_ok; 137 138 //GMutex* sample_mutex; 139 //GCond* sample_done; 140 PF::Condition sample_cond; 141 142 PF::Condition destroy_cond; 143 144 //GMutex* remove_layer_mutex; 145 //GCond* remove_layer_done; 146 PF::Condition remove_layer_cond; 147 148 //ProcessorBase* convert2srgb; 149 ProcessorBase* convert_format; 150 ProcessorBase* resize; 151 ProcessorBase* sharpen; 152 ProcessorBase* convert2outprof; 153 ProcessorBase* convert2linear; 154 155 void remove_from_inputs( PF::Layer* layer ); 156 void remove_from_inputs( PF::Layer* layer, std::list<Layer*>& list ); 157 void remove_layer( PF::Layer* layer, std::list<Layer*>& list ); 158 159 VipsImage* sampler_image; 160 std::vector<float> sampler_values; 161 162 void update_async(); 163 164 public: 165 Image(); 166 167 ~Image(); 168 169 sigc::signal<void> signal_modified; 170 171 sigc::signal<void> signal_updated; 172 get_layer_manager()173 LayerManager& get_layer_manager() { return layer_manager; } 174 175 void do_remove_layer( PF::Layer* layer ); 176 void remove_layer( PF::Layer* layer ); 177 add_pipeline(VipsBandFormat fmt,int level,rendermode_t mode=PF_RENDER_PREVIEW)178 Pipeline* add_pipeline( VipsBandFormat fmt, int level, rendermode_t mode=PF_RENDER_PREVIEW ) 179 { 180 Pipeline* pipeline = new Pipeline( this, fmt, level, mode ); 181 pipelines.push_back( pipeline); 182 return pipeline; 183 } 184 remove_pipeline(Pipeline * pipeline)185 void remove_pipeline( Pipeline* pipeline ) 186 { 187 std::vector<Pipeline*>::iterator i; 188 for( i = pipelines.begin(); i != pipelines.end(); i++) { 189 if( *i == pipeline) { 190 pipelines.erase( i ); 191 break; 192 } 193 } 194 } 195 get_npipelines()196 unsigned int get_npipelines() { return pipelines.size(); } 197 get_pipeline(unsigned int n)198 Pipeline* get_pipeline(unsigned int n) 199 { 200 if( n >= pipelines.size() ) return NULL; 201 return(pipelines[n]); 202 } 203 204 PipelineNode* get_compatible_node(Layer* layer, Pipeline* pipeline, unsigned int level); 205 is_async()206 bool is_async() { return async; } set_async(bool flag)207 void set_async( bool flag ) { async = flag; } 208 is_modified()209 bool is_modified() { return modified_flag; } set_modified()210 void set_modified() { modified_flag = true; } clear_modified()211 void clear_modified() { modified_flag = false; } modified()212 void modified() { set_modified(); signal_modified.emit(); } 213 is_rebuilding()214 bool is_rebuilding() { return rebuilding; } set_rebuilding(bool flag)215 void set_rebuilding( bool flag ) { rebuilding = flag; } 216 get_force_synced_update()217 bool get_force_synced_update() { return force_synced_update; } set_force_synced_update(bool flag)218 void set_force_synced_update( bool flag ) { force_synced_update = flag; } 219 is_loaded()220 bool is_loaded() { return loaded; } set_loaded(bool flag)221 void set_loaded( bool flag ) { loaded = flag; } 222 223 //Glib::Threads::Mutex& get_rebuild_mutex() { return rebuild_mutex; } 224 225 void lock(); 226 void unlock(); 227 //void export_lock(); 228 //void export_unlock(); 229 //void sample_lock(); 230 //void sample_unlock(); 231 //void destroy_lock(); 232 //void destroy_unlock(); 233 //void remove_layer_lock() { g_mutex_lock( remove_layer_mutex); } 234 //void remove_layer_unlock() { g_mutex_unlock( remove_layer_mutex); } 235 //void rebuild_lock() { /*g_cond_signal( rebuild_done );*/ rebuild_cond.lock(); } 236 //void rebuild_unlock() { /*g_cond_signal( rebuild_done );*/ rebuild_cond.unlock(); } rebuild_done_reset()237 void rebuild_done_reset() { /*g_cond_signal( rebuild_done ); rebuild_cond.lock();*/ rebuild_cond.reset(); } rebuild_done_signal()238 void rebuild_done_signal() { /*g_cond_signal( rebuild_done );*/ rebuild_cond.signal(); } rebuild_done_wait(bool unlock=true)239 void rebuild_done_wait(bool unlock=true) { /*g_cond_signal( rebuild_done );*/ rebuild_cond.wait(); } export_done_signal()240 void export_done_signal() { export_cond.signal(); } sample_done_signal()241 void sample_done_signal() { /*g_cond_signal( sample_done );*/ sample_cond.signal(); } destroy_done_signal()242 void destroy_done_signal() { /*g_cond_signal( sample_done );*/ destroy_cond.signal(); } 243 //void remove_layer_done_signal() { /*g_cond_signal( remove_layer_done );*/ } remove_layer_reset()244 void remove_layer_reset() { /*g_cond_signal( rebuild_done ); remove_layer_cond.lock();*/ remove_layer_cond.reset(); } remove_layer_signal()245 void remove_layer_signal() { /*g_cond_signal( rebuild_done );*/ remove_layer_cond.signal(); } remove_layer_wait(bool unlock=true)246 void remove_layer_wait(bool unlock=true) { /*g_cond_signal( rebuild_done );*/ remove_layer_cond.wait(); } 247 248 void set_pipeline_level( PF::Pipeline* pipeline, int level ); 249 250 void update( PF::Pipeline* pipeline=NULL, bool sync=false ); update_all()251 void update_all() { update( NULL ); } 252 void do_update( PF::Pipeline* pipeline=NULL, bool update_gui=true ); 253 254 255 void sample( int layer_id, std::vector<VipsRect>& areas, bool weighted, 256 VipsImage** image, std::vector<float>& values ); 257 void sample( int layer_id, int x, int y, int size, 258 VipsImage** image, std::vector<float>& values ); 259 void do_sample( int layer_id, std::vector<VipsRect>& areas, bool weighted ); 260 261 void destroy(); 262 void do_destroy(); 263 264 bool open( std::string filename, std::string bckname="" ); 265 set_filename(std::string name)266 void set_filename(std::string name) { file_name = name; } get_filename()267 std::string get_filename() { return file_name; } 268 set_backup_filename(std::string name)269 void set_backup_filename(std::string name) { backup_file_name = name; } get_backup_filename()270 std::string get_backup_filename() { return backup_file_name; } 271 bool save_backup(); 272 273 bool save( std::string filename, bool do_clear=true, bool update_filename=true ); 274 bool export_merged( std::string filename, image_export_opt_t* export_opt=NULL ); 275 void do_export_merged( std::string filename, image_export_opt_t* export_opt=NULL ); 276 void export_merged_to_mem( ImageBuffer* imgbuf, void* gimp_iccdata, size_t gimp_iccsize ); 277 void export_merged_to_tiff( const std::string filename ); 278 }; 279 280 gint image_rebuild_callback( gpointer data ); 281 282 } 283 284 285 #endif /*VIPS_PARITHMETIC_H*/ 286 287 288