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_PIXEL_PROCESSOR__H 31 #define PF_PIXEL_PROCESSOR__H 32 33 #include <iostream> 34 35 //#include "processor.hh" 36 //#include "layer.hh" 37 #include "operation.hh" 38 #include "color.hh" 39 40 namespace PF 41 { 42 43 #define PIXELPROC_TEMPLATE_DEF \ 44 typename T_, colorspace_t CS_, \ 45 int CHMIN_, int CHMAX_, \ 46 bool PREVIEW_, typename OP_PAR_ 47 48 #define PIXELPROC_TEMPLATE_IMP \ 49 T, CS, CHMIN, CHMAX, PREVIEW, OP_PAR 50 51 52 #define PIXELPROC_TEMPLATE_DEF_CS_SPEC \ 53 typename T_, \ 54 int CHMIN_, int CHMAX_, \ 55 bool PREVIEW_, typename OP_PAR_ 56 57 #define PIXELPROC_TEMPLATE_IMP_CS_SPEC(CS_SPEC) \ 58 T, CS_SPEC, CHMIN, CHMAX, PREVIEW, OP_PAR 59 60 61 62 class PixelProcessorPar: public OpParBase 63 { 64 Property<float> color_blend; 65 66 public: PixelProcessorPar()67 PixelProcessorPar(): 68 OpParBase(), 69 color_blend("color_blend",this,0) 70 { 71 } has_imap()72 bool has_imap() { return false; } has_omap()73 bool has_omap() { return false; } needs_input()74 bool needs_input() { return true; } 75 get_color_blend()76 float get_color_blend() { return( color_blend.get() ); } 77 }; 78 79 80 81 82 83 84 template < OP_TEMPLATE_DEF, class OP_PAR, template < PIXELPROC_TEMPLATE_DEF > class PEL_PROC > 85 class PixelProcessor: public IntensityProc<T, has_imap> 86 { 87 typedef OP_PAR OpParams; 88 public: render(VipsRegion ** ir,int n,int in_first,VipsRegion * imap,VipsRegion *,VipsRegion * oreg,OP_PAR * par)89 void render(VipsRegion** ir, int n, int in_first, 90 VipsRegion* imap, VipsRegion* , 91 VipsRegion* oreg, OP_PAR* par) 92 { 93 PEL_PROC<PIXELPROC_TEMPLATE_IMP> proc(par); 94 95 float intensity = par->get_intensity(); 96 float blend = par->get_color_blend(); 97 float nblend = -1.0f * blend; 98 VipsRect *r = &oreg->valid; 99 int sz = oreg->im->Bands;//IM_REGION_N_ELEMENTS( oreg ); 100 int line_size = r->width * oreg->im->Bands; //layer->in_all[0]->Bands; 101 102 #ifdef _NDEBUG 103 std::cout<<"PixelProcessor::render(): "<<std::endl 104 <<" name: "<<par->get_config_ui()->get_layer()->get_name()<<std::endl 105 <<" input region: top="<<ir[in_first]->valid.top 106 <<" left="<<ir[in_first]->valid.left 107 <<" width="<<ir[in_first]->valid.width 108 <<" height="<<ir[in_first]->valid.height<<std::endl 109 <<" output region: top="<<oreg->valid.top 110 <<" left="<<oreg->valid.left 111 <<" width="<<oreg->valid.width 112 <<" height="<<oreg->valid.height<<std::endl; 113 #endif 114 115 const int NMAX = 100; 116 const int nch = oreg->im->Bands; 117 T* p[NMAX+1]; 118 T* pout; 119 T* pimap; 120 121 if(n > NMAX) n = NMAX; 122 123 int x, y, ch, dx=CHMAX-CHMIN+1;//, CHMAXplus1=CHMAX+1; 124 int ximap, ni; 125 126 //std::cout<<"PixelProcessor::render(): CHMIN="<<CHMIN<<" CHMAX="<<CHMAX 127 // <<"PF::ColorspaceInfo<CS>::NCH="<<PF::ColorspaceInfo<CS>::NCH<<std::endl; 128 129 for( y = 0; y < r->height; y++ ) { 130 131 for( ni = 0; ni < n; ni++) 132 p[ni] = (T*)VIPS_REGION_ADDR( ir[ni], r->left, r->top + y ); 133 pout = (T*)VIPS_REGION_ADDR( oreg, r->left, r->top + y ); 134 if(has_imap) pimap = (T*)VIPS_REGION_ADDR( imap, r->left, r->top + y ); 135 136 for( x=0, ximap=0; x < line_size; ) { 137 float intensity_real = this->get_intensity( intensity, pimap, ximap ); 138 for( ch=0; ch<CHMIN; ch++, x++ ) pout[x] = p[0][x]; 139 proc.process( p, n, in_first, sz, x, intensity_real/*get_intensity( intensity, pimap, ximap )*/, pout ); 140 x += dx; 141 //for( ch=CHMAX+1; ch<PF::ColorspaceInfo<CS>::NCH; ch++, x++ ) pout[x] = p[0][x]; 142 for( ch=CHMAX+1; ch<nch; ch++, x++ ) pout[x] = p[0][x]; 143 //for( ch=0; ch<PF::ColorspaceInfo<CS>::NCH; ch++, x++ ) pout[x] = p[0][x]; 144 } 145 if( CS != PF_COLORSPACE_RGB || blend == 0 ) continue; 146 147 if( blend > 0 ) { 148 // Blend the output luminance with the input colors 149 // Preserves the color information of the input image 150 // Equivalent to the "luminosity blend" in photoshop 151 double ired, ig, ib; 152 double ored, og, ob; 153 double ored2, og2, ob2; 154 for( x=0, ximap=0; x < line_size; ) { 155 ored = (double(pout[x]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 156 og = (double(pout[x+1]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 157 ob = (double(pout[x+2]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 158 double lumi = PF::luminance( ored, og, ob ); 159 ired = (double(p[0][x]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 160 ig = (double(p[0][x+1]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 161 ib = (double(p[0][x+2]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 162 //std::cout<<"Input: "<<ired<<" "<<ig<<" "<<ib<<std::endl; 163 //std::cout<<"Output: "<<ored<<" "<<og<<" "<<ob<<std::endl; 164 ored2 = ired; og2 = ig; ob2 = ib; 165 PF::lc_blend( ored2, og2, ob2, lumi ); 166 pout[x] = (T)(( (ored2*blend)+(ored*(1.0f-blend)) )*FormatInfo<T>::RANGE - FormatInfo<T>::MIN); 167 pout[x+1] = (T)(( (og2*blend)+(og*(1.0f-blend)) )*FormatInfo<T>::RANGE - FormatInfo<T>::MIN); 168 pout[x+2] = (T)(( (ob2*blend)+(ob*(1.0f-blend)) )*FormatInfo<T>::RANGE - FormatInfo<T>::MIN); 169 //std::cout<<"ired="<<ired<<" ored="<<ored<<" (ored*blend)+(ired*(1.0f-blend))="<<(ored*blend)+(ired*(1.0f-blend))<<std::endl; 170 //std::cout<<"p[x]="<<p[0][x]<<" pout[x]="<<pout[x]<<std::endl; 171 x += 3; 172 } 173 } else if( blend < 0 ) { 174 // Blend the output color with the input luminance 175 // Preserves the luminance information of the input image 176 // Equivalent to the "color blend" in photoshop 177 double ired, ig, ib; 178 double ored, og, ob; 179 double ored2, og2, ob2; 180 for( x=0, ximap=0; x < line_size; ) { 181 ired = (double(p[0][x]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 182 ig = (double(p[0][x+1]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 183 ib = (double(p[0][x+2]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 184 ored = (double(pout[x]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 185 og = (double(pout[x+1]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 186 ob = (double(pout[x+2]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE; 187 double lumi = PF::luminance( ired, ig, ib ); 188 ored2 = ored; og2 = og; ob2 = ob; 189 PF::lc_blend( ored2, og2, ob2, lumi ); 190 pout[x] = (T)(( (ored2*nblend)+(ored*(1.0f-nblend)) )*FormatInfo<T>::RANGE - FormatInfo<T>::MIN); 191 pout[x+1] = (T)(( (og2*nblend)+(og*(1.0f-nblend)) )*FormatInfo<T>::RANGE - FormatInfo<T>::MIN); 192 pout[x+2] = (T)(( (ob2*nblend)+(ob*(1.0f-nblend)) )*FormatInfo<T>::RANGE - FormatInfo<T>::MIN); 193 x += 3; 194 } 195 } 196 } 197 } 198 }; 199 200 } 201 202 #endif 203