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
31 #ifndef RAW_BUFFER_H
32 #define RAW_BUFFER_H
33
34 #include <math.h>
35
36 #include <string>
37 #include <list>
38 #include <vector>
39 #include <iostream>
40 #include <fstream>
41
42
43 #include <vips/vips.h>
44 //#include <vips/vips>
45
46 #include "pftypes.hh"
47
48 #include "format_info.hh"
49
50 #include "property.hh"
51
52 #include "imagepyramid.hh"
53
54
55
56 namespace PF
57 {
58
59 class PencilMask
60 {
61 unsigned int size;
62 float opacity;
63 float smoothness;
64 float** mask;
65 public:
PencilMask()66 PencilMask(): size(0), opacity(1), smoothness(0), mask(NULL)
67 {
68 //std::cout<<"PencilMask() called"<<std::endl;
69 }
70
PencilMask(const PencilMask & sm)71 PencilMask( const PencilMask& sm ):
72 size(0),
73 opacity(1),
74 smoothness(0),
75 mask(NULL)
76 {
77 init( sm.get_size(), sm.get_opacity(), sm.get_smoothness() );
78 //std::cout<<"PencilMask(const PencilMask& sm) called"<<std::endl;
79 }
80
~PencilMask()81 ~PencilMask()
82 {
83 //std::cout<<"~PencilMask() called. this="<<(void*)this<<" mask="<<mask<<" size="<<size<<std::endl;
84 //return;
85 if( mask ) {
86 for( unsigned int i = 0; i < size; i++) delete[] mask[i];
87 delete[] mask;
88 mask = NULL;
89 }
90 //std::cout<<"~PencilMask() finished"<<std::endl;
91 }
92
operator =(const PencilMask & sm)93 PencilMask& operator=( const PencilMask& sm )
94 {
95 init( sm.get_size(), sm.get_opacity(), sm.get_smoothness() );
96 //std::cout<<"PencilMask& operator=(const PencilMask& sm) called"<<std::endl;
97 return ( *this );
98 }
99
get_size() const100 unsigned int get_size() const { return size; }
get_opacity() const101 float get_opacity() const { return opacity; }
get_smoothness() const102 float get_smoothness() const { return smoothness; }
103
104 void init(unsigned int s, float op, float sm);
105
get(int x,int y)106 float get(int x, int y )
107 {
108 if( !mask ) {
109 std::cout<<"PencilMask::get(): WARNING: mask = NULL"<<std::endl;
110 return 1;
111 }
112 if( x < 0 || x >= (int)size) {
113 std::cout<<"PencilMask::get(): WARNING: x value out of range ("<<x<<")"<<std::endl;
114 return 1;
115 }
116 if( y < 0 || y >= (int)size) {
117 std::cout<<"PencilMask::get(): WARNING: y value out of range ("<<y<<")"<<std::endl;
118 return 1;
119 }
120 return mask[y][x];
121 }
122 };
123
124
125
126 class Pencil
127 {
128 std::vector<float> color;
129 int size;
130 float opacity;
131 float smoothness;
132 PencilMask mask;
133 public:
Pencil()134 Pencil(): size(0), opacity(1), smoothness(0.5) {}
Pencil(const Pencil & p)135 Pencil( const Pencil& p )
136 {
137 //std::cout<<"Stamp(const Stamp& s) called."<<std::endl;
138 size = p.get_size();
139 opacity = p.get_opacity();
140 smoothness = p.get_smoothness();
141 init_mask();
142 }
143
set_size(int s)144 void set_size( int s ) { size = s; init_mask(); }
get_size() const145 int get_size() const { return size; }
146
set_channel(unsigned int ch,float val)147 void set_channel( unsigned int ch, float val )
148 {
149 if( color.size() <= ch )
150 color.resize( ch+1 );
151 color[ch] = val;
152 }
get_channel(unsigned int ch) const153 float get_channel( unsigned int ch ) const
154 {
155 if( color.size() <= ch ) return 0;
156 return color[ch];
157 }
get_color()158 std::vector<float>& get_color() { return color; }
get_color() const159 const std::vector<float>& get_color() const { return color; }
160
set_opacity(float val)161 void set_opacity( float val ) { opacity = val; }
get_opacity() const162 float get_opacity() const { return opacity; }
163
set_smoothness(float val)164 void set_smoothness( float val ) { smoothness = val; init_mask(); }
get_smoothness() const165 float get_smoothness() const { return smoothness; }
166
init_mask()167 void init_mask()
168 {
169 mask.init( size*2+1, opacity, smoothness );
170 }
get_mask()171 PencilMask& get_mask() { return mask; }
172
operator =(const Pencil & p)173 Pencil & operator=(const Pencil &p)
174 {
175 color = p.get_color();
176 size = p.get_size();
177 opacity = p.get_opacity();
178 smoothness = p.get_smoothness();
179 init_mask();
180 return(*this);
181 }
182 };
183
184
185 inline
operator ==(const Pencil & l,const Pencil & r)186 bool operator ==(const Pencil& l, const Pencil& r)
187 {
188 if( l.get_color() != r.get_color() ) return false;
189 if( l.get_opacity() != r.get_opacity() ) return false;
190 if( l.get_size() != r.get_size() ) return false;
191 if( l.get_smoothness() != r.get_smoothness() ) return false;
192 return true;
193 }
194
195 inline
operator !=(const Pencil & l,const Pencil & r)196 bool operator !=(const Pencil& l, const Pencil& r)
197 {
198 return( !(l==r) );
199 }
200
201
202
203
204 class Segment
205 {
206 unsigned int x1, y1, x2, y2;
207 public:
Segment()208 Segment(): x1(0), y1(0), x2(0), y2(0) {}
set(unsigned int _x1,unsigned int _y1,unsigned int _x2,unsigned int _y2)209 void set( unsigned int _x1, unsigned int _y1,
210 unsigned int _x2, unsigned int _y2 )
211 {
212 x1 = _x1; y1 = _y1; x2 = _x2; y2 = _y2;
213 }
get_x1()214 unsigned int get_x1() { return x1; }
get_y1()215 unsigned int get_y1() { return y1; }
get_x2()216 unsigned int get_x2() { return x2; }
get_y2()217 unsigned int get_y2() { return y2; }
218 };
219
220
221
222
223 template <class Pen>
224 class Stroke
225 {
226 Pen pen;
227 std::list<Segment> segments;
228 std::list< std::pair<int, int> > points;
229
230 VipsRect area;
231
232 public:
Stroke()233 Stroke()
234 {
235 //std::cout<<"Calling Stroke()"<<std::endl;
236 }
237
Stroke(const Stroke & s)238 Stroke(const Stroke& s)
239 {
240 //std::cout<<"Calling Stroke(const Stroke& s)"<<std::endl;
241 pen = s.get_pen();
242 segments = s.get_segments();
243 points = s.get_points();
244 area.width = s.get_area().width;
245 area.height = s.get_area().height;
246 area.left = s.get_area().left;
247 area.top = s.get_area().top;
248 //std::cout<<"Stroke(const Stroke& s) finished"<<std::endl;
249 }
250
operator =(const Stroke & s)251 Stroke& operator=(const Stroke& s)
252 {
253 //std::cout<<"Calling Stroke& operator=(const Stroke& s)"<<std::endl;
254 pen = s.get_pen();
255 segments = s.get_segments();
256 points = s.get_points();
257 area.width = s.get_area().width;
258 area.height = s.get_area().height;
259 area.left = s.get_area().left;
260 area.top = s.get_area().top;
261 //std::cout<<"Stroke& operator=(const Stroke& s) finished"<<std::endl;
262 return *this;
263 }
264
~Stroke()265 ~Stroke()
266 {
267 //std::cout<<"Calling ~Stroke()"<<std::endl;
268 }
269
get_pen()270 Pen& get_pen() { return pen; }
get_pen() const271 const Pen& get_pen() const { return pen; }
get_points()272 std::list< std::pair<int, int> >& get_points() { return points; }
get_points() const273 const std::list< std::pair<int, int> >& get_points() const { return points; }
get_segments()274 std::list< Segment >& get_segments() { return segments; }
get_segments() const275 const std::list< Segment >& get_segments() const { return segments; }
get_area()276 VipsRect& get_area() { return area; }
get_area() const277 const VipsRect& get_area() const { return area; }
278 void compute_area();
279 };
280
281
282 template <class Pen>
compute_area()283 void PF::Stroke<Pen>::compute_area()
284 {
285 int xmin = 10000000, xmax = -10000000;
286 int ymin = 10000000, ymax = -10000000;
287 std::list< std::pair<int, int> >::iterator pi;
288 for( pi = points.begin(); pi != points.end(); pi++ ) {
289 int x1 = pi->first - pen.get_size();
290 int x2 = pi->first + pen.get_size();
291 int y1 = pi->second - pen.get_size();
292 int y2 = pi->second + pen.get_size();
293
294 xmin = MIN( xmin, x1 );
295 xmax = MAX( xmax, x2 );
296 ymin = MIN( ymin, y1 );
297 ymax = MAX( ymax, y2 );
298 }
299
300 //std::cout<<"Stroke<Pen>::compute_area(): points.size()="<<points.size()<<" xmin="<<xmin<<" xmax="<<xmax<<" ymin="<<ymin<<" ymax="<<ymax<<std::endl;
301
302 area.left = xmin;
303 area.top = ymin;
304 area.width = xmax - xmin + 1;
305 area.height = ymax - ymin + 1;
306 }
307
308
309
310 template <class Pen>
operator ==(const Stroke<Pen> & l,const Stroke<Pen> & r)311 inline bool operator ==(const Stroke<Pen>& l, const Stroke<Pen>& r)
312 {
313 if( l.get_pen() != r.get_pen() ) return false;
314 if( l.get_points() != r.get_points() ) return false;
315 return true;
316 }
317
318 template <class Pen>
operator !=(const Stroke<Pen> & l,const Stroke<Pen> & r)319 inline bool operator !=(const Stroke<Pen>& l, const Stroke<Pen>& r)
320 {
321 return( !(l==r) );
322 }
323
324
operator >>(std::istream & str,Pencil & pen)325 inline std::istream& operator >>( std::istream& str, Pencil& pen )
326 {
327 unsigned int nch;
328 str>>nch;
329 std::vector<float>& color = pen.get_color();
330 color.clear();
331 for( unsigned int i = 0; i < nch; i++ ) {
332 float val;
333 str>>val;
334 color.push_back( val );
335 }
336 unsigned int size;
337 //float opacity;
338 //str>>size>>opacity;
339 float sharpness;
340 str>>size>>sharpness;
341 pen.set_size( size );
342 //pen.set_opacity( opacity );
343 pen.set_smoothness( 1.0f-sharpness );
344 return str;
345 }
346
operator <<(std::ostream & str,const Pencil & pen)347 inline std::ostream& operator <<( std::ostream& str, const Pencil& pen )
348 {
349 const std::vector<float>& color = pen.get_color();
350 str<<color.size()<<" ";
351 std::list< std::pair<unsigned int, unsigned int> >::iterator i;
352 for( unsigned int i = 0; i < color.size(); i++ ) {
353 str<<color[i]<<" ";
354 }
355 //str<<pen.get_size()<<" "<<pen.get_opacity()<<" ";
356 str<<pen.get_size()<<" "<<1.0f-pen.get_smoothness()<<" ";
357 return str;
358 }
359
360
361
362 template <class Pen>
operator >>(std::istream & str,Stroke<Pen> & stroke)363 inline std::istream& operator >>( std::istream& str, Stroke<Pen>& stroke )
364 {
365 str>>stroke.get_pen();
366 std::list< std::pair<int, int> >& points = stroke.get_points();
367 points.clear();
368 int npoints;
369 str>>npoints;
370 for( int i = 0; i < npoints; i++ ) {
371 int a, b;
372 str>>a>>b;
373 points.push_back( std::make_pair(a,b) );
374 }
375 return str;
376 }
377
378 template <class Pen>
operator <<(std::ostream & str,const Stroke<Pen> & stroke)379 inline std::ostream& operator <<( std::ostream& str, const Stroke<Pen>& stroke )
380 {
381 str<<stroke.get_pen();
382 const std::list< std::pair<int, int> >& points = stroke.get_points();
383 str<<points.size()<<" ";
384 std::list< std::pair<int, int> >::const_iterator i;
385 for( i = points.begin(); i != points.end(); i++ ) {
386 str<<i->first<<" "<<i->second<<" ";
387 }
388 return str;
389 }
390
391
392 /*
393 template <class Pen>
394 inline std::istream& operator >>( std::istream& str, std::list< Stroke<Pen> >& strokes )
395 {
396 strokes.clear();
397 int nstrokes;
398 str>>nstrokes;
399 for( int i = 0; i < nstrokes; i++ ) {
400 strokes.push_back( Stroke<Pen>() );
401 Stroke<Pen>& stroke = strokes.back();
402 str>>stroke;
403 }
404 return str;
405 }
406
407 template <class Pen>
408 inline std::ostream& operator <<( std::ostream& str, const std::list< Stroke<Pen> >& strokes )
409 {
410 str<<strokes.size()<<" ";
411 typename std::list< Stroke<Pen> >::const_iterator i;
412 for( i = strokes.begin(); i != strokes.end(); i++ ) {
413 str<<(*i);
414 }
415 return str;
416 }
417 */
418
419 /*
420 template <class T>
421 inline bool operator ==(const std::list<T>& l, const std::list<T>& r)
422 {
423 if( l.size() != r.size() ) return false;
424 typename std::list<T>::const_iterator i, j;
425 for( i = l.begin(), j = r.begin(); i != l.end(); i++, j++ ) {
426 if( (*i) != (*j) ) return false;
427 }
428 return true;
429 }
430
431 template <class T>
432 inline bool operator !=(const std::list<T>& l, const std::list<T>& r)
433 {
434 return( !(l==r) );
435 }
436 */
437
438 /*
439 template <class T>
440 inline std::istream& operator >>( std::istream& str, std::list<T>& list )
441 {
442 list.clear();
443 int n;
444 str>>n;
445 for( int i = 0; i < n; i++ ) {
446 list.push_back( T() );
447 T& val = list.back();
448 str>>val;
449 }
450 return str;
451 }
452
453 template <class T>
454 inline std::ostream& operator <<( std::ostream& str, const std::list<T>& list )
455 {
456 str<<list.size()<<" ";
457 typename std::list<T>::const_iterator i;
458 for( i = list.begin(); i != list.end(); i++ ) {
459 str<<(*i);
460 }
461 return str;
462 }
463 */
464
465
466 template<> inline
set_gobject_property(gpointer object,const std::string name,const std::list<Stroke<Pencil>> & value)467 void set_gobject_property< std::list< Stroke<Pencil> > >(gpointer object, const std::string name,
468 const std::list< Stroke<Pencil> >& value)
469 {
470 }
471
472
473
474 class RawBuffer
475 {
476 std::string file_name;
477 int fd;
478 void* buf;
479 unsigned char* pxmask;
480
481 // Requested image fields
482 unsigned int xsize;
483 unsigned int ysize;
484 unsigned int bands;
485 VipsBandFormat format;
486 VipsCoding coding;
487 VipsInterpretation interpretation;
488
489 std::vector<float> bgd_color;
490
491 VipsImage* image;
492
493 ImagePyramid pyramid;
494
495 std::vector< std::list< std::pair<unsigned int, unsigned int> > > stroke_ranges;
496
497 public:
498 RawBuffer();
499 RawBuffer( std::string file_name );
500
~RawBuffer()501 virtual ~RawBuffer()
502 {
503 std::cout<<"PF::RawBuffer::~RawBuffer(): deleting "<<(void*)this<<std::endl;
504 if( fd >= 0 ) {
505 close( fd );
506 unlink( file_name.c_str() );
507 std::cout<<"PF::RawBuffer::~RawBuffer(): "<<file_name<<" removed."<<std::endl;
508 }
509 }
510
get_file_name()511 std::string get_file_name() { return file_name; }
get_fd()512 int get_fd() { return fd; }
513
get_xsize()514 int get_xsize() { return xsize; }
get_ysize()515 int get_ysize() { return ysize; }
516
set_xsize(int sz)517 void set_xsize(int sz) { xsize = sz; }
set_ysize(int sz)518 void set_ysize(int sz) { ysize = sz; }
519
get_nbands()520 int get_nbands() { return bands; }
set_nbands(int n)521 void set_nbands( int n ) { bands = n; }
522
get_interpretation()523 VipsInterpretation get_interpretation() { return interpretation; }
get_colorspace()524 colorspace_t get_colorspace() { return( PF::convert_colorspace( get_interpretation() ) ); }
set_interpretation(VipsInterpretation val)525 void set_interpretation( VipsInterpretation val ) { interpretation = val; }
526
get_format()527 VipsBandFormat get_format() { return format; }
set_format(VipsBandFormat fmt)528 void set_format( VipsBandFormat fmt ) { format = fmt; }
529
get_coding()530 VipsCoding get_coding() { return coding; }
set_coding(VipsCoding c)531 void set_coding( VipsCoding c ) { coding = c; }
532
get_bgd_color()533 std::vector<float> get_bgd_color() { return bgd_color; }
534
get_pyramid()535 ImagePyramid& get_pyramid() { return pyramid; }
536
537 void init( const std::vector<float>& bgd_color );
538
539 void draw_row( Pencil& pen, unsigned int row,
540 unsigned int startcol, unsigned int endcol );
541 void draw_point( Pencil& pen, unsigned int x, unsigned int y, VipsRect& update, bool update_pyramid );
542 void draw_segment( Pencil& pen, Segment& segment );
543
544 void start_stroke();
545 void end_stroke();
546
547 //void draw_stroke( Stroke& stroke );
548 };
549
550
551 };
552
553 #endif
554