source: src/filter/coloradj/coloradj_RGB.c @ 0ee638

Revision 0ee638, 10.6 KB checked in by Marko Cebokli <mc@…>, 3 years ago (diff)

coloradj_RGB fixed blue channel alpha control

  • Property mode set to 100755
Line 
1/*
2coloradj_RGB.c
3
4This frei0r plugin   is for simple RGB color adjustment
5Version 0.1     jul 2010
6
7Copyright (C) 2010  Marko Cebokli    http://lea.hamradio.si/~s57uuu
8
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
24*/
25
26
27//compile: gcc -c -fPIC -Wall coloradj_RGB.c -o coloradj_RGB.o
28//link: gcc -shared -lm -o coloradj_RGB.so coloradj_RGB.o
29
30//#include <stdio.h>
31#include <stdlib.h>
32#include <math.h>
33#include <assert.h>
34
35#include <frei0r.h>
36
37//------------------------------------------------------
38//computes x to the power p
39//only for positive x
40float pwr(float x, float p)
41{
42if (x<=0) return 0;
43return expf(p*logf(x));
44}
45
46//-----------------------------------------------------
47//stretch [0...1] to parameter range [min...max] logarithmic
48//min and max must be positive!
49float map_value_forward_log(double v, float min, float max)
50{
51float sr,k;
52
53sr=sqrtf(min*max);
54k=2.0*log(max/sr);
55return sr*expf(k*(v-0.5));
56}
57
58//---------------------------------------
59//8 bit RGB lookup table
60typedef struct
61  {
62  unsigned char r[256];
63  unsigned char g[256];
64  unsigned char b[256];
65  } lut_s;
66
67//-------------------------------------------------------
68//  "Add constant"
69//norm=0 don't normalize    norm=1 do normalize
70void make_lut1(float r, float g, float b, lut_s *lut, int norm, int cm)
71{
72int i;
73float rr,gg,bb,l;
74
75for (i=0;i<256;i++)
76        {
77        rr=(float)i+(r-0.5)*150.0;  if (rr<0.0) rr=0.0;
78        gg=(float)i+(g-0.5)*150.0;  if (gg<0.0) gg=0.0;
79        bb=(float)i+(b-0.5)*150.0;  if (bb<0.0) bb=0.0;
80
81        if (norm==1)
82                {
83                switch (cm)
84                        {
85                        case 0:  //rec 601
86                                {
87                                l = 0.299*rr + 0.587*rr + 0.114*bb;
88                                break;
89                                }
90                        case 1:  //rec 709
91                                {
92                                l = 0.2126*rr + 0.7152*gg + 0.0722*bb;
93                                break;
94                                }
95                        default:
96                                {
97                                l=(float)i;
98                                break;
99                                }
100                        }
101                if (l>0.0)
102                        {
103                        rr=rr*(float)i/l;
104                        gg=gg*(float)i/l;
105                        bb=bb*(float)i/l;
106                        }
107                else
108                        {
109                        rr=0.0; gg=0.0; bb=0.0;
110                        }
111                }
112
113        if (rr>255.0) rr=255.0;
114        if (gg>255.0) gg=255.0;
115        if (bb>255.0) bb=255.0;
116        lut->r[i]=rintf(rr);
117        lut->g[i]=rintf(gg);
118        lut->b[i]=rintf(bb);
119        }
120}
121
122//-------------------------------------------------------
123//  "Change gamma"
124//norm=0 don't normalize    norm=1 do normalize
125void make_lut2(float r, float g, float b, lut_s *lut, int norm, int cm)
126{
127int i;
128float rr,gg,bb,gama,l;
129
130for (i=0;i<256;i++)
131        {
132        gama=map_value_forward_log(r,3.0,0.3333);
133        rr=255.0*pwr((float)i/255.0,gama);
134        gama=map_value_forward_log(g,3.0,0.3333);
135        gg=255.0*pwr((float)i/255.0,gama);
136        gama=map_value_forward_log(b,3.0,0.3333);
137        bb=255.0*pwr((float)i/255.0,gama);
138
139        if (norm==1)
140                {
141                switch (cm)
142                        {
143                        case 0:  //rec 601
144                                {
145                                l = 0.299*rr + 0.587*gg + 0.114*bb;
146                                break;
147                                }
148                        case 1:  //rec 709
149                                {
150                                l = 0.2126*rr + 0.7152*gg + 0.0722*bb;
151                                break;
152                                }
153                        default:
154                                {
155                                l=(float)i;
156                                break;
157                                }
158                        }
159                if (l>0.0)
160                        {
161                        rr=rr*(float)i/l;
162                        gg=gg*(float)i/l;
163                        bb=bb*(float)i/l;
164                        }
165                else
166                        {
167                        rr=0.0; gg=0.0; bb=0.0;
168                        }
169                }
170
171        if (rr>255.0) rr=255.0;  if (rr<0.0) rr=0.0;
172        if (gg>255.0) gg=255.0;  if (gg<0.0) gg=0.0;
173        if (bb>255.0) bb=255.0;  if (bb<0.0) bb=0.0;
174        lut->r[i]=rintf(rr);
175        lut->g[i]=rintf(gg);
176        lut->b[i]=rintf(bb);
177        }
178}
179
180//-------------------------------------------------------
181//  "Multiply"
182//norm=0 don't normalize    norm=1 do normalize
183void make_lut3(float r, float g, float b, lut_s *lut, int norm, int cm)
184{
185int i;
186float rr,gg,bb,l;
187
188for (i=0;i<256;i++)
189        {
190        rr=(float)i*map_value_forward_log(r,0.3333,3.0);
191        gg=(float)i*map_value_forward_log(g,0.3333,3.0);
192        bb=(float)i*map_value_forward_log(b,0.3333,3.0);
193
194        if (norm==1)
195                {
196                switch (cm)
197                        {
198                        case 0:  //rec 601
199                                {
200                                l = 0.299*rr + 0.587*gg + 0.114*bb;
201                                break;
202                                }
203                        case 1:  //rec 709
204                                {
205                                l = 0.2126*rr + 0.7152*gg + 0.0722*bb;
206                                break;
207                                }
208                        default:
209                                {
210                                l=(float)i;
211                                break;
212                                }
213                        }
214                if (l>0.0)
215                        {
216                        rr=rr*(float)i/l;
217                        gg=gg*(float)i/l;
218                        bb=bb*(float)i/l;
219                        }
220                else
221                        {
222                        rr=0.0; gg=0.0; bb=0.0;
223                        }
224                }
225
226        if (rr>255.0) rr=255.0;  if (rr<0.0) rr=0.0;
227        if (gg>255.0) gg=255.0;  if (gg<0.0) gg=0.0;
228        if (bb>255.0) bb=255.0;  if (bb<0.0) bb=0.0;
229        lut->r[i]=rintf(rr);
230        lut->g[i]=rintf(gg);
231        lut->b[i]=rintf(bb);
232        }
233}
234
235//----------------------------------------------------
236//F0R_COLOR_MODEL_RGBA8888  little endian
237void apply_lut(uint32_t* inframe, uint32_t* outframe, int size, lut_s *lut, int ac)
238{
239int i;
240uint32_t r,g,b,a;
241
242if (ac==0)
243        {
244        for (i=0;i<size;i++)
245                {
246                outframe[i] = lut->r[inframe[i]&255];
247                outframe[i] = outframe[i] + ((lut->g[(inframe[i]>>8)&255])<<8);
248                outframe[i] = outframe[i] + ((lut->b[(inframe[i]>>16)&255])<<16);
249                outframe[i] = outframe[i] + (inframe[i]&0xFF000000);
250                }
251        }
252else            //alpha controlled
253        {
254        for (i=0;i<size;i++)
255                {
256                a=(inframe[i]>>24)&255;
257                r = (255-a)*(inframe[i]&255) + a*lut->r[inframe[i]&255];
258                g = (255-a)*((inframe[i]>>8)&255) + a*lut->g[(inframe[i]>>8)&255];
259                b = (255-a)*((inframe[i]>>16)&255) + a*lut->b[(inframe[i]>>16)&255];
260                outframe[i] = r/255 + ((g/255)<<8) + ((b/255)<<16);
261                outframe[i] = outframe[i] + (inframe[i]&0xFF000000);
262                }
263        }
264}
265
266//-----------------------------------------------------
267//stretch [0...1] to parameter range [min...max] linear
268float map_value_forward(double v, float min, float max)
269{
270return min+(max-min)*v;
271}
272
273//-----------------------------------------------------
274//collapse from parameter range [min...max] to [0...1] linear
275double map_value_backward(float v, float min, float max)
276{
277return (v-min)/(max-min);
278}
279
280//----------------------------------------
281//struktura za instanco efekta
282typedef struct
283{
284int h;
285int w;
286float r,g,b;
287int act;
288int norm;
289int ac;
290int cm;
291lut_s *lut;
292} inst;
293
294//***********************************************
295// OBVEZNE FREI0R FUNKCIJE
296
297//-----------------------------------------------
298int f0r_init()
299{
300return 1;
301}
302
303//------------------------------------------------
304void f0r_deinit()
305{
306}
307
308//-----------------------------------------------
309void f0r_get_plugin_info(f0r_plugin_info_t* info)
310{
311
312info->name="coloradj_RGB";
313info->author="Marko Cebokli";
314info->plugin_type=F0R_PLUGIN_TYPE_FILTER;
315info->color_model=F0R_COLOR_MODEL_RGBA8888;
316info->frei0r_version=FREI0R_MAJOR_VERSION;
317info->major_version=0;
318info->minor_version=1;
319info->num_params=7;
320info->explanation="Simple color adjustment";
321}
322
323//--------------------------------------------------
324void f0r_get_param_info(f0r_param_info_t* info, int param_index)
325{
326switch(param_index)
327        {
328        case 0:
329                info->name = "R";
330                info->type = F0R_PARAM_DOUBLE;
331                info->explanation = "Amount of red";
332                break;
333        case 1:
334                info->name = "G";
335                info->type = F0R_PARAM_DOUBLE;
336                info->explanation = "Amount of green";
337                break;
338        case 2:
339                info->name = "B";
340                info->type = F0R_PARAM_DOUBLE;
341                info->explanation = "Amount of blue";
342                break;
343        case 3:
344                info->name = "Action";
345                info->type = F0R_PARAM_DOUBLE;
346                info->explanation = "Type of color adjustment";
347                break;
348        case 4:
349                info->name = "Keep luma";
350                info->type = F0R_PARAM_BOOL;
351                info->explanation = "Don't change brightness";
352                break;
353        case 5:
354                info->name = "Alpha controlled";
355                info->type = F0R_PARAM_BOOL;
356                info->explanation = "Adjust only areas with nonzero alpha";
357                break;
358        case 6:
359                info->name = "Luma formula";
360                info->type = F0R_PARAM_DOUBLE;
361                info->explanation = "";
362                break;
363        }
364}
365
366//----------------------------------------------
367f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
368{
369inst *in;
370
371in=calloc(1,sizeof(inst));
372in->w=width;
373in->h=height;
374in->r = 0.5;
375in->g = 0.5;
376in->b = 0.5;
377in->act=1;      //change gamma
378in->norm=1;     //keep luma
379in->ac=0;       //alpha controlled OFF
380in->cm=1;       //rec 709
381
382in->lut=(lut_s*)calloc(1,sizeof(lut_s));
383make_lut1(0.5,0.5,0.5,in->lut,0,1);
384
385return (f0r_instance_t)in;
386}
387
388//---------------------------------------------------
389void f0r_destruct(f0r_instance_t instance)
390{
391inst *in;
392
393in=(inst*)instance;
394
395free(in->lut);
396free(instance);
397}
398
399//-----------------------------------------------------
400void f0r_set_param_value(f0r_instance_t instance, f0r_param_t parm, int param_index)
401{
402inst *p;
403double tmpf;
404int tmpi,chg;
405
406p=(inst*)instance;
407
408chg=0;
409switch(param_index)
410        {
411        case 0:
412                tmpf=*(double*)parm;
413                if (tmpf!=p->r) chg=1;
414                p->r=tmpf;
415                break;
416        case 1:
417                tmpf=*(double*)parm;
418                if (tmpf!=p->g) chg=1;
419                p->g=tmpf;
420                break;
421        case 2:
422                tmpf=*(double*)parm;
423                if (tmpf!=p->b) chg=1;
424                p->b=tmpf;
425                break;
426        case 3:
427                tmpi=map_value_forward(*((double*)parm), 0.0, 2.9999);
428                if (tmpi != p->act) chg=1;
429                p->act=tmpi;
430                break;
431        case 4:
432                tmpi=map_value_forward(*((double*)parm), 0.0, 1.0); //BOOL!!
433                if (p->norm != tmpi) chg=1;
434                p->norm=tmpi;
435                break;
436        case 5:
437                tmpi=map_value_forward(*((double*)parm), 0.0, 1.0); //BOOL!!
438                if (p->ac != tmpi) chg=1;
439                p->ac=tmpi;
440                break;
441        case 6:
442                tmpi=map_value_forward(*((double*)parm), 0.0, 1.9999);
443                if (p->cm != tmpi) chg=1;
444                p->cm=tmpi;
445                break;
446        }
447
448if (chg==0) return;
449
450switch(p->act)
451        {
452        case 0:
453                make_lut1(p->r,p->g,p->b,p->lut,p->norm,p->cm);
454                break;
455        case 1:
456                make_lut2(p->r,p->g,p->b,p->lut,p->norm,p->cm);
457                break;
458        case 2:
459                make_lut3(p->r,p->g,p->b,p->lut,p->norm,p->cm);
460                break;
461        }
462
463}
464
465//--------------------------------------------------
466void f0r_get_param_value(f0r_instance_t instance, f0r_param_t param, int param_index)
467{
468inst *p;
469double tmpf;
470int tmpi;
471
472p=(inst*)instance;
473
474switch(param_index)
475        {
476        case 0:
477                *((double*)param)=p->r;
478                break;
479        case 1:
480                *((double*)param)=p->g;
481                break;
482        case 2:
483                *((double*)param)=p->b;
484                break;
485        case 3:
486                *((double*)param)=map_value_backward(p->act, 0.0, 2.9999);
487                break;
488        case 4:
489                *((double*)param)=map_value_backward(p->norm, 0.0, 1.0);//BOOL!!
490                break;
491        case 5:
492                *((double*)param)=map_value_backward(p->ac, 0.0, 1.0);//BOOL!!
493                break;
494        case 6:
495                *((double*)param)=map_value_backward(p->cm, 0.0, 1.9999);
496                break;
497        }
498}
499
500//-------------------------------------------------
501void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe)
502{
503inst *in;
504
505assert(instance);
506in=(inst*)instance;
507
508apply_lut(inframe,outframe,in->w*in->h, in->lut, in->ac);
509
510}
511
512//**********************************************************
Note: See TracBrowser for help on using the repository browser.