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 #ifndef PF_CLIP_WARNING_H
31 #define PF_CLIP_WARNING_H
32 
33 #include <string.h>
34 #include <string>
35 
36 #include "../base/processor.hh"
37 
38 
39 namespace PF
40 {
41 
42 class ClippingWarningPar: public OpParBase
43 {
44   bool highlights_warning_enabled, shadows_warning_enabled;
45 public:
46   ClippingWarningPar();
47 
set_highlights_warning(bool flag)48   void set_highlights_warning( bool flag ) { highlights_warning_enabled = flag; }
get_highlights_warning()49   bool get_highlights_warning() { return highlights_warning_enabled; }
set_shadows_warning(bool flag)50   void set_shadows_warning( bool flag ) { shadows_warning_enabled = flag; }
get_shadows_warning()51   bool get_shadows_warning() { return shadows_warning_enabled; }
52 
has_intensity()53   bool has_intensity() { return false; }
has_opacity()54   bool has_opacity() { return false; }
needs_input()55   bool needs_input() { return true; }
56 };
57 
58 
59 
60 template < OP_TEMPLATE_DEF >
61 class ClippingWarning
62 {
63 public:
render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)64   void render(VipsRegion** ireg, int n, int in_first,
65       VipsRegion* imap, VipsRegion* omap,
66       VipsRegion* oreg, OpParBase* par)
67   {
68     VipsRect *r = &oreg->valid;
69     int line_size = r->width * oreg->im->Bands; //layer->in_all[0]->Bands;
70     int height = r->height;
71 
72     T* p;
73     T* pout;
74     int x, y;
75 
76     for( y = 0; y < height; y++ ) {
77       p = (T*)VIPS_REGION_ADDR( ireg[in_first], r->left, r->top + y );
78       pout = (T*)VIPS_REGION_ADDR( oreg, r->left, r->top + y );
79       memcpy( pout, p, sizeof(T)*line_size );
80     }
81   }
82 };
83 
84 
85 template < OP_TEMPLATE_DEF_CS_SPEC >
86 class ClippingWarning< OP_TEMPLATE_IMP_CS_SPEC(PF_COLORSPACE_RGB) >
87 {
88 public:
render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)89   void render(VipsRegion** ireg, int n, int in_first,
90       VipsRegion* imap, VipsRegion* omap,
91       VipsRegion* oreg, OpParBase* par)
92   {
93     VipsRect *r = &oreg->valid;
94     int line_size = r->width * oreg->im->Bands; //layer->in_all[0]->Bands;
95     int width = r->width;
96     int height = r->height;
97 
98     ClippingWarningPar* opar = dynamic_cast<ClippingWarningPar*>( par );
99     if( !opar ) return;
100 
101     T max = static_cast<T>( 0.999f*PF::FormatInfo<T>::RANGE + PF::FormatInfo<T>::MIN );
102     T min = static_cast<T>( 0.001f*PF::FormatInfo<T>::RANGE + PF::FormatInfo<T>::MIN );
103 
104     T* p;
105     T* pin;
106     T* pout;
107     typename PF::FormatInfo<T>::PROMOTED avg;
108     int x, y;
109 
110     for( y = 0; y < height; y++ ) {
111       p = (T*)VIPS_REGION_ADDR( ireg[in_first], r->left, r->top + y );
112       pout = (T*)VIPS_REGION_ADDR( oreg, r->left, r->top + y );
113       for( x=0; x < line_size; x+=3 ) {
114         //avg = p[x]; avg += p[x+1]; avg += p[x+2]; avg /= 3;
115         if( opar->get_shadows_warning() && MIN3(p[x],p[x+1],p[x+2])<=min ) {
116           pout[x] = static_cast<T>( 0.2f*PF::FormatInfo<T>::RANGE + PF::FormatInfo<T>::MIN );
117           pout[x+1] = static_cast<T>( 0.8f*PF::FormatInfo<T>::RANGE + PF::FormatInfo<T>::MIN );
118           pout[x+2] = static_cast<T>( 1.0f*PF::FormatInfo<T>::RANGE + PF::FormatInfo<T>::MIN );
119         } else if( opar->get_highlights_warning() && MAX3(p[x],p[x+1],p[x+2])>=max ) {
120           pout[x] = static_cast<T>( 1.0f*PF::FormatInfo<T>::RANGE + PF::FormatInfo<T>::MIN );
121           pout[x+1] = 0;
122           pout[x+2] = 0;
123         } else {
124           pout[x] = p[x];
125           pout[x+1] = p[x+1];
126           pout[x+2] = p[x+2];
127         }
128       }
129     }
130   }
131 };
132 
133 
134 
135 
136 
137 ProcessorBase* new_clipping_warning();
138 }
139 
140 #endif
141 
142 
143