1 /*-----------------------------------------------------------------------
2     This file is part of aaphoto.
3 
4     aaphoto is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 3 of the License, or
7     (at your option) any later version.
8 
9     aaphoto is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 ------------------------------------------------------------------------*/
17 
18 
19 
20 
21 
22 /* --------------------------------------------------- */
23 /* ----------- Auto Adjust RGB ----------------------- */
24 /* ----------- András Horváth (C) 2006-2013 ---------- */
25 /* ----------- Hungary, http://log69.com ------------- */
26 /* --------------------------------------------------- */
27 
28 /*
29 
30 aaRGB Changelog:
31 ------------------
32 2013/09/30 - aaRGB v0.65 - fix some compile time warnings and uninitalized variables
33 2011/01/26 - aaRGB v0.64 - the contrast seemed strong with the default initial value of the former algorithm,
34                            so now constant optimized to the new contrast algorithm introduced in 0.63
35                          - add more detailed explanations to the contrast algorithm (in hungarian)
36 2010/12/18 - aaRGB v0.63 - include OpenMP defs in aargb.c too for standalone usage
37                          - fix some warning messages during build
38                          - make embedded test info image look more readable by changing the colors (--test switch)
39                          - change saturation algorithm from linear to exponential
40                          - improve contrast algorithm to include a self balance mechanism to avoid overexposure
41                            on images with large blank areas that have relatively small details
42                          - improve color balance algorithm to make it a bit more aggressive by raising the value
43                            of the color difference factor of the white and black point to the 3rd power
44                          - speed up process by skipping saturation part if no change is needed
45                          - some memory allocation check
46                          - some changes in documentation
47 2010/09/14 - aaRGB v0.62 - bugfix: an ugly misconception in my paralleled code caused weird behavior
48                            when using more threads
49                          - rewrite the code to suffice the ISO C90 ANSI standard C form (GCC -pedantic option)
50 2010/05/02 - aaRGB v0.61 - add OpenMP support for multi processing, all computing cycles paralleled
51                          - solve warning issues with some uninitialized variables
52                          - some code cleanup
53 2009/10/18 - aaRGB v0.60 - remove gamma handling of the lighter colors from the two-pole gamma computing
54                            by setting the gamma_interval_high from 0.9 to 1, it proved to be inefficient
55 2009/04/05 - aaRGB v0.59 - some more code cleanup
56 2009/02/22 - aaRGB v0.58 - code cleanup
57 2007/08/11 - aaRGB v0.57 - improve black and white point analyzing
58                            from now they are not scaled to perfect black and white, but to their darkest
59                            and brightest color that have maximum saturation to fix overexposure problem
60                          - improve saturation algorithm with full floating point computing and HSL conversion
61                            to fix over saturated colors
62                          - expand image information display with color balance circle for testing (--test switch)
63                          - remove text information from test display (--test switch)
64 2007/06/21 - aaRGB v0.56 - expand functionality with "apply only on selection" to process only the selected area
65 2007/04/03 - aaRGB v0.55 - maximize saturation limit with a predefined constant to avoid overexposure in saturation
66                            when reconverting the same image
67 2007/04/01 - aaRGB v0.54 - new two-pole gamma computing
68                          - new saturation compensation
69 2007/03/29 - aaRGB v0.53 - improve contrast computing to avoid underexposure
70 2007/02/25 - aaRGB v0.52 - improve image information display for testing (--test switch)
71 2007/02/16 - aaRGB v0.51 - improve average RGB color computing for more accurate color balance calibration
72 2007/01/04 - aaRGB v0.49 - stable working version with gamma handling and more clever image analyzing
73 2006/08/29 - aaRGB project begun...
74 
75 aaRGB end of Changelog.
76 
77 */
78 
79 
80 /* ---------------------------------------------------------------- */
81 /* -- Automatically adjusts contrast, color balance, gamma level -- */
82 /* -- and saturation of an RGB image ------------------------------ */
83 /* ---------------------------------------------------------------- */
84 
85 /*
86    pictures might need some contrast adjustment when their colors don't spread
87    the entire spectrum, usually when their darkest colors aren't dark enough and
88    the lightest colors not bright enough, this causing a veiled effect on them.
89 
90    sometime color balance adjustment is also necessary, when the brightest and darkest
91    colors of the image are not black and white enough, but they are shifted towards
92    some other color which may be the effect of the technology used,
93    or simply the environment changes the colors unrealistically.
94 
95    the procedure assumes that there must be some detail on the picture that's
96    supposed to be black (dark enough) and also white (bright enough) in real.
97    the automatic contrast and color balance process is built upon this.
98 
99    the overall (or average) brilliance of the image can be set by the gamma level.
100    this procedure makes sure that those pictures that seem too dark will be
101    corrected by this factor by changing the middle dark colors while not changing
102    the darkest and brightest colors.
103 
104    as the last step, a saturation adjustment takes place to intensify the colors
105    themselves if needed.
106 */
107 
108 
109 
110 #include <math.h>
111 #include <stdlib.h>
112 
113 
114 
115 /* ------------------------- */
116 /* ----- SIGN FUNCTION ----- */
117 /* ------------------------- */
118 
sgn(double x)119 int sgn(double x)
120 {
121     if (x <  0) { return -1; }
122     if (x >  0) { return  1; }
123 /*  if x is 0 then return 0 */
124     return 0;
125 }
126 
127 
128 
129 /* -------------------------------- */
130 /* ----- RGB - HSL CONVERSION ----- */
131 /* -------------------------------- */
132 
RGB_TO_HSL(double R,double G,double B,double * H1,double * S1,double * L1)133 void RGB_TO_HSL(double R, double G, double B, double *H1, double *S1, double *L1)
134 {
135     double H, S, L;
136     double LN, LK, LNX, LKX;
137 
138     if (R < 0) { R = 0; } if (R > 1) { R = 1; }
139     if (G < 0) { G = 0; } if (G > 1) { G = 1; }
140     if (B < 0) { B = 0; } if (B > 1) { B = 1; }
141 
142     H = 0;
143     S = 0;
144     L = 0;
145 
146     L = (R + G + B) / 3;
147 
148     /* To calculate the 'S' saturation value, first i determine the
149        maximum amount of how much i can stretch the RGB color elements
150        to their limits while keeping the same 'L' lightness and 'H' hue values */
151 
152     LN = R;
153     if (LN < G) { LN = G; }
154     if (LN < B) { LN = B; }
155     LK = R;
156     if (LK > G) { LK = G; }
157     if (LK > B) { LK = B; }
158     if (LN == LK) { S = 0; H = 0; }
159     else {
160         double R2, G2, B2;
161 
162         if ((LN < 1) && (LK > 0)) {
163             /* L cannot be either 0 or 1 here */
164             LKX = (L - LK) / L;
165             LNX = (LN - L) / (1 - L);
166             S = LNX;
167             if (LKX >= LNX) { S = LKX; }
168         }
169         else { S = 1; }
170 
171         /* To get the 'H' color value, i stretch the RGB elements to their maximum,
172            so it'll be a 6 case outcome. */
173 
174         LN = LN - LK;
175         R2 = (R - LK) / LN;
176         G2 = (G - LK) / LN;
177         B2 = (B - LK) / LN;
178 
179         if ((R2 == 1) && (G2 <  1) && (G2 >= 0) && (B2 == 0))  { H = (  0 +    G2  * 60) / 360; }
180         if ((G2 == 1) && (R2 <= 1) && (R2 >  0) && (B2 == 0))  { H = ( 60 + (1-R2) * 60) / 360; }
181         if ((G2 == 1) && (B2 <  1) && (B2 >= 0) && (R2 == 0))  { H = (120 +    B2  * 60) / 360; }
182         if ((B2 == 1) && (G2 <= 1) && (G2 >  0) && (R2 == 0))  { H = (180 + (1-G2) * 60) / 360; }
183         if ((B2 == 1) && (R2 <  1) && (R2 >= 0) && (G2 == 0))  { H = (240 +    R2  * 60) / 360; }
184         if ((R2 == 1) && (B2 <= 1) && (B2 >  0) && (G2 == 0))  { H = (300 + (1-B2) * 60) / 360; }
185 
186         if (H == 1) { H = 0; }
187     }
188 
189     *H1 = H; *S1 = S; *L1 = L;
190 
191 }
192 
193 
194 
HSL_TO_RGB(double H,double S,double L,double * R1,double * G1,double * B1)195 void HSL_TO_RGB(double H, double S, double L, double *R1, double *G1, double *B1)
196 {
197     double R = 0;
198     double G = 0;
199     double B = 0;
200 
201     if (H < 0) { H = 0; } if (H > 1) { H = 1; }
202     if (S < 0) { S = 0; } if (S > 1) { S = 1; }
203     if (L < 0) { L = 0; } if (L > 1) { L = 1; }
204 
205     if (L == 0) { R = 0; G = 0; B = 0; }
206     else {
207         if (L == 1) { R = 1; G = 1; B = 1; }
208         else {
209             double L2, templ;
210 
211             /* set the things here based on 'H' value */
212             int deg;
213             double mul;
214             if (H == 1) { H = 0; }
215             deg = (int)(H * 6);
216             mul = H * 6 - deg;
217 
218             switch (deg) {
219                 case 0:
220                     R = 1; G = mul;   B = 0; break;
221                 case 1:
222                     G = 1; R = 1-mul; B = 0; break;
223                 case 2:
224                     G = 1; B = mul;   R = 0; break;
225                 case 3:
226                     B = 1; G = 1-mul; R = 0; break;
227                 case 4:
228                     B = 1; R = mul;   G = 0; break;
229                 case 5:
230                     R = 1; B = 1-mul; G = 0; break;
231             }
232 
233             /* scale the things here in the RGB field by the value of 'L' */
234             L2 = (R + G + B) / 3;
235             if (L > L2) {
236                 templ = (1-L) / (1-L2);
237                 R = 1 - (1-R) * templ;
238                 G = 1 - (1-G) * templ;
239                 B = 1 - (1-B) * templ;
240             }
241             else {
242                 templ = L / L2;
243                 R = R * templ;
244                 G = G * templ;
245                 B = B * templ;
246             }
247 
248             /* scale the things here in the RGB field by the value of 'S' */
249             if (R > L) { R = L + (R-L) * S; } else { R = L - (L-R) * S; }
250             if (G > L) { G = L + (G-L) * S; } else { G = L - (L-G) * S; }
251             if (B > L) { B = L + (B-L) * S; } else { B = L - (L-B) * S; }
252         }
253     }
254 
255     *R1 = R; *G1 = G; *B1 = B;
256 
257 }
258 
259 
260 
261 /* ------------------------------------------------------------------------------ */
262 
AARGB_MAIN(unsigned char * image_buffer,int image_width,int image_height,int x1,int y1,int x2,int y2,int format_flag,int apply_on_selection,int test_flag)263 void AARGB_MAIN(
264     unsigned char *image_buffer,
265     int image_width,
266     int image_height,
267     int x1,
268     int y1,
269     int x2,
270     int y2,
271     int format_flag,
272     int apply_on_selection,
273     int test_flag)
274 {
275 
276 
277 /* ------------------------------------------------------------------------------ */
278 /* ----------  Global variables for the procedure  ------------------------------ */
279 /* ------------------------------------------------------------------------------ */
280 
281       int max_threads2;
282 
283       double cont_max;
284       double gamma_max;
285       double gamma_interval_low;
286       double gamma_interval_high;
287       double satur_max;
288 
289       double gamma_weight_low_all;
290       double gamma_weight_high_all;
291       double gamma_weight_low;
292       double gamma_weight_high;
293       double gamma_low;
294       double gamma_high;
295 
296       long hist1[256];
297       long hist2[256];
298       long hist3[256];
299       long *hist1n;
300       long *hist2n;
301       long *hist3n;
302       long hist_min;
303       long hist_max;
304       long hist_cut_columns;
305       long hist_cut_weight;
306       double hist_cut_limit;
307       double hist_avg;
308 
309 /*
310       long hist_sum;
311       long hist_min_test;
312       long hist_max_test;
313       double hist_avg_test;
314 */
315 
316       long hist_satur[256];
317       long  *hist_saturn;
318       double hist_satur_avg;
319       double hist_satur_low;
320       double hist_satur_ok;
321 
322       double temp1, temp2, temp3;
323       long flag1;
324       long bw, bh;
325       long x, y;
326       long i1, i2, i3;
327 
328       long col_r, col_g, col_b;
329       double col_r2, col_g2, col_b2;
330       unsigned long col_r3[256];
331       unsigned long col_g3[256];
332       unsigned long col_b3[256];
333       unsigned long *col_r3n;
334       unsigned long *col_g3n;
335       unsigned long *col_b3n;
336 
337       double H, S, L;
338 
339       double wp, bp;
340       double wp_end, bp_end;
341       double wp_r, wp_g, wp_b;
342       double bp_r, bp_g, bp_b;
343       double wp_r_end = 0, wp_g_end = 0, wp_b_end = 0;
344       double bp_r_end = 0, bp_g_end = 0, bp_b_end = 0;
345 
346       long cc;
347       long addr, addr2;
348       long addr_offset;
349       int N;
350 
351 
352       long col;
353       long xm, ym;
354       long xma1, xma2;
355       long xmb1, xmb2;
356       long color_black =       0x00000000;
357       long color_green =       0x0000ff00;
358       long color_brown =       0x00707000;
359       long color_blue =        0x000080ff;
360       long color_white =       0x00ffffff;
361       long color_gray =        0x00606060;
362       long color_red =         0x00a00000;
363       long color_yellow =      0x00ffff00;
364 /*    long color_green_dark =  0x00008000; */
365 
366 
367 	/* is there openmp support? */
368 	max_threads2 = 1;
369 	#ifdef __OPENMP__
370         /* get the number of available processors to know maximum number of threads */
371         max_threads2 = omp_get_num_procs();
372         /* set it to minimum 1 */
373         if (max_threads2 < 1){ max_threads2 = 1; }
374 	#endif
375 
376 
377 	/* allocate memory for the arrays that help to parallel cycles */
378 	/* the allocated memory here is way too small, so i don't print any error message on failure
379 	   cause i don't want to have stdio.h as a dependency for this procedure,
380 	   just simply exit */
381 
382 	hist_saturn = 0;
383 
384 	hist1n = 0;
385 	hist2n = 0;
386 	hist3n = 0;
387 
388 	col_r3n = 0;
389 	col_g3n = 0;
390 	col_b3n = 0;
391 
392 	if ((hist_saturn = calloc (256 * max_threads2, sizeof (*hist_saturn))) == 0){ goto exit; }
393 
394 	if ((hist1n = calloc (256 * max_threads2, sizeof (*hist1n))) == 0){ goto exit; }
395 	if ((hist2n = calloc (256 * max_threads2, sizeof (*hist2n))) == 0){ goto exit; }
396 	if ((hist3n = calloc (256 * max_threads2, sizeof (*hist3n))) == 0){ goto exit; }
397 
398 	if ((col_r3n = calloc (256 * max_threads2, sizeof (*col_r3n))) == 0){ goto exit; }
399 	if ((col_g3n = calloc (256 * max_threads2, sizeof (*col_g3n))) == 0){ goto exit; }
400 	if ((col_b3n = calloc (256 * max_threads2, sizeof (*col_b3n))) == 0){ goto exit; }
401 
402 
403 /* ------------------------------------------------------------------------------ */
404 /* Initialization and constants for the contrast and gamma (0...1) */
405 /* ------------------------------------------------------------------------------ */
406 /* Kezdõ értékek és konstansok megadása a kontraszt és gamma mûveletekhez */
407 
408 /* Kontraszt konstans megadása: megadja, hogy mekkora lehet az automata */
409 /* kontraszt állítás maximum értéke (0...1-ig terjedhet az értéke), */
410 /* alapértelmezett = 0.1 */
411 /* Gamma konstans megadása: megadja, hogy mekkora lehet az automatikus */
412 /* gamma állítás maximum értéke (1...10-ig ajánlott), */
413 /* alapértelmezett = 1.5 */
414 
415 /* Gamma állításhoz a maximum elõfordulás értékének megadása (occur_max), */
416 /* amely megadja, hogy a gamma érték számításánál ha ennél kisebb az */
417 /* elõfordulása a nagy mértékben elõforduló színeknek, akkor kihagyjuk õket a */
418 /* számításból, vagyis a nagy mértékben elõforduló színeket azért nem vesszük */
419 /* be a számításba, mert inkább a részletek látszódjanak jól, */
420 /* vagyis a részletekhez legyen inkább kiszámolva a megfelelõ fényerõ */
421 
422 
423 /* ------------------------------ */
424 /* Konstans értékek beállítása */
425 /* ------------------------------ */
426     /* maximális kontraszt mértéke (0..1) */
427     cont_max = 0.066666;
428 
429     /* maximális gamma korrekció mértéke (1..10) */
430     gamma_max = 1.5;
431     gamma_interval_low = 0.333;
432     gamma_interval_high = 1;
433 
434     /* maximális színtelítettség limit (0..1) */
435     satur_max = 0.333;
436 
437     bw = image_width;
438     bh = image_height;
439 
440     /* Kijelölt területhez a koordináták határértékeinek vizsgálata */
441     /* és megfelelõ beállítása */
442     /* A kijelölés célja, hogy egy meghatározott képrészletet szeretnénk jól */
443     /* láthatóvá tenni (nem pedig az egészet arányaiban) */
444 
445     /* a szélesség konvertálása abszolút koordinátává, jelenleg nem él */
446     /* x2 = x1 + x2 - 1; */
447     /* y2 = y1 + y2 - 1; */
448 
449     if (x1 < 0) { x1 = 0; }
450     if (x2 < 0) { x2 = 0; }
451     if (y1 < 0) { y1 = 0; }
452     if (y2 < 0) { y2 = 0; }
453     if (x1 > bw-1) { x1 = bw-1; }
454     if (x2 > bw-1) { x2 = bw-1; }
455     if (y1 > bh-1) { y1 = bh-1; }
456     if (y2 > bh-1) { y2 = bh-1; }
457     /* A DIB formátum 4-byte-os igazításához az eltolás értékének kiszámítása */
458     /* Normál tömbnél erre nincs szükség, ekkor a format_flag értéke = 0 */
459     /* egyébként a DIB formátumú tömb függõlegesen fordított sorokat tartalmaz, */
460     /* és a sorvégek 4 byte-tal vannak igazítva */
461     addr_offset = 0;
462     /* Format = 0 --> NORMAL 3 byte RGB data in array */
463     /* Format = 1 --> DIB data format in array */
464     /* Format = 2 --> BMP data format in array */
465     if ((format_flag == 1) || (format_flag == 2)){
466         y1 = bh - 1 - y1;
467         y2 = bh - 1 - y2;
468         addr_offset = bw * 3 - 4 * (bw * 3 / 4);
469         if (addr_offset) addr_offset = 4 - addr_offset;
470     }
471     /* Kijelölés koordinátáinak felcserélése, ha nem jó sorrendben adták meg, */
472     /* vagyis a bal felsõ sarok az x1 és y1, a jobb alsó pedig az x2 és y2 */
473     if (x1 > x2) { i1 = x1; x1 = x2; x2 = i1; }
474     if (y1 > y2) { i1 = y1; y1 = y2; y2 = i1; }
475 
476 
477 /* ------------------------------------------------------------------------------ */
478 /* Create Histogram and average RGB colors for the Image */
479 /* ------------------------------------------------------------------------------ */
480 /* Hisztogram generálása a kép színeibõl, ami a kép feényerõ eloszlását adja meg */
481 /* plusz a színegyensúly beállításához az egy fényerejû színek átlag RGB */
482 /* értékeinek letárolása, megelõlegezve egy késõbbi rutin munkáját */
483 
484 /* A kép minden egyes pontjának átlag fényereje (szürkéje) bekerül egy */
485 /* 256 elemû tömbbe, ahol a fényerejük értéke az azonos indexû elem értékét */
486 /* 1-gyel növeli */
487 
488 /* Így ez a hisztogram tömb pontos leírást ad a feketétõl a fehérig terjedõ */
489 /* színskálájáról a képnek */
490 
491     /* array initialization with zeros */
492     #ifdef __OPENMP__
493     #pragma omp parallel for num_threads(max_threads2)
494     #endif
495     for (i1=0; i1<256; i1++){
496         hist1[i1] = 0;
497         hist2[i1] = 0;
498         hist3[i1] = 0;
499         hist_satur[i1] = 0;
500         col_r3[i1] = 0;
501         col_g3[i1] = 0;
502         col_b3[i1] = 0;
503     }
504 
505     #ifdef __OPENMP__
506     #pragma omp parallel for private(x, y, addr, addr2, col_r, col_g, col_b, cc, N) num_threads(max_threads2)
507     #endif
508     for (y=0; y<=bh-1; y++){
509         addr2 = y * bw * 3 + y * addr_offset;
510         for (x=0; x<=bw-1; x++){
511             if (x >= x1 &&
512                 x <= x2 &&
513                 y >= y1 &&
514                 y <= y2) {
515 
516                 addr = addr2 + x * 3;
517                 col_r = image_buffer[addr + 0];
518                 col_g = image_buffer[addr + 1];
519                 col_b = image_buffer[addr + 2];
520                 cc = (col_r + col_g + col_b) / 3;
521 		/* multi processing, thread id */
522 #ifdef __OPENMP__
523 		N = omp_get_thread_num();
524 #else
525 		N = 0;
526 #endif
527                 /* szürke hisztogramm */
528                 hist1n[cc + N*256]++;
529                 /* Átlag RGB értékek letárolása a fekete és fehér pont */
530                 /* átlag RGB-jének későbbi megállapításához */
531                 col_r3n[cc + N*256] += col_r;
532                 col_g3n[cc + N*256] += col_g;
533                 col_b3n[cc + N*256] += col_b;
534             }
535         }
536     }
537 
538     /* this is a replacement code for arrays for multi processing */
539     #ifdef __OPENMP__
540     #pragma omp parallel for private(i1, i2) num_threads(max_threads2)
541     #endif
542     for (i1=0; i1<256; i1++){
543 	for (i2=0; i2<max_threads2; i2++){
544 		hist1[i1]  += hist1n[i1 + i2*256];
545 		col_r3[i1] += col_r3n[i1 + i2*256];
546 		col_g3[i1] += col_g3n[i1 + i2*256];
547 		col_b3[i1] += col_b3n[i1 + i2*256];
548 	}
549     }
550 
551 
552 /* ------------------------------------------------------------------------------ */
553 /* Start analyzing to find the White and Black points */
554 /* ------------------------------------------------------------------------------ */
555 /* Az automata kontraszt beállításához a Fekete és Fehér pont megállapítása */
556 
557 /* A hisztogram bal és jobb oldaláról elkezdem beolvasni a szürke értékek */
558 /* nagyságát és addig olvasom be, amíg az nem nagyobb egy elõre meghatározott */
559 /* értéknél, ekkor megkapom a fekete és fehér pont helyzetét */
560 
561 /* Ez az elõre meghatározott érték a kontraszt konstans és a hisztogram */
562 /* összes tömbeleme átlagának a szorzata */
563 /* Az átlag szorzat egyensúlyt teremt a határérték elérésénél, mert egyébként */
564 /* ha ez az érték mondjuk a hisztogram maximum értéke lenne, akkor */
565 /* drasztikus kontraszt túlállítás jellemezné a funkciót */
566 
567 /* Vagyis ez az érték azt adja meg, hogy a kép átlag fényerejének hány */
568 /* százaléka az az érték, amely a továbbiakban megadja, hogy az ekkora */
569 /* százalék alatt található feketék és fehérek lesznek kihúzva a határig (le lesznek vágva)*/
570 
571     hist_min = bw * bh;
572     hist_max = 0;
573     hist_avg = 0;
574 
575     /* Átlag fényerõ kiszámítása: ezt úgy kapom meg, hogy összeadom a histogramm
576     összes oszlopát és osztom 256-al (oszlopok száma), vagyis matematikai átlaga.
577     Ezt még leosztom egy konstanssal (10%-ára alapból) úgy, hogy nullánál kisebbel szorzok,
578     az így kapott értéket nevezem itt limit-nek.
579 
580     (a maximum és minimum érték számítása csak tesztelési céllal él)
581     */
582     for (i1=0; i1<256; i1++){
583         temp1 = hist1[i1];
584         if (hist_min > (long)temp1){ hist_min = (long)temp1; }
585         if (hist_max < (long)temp1){ hist_max = (long)temp1; }
586         hist_avg = hist_avg + temp1;
587     }
588     /* histogram teljes összege */
589 /*    hist_sum = hist_avg; */
590 
591     /* histogram matematikai átlag értéke */
592     hist_avg = hist_avg / 256;
593 
594 /*
595     hist_min_test = hist_min;
596     hist_max_test = hist_max;
597     hist_avg_test = hist_avg;
598 */
599 
600     /* ez lesz itt a limit */
601     temp1 = hist_avg * cont_max;
602     hist_cut_limit = temp1;
603 
604 
605 
606     /* fehér és feketepont keresése 0 (nulla) maximumig */
607 
608     bp = 255;
609     flag1 = 0;
610 
611     for (i1=0; i1<256; i1++){
612         if (flag1 == 0){
613             if (hist1[i1] > 0){
614                 flag1 = 1;
615                 bp = i1;
616             }
617         }
618     }
619 
620     wp = 0;
621     flag1 = 0;
622     hist_cut_columns = 0;
623 
624     for (i1=255; i1>=0; i1--){
625         if (flag1 == 0){
626             if (hist1[i1] > 0){
627                 flag1 = 1;
628                 wp = i1;
629             }
630         }
631     }
632 
633     if (bp > wp){
634         i1 = (long)(wp);
635         wp = bp;
636         bp = i1;
637     }
638     if (bp == wp){
639        bp = bp - 1;
640        wp = wp + 1;
641     }
642     if (bp < 0){ bp = 0; }
643     if (bp >= 255){ bp = 254; }
644     if (wp > 255){ wp = 255; }
645     if (wp <= 0){ wp = 1; }
646 
647 
648     /* -----------------------------------------------------------------------------------
649     Az automatikus kontraszt állító algoritmus néha olyan bemenetet is kaphat,
650     ahol a részletek a képen túl kis mennyiségben vannak jelen, és nagy terjedelmű
651     egy színű részek a jellemzőek - ekkor az volt a jelenség, hogy az algoritmus
652     túl nagyot vág le a hisztogram széléből, és az ezen a képen fontosabb kis mennyiségű
653     részlet veszik el.
654 
655     Ezért beillesztettem az algoritmusba egy önszabályozó mechanizmust, amelynél ha
656     felmerül a fenti eset, akkor jó esély van rá, hogy a részletek maradnak meg inkább
657     a kontraszt állítás után.
658 
659     Ez úgy történik, hogy megnézem, mennyi oszlop esik a limit érték alá, és ennek függvényében
660     tovább csökkentem ezt a limit-et, mivel minél több rész esik az átlag alá (oszlopok száma a hisztogramban),
661     ez azt jelenti hogy annál több a képen az olyan érdekes részlet, amely levágásra kerülne,
662     ezért a sok és meghatározó nagy üres részek kevésbé kellene hogy számítsanak.
663 
664     A limit értéket az alábbi módon húzom tovább lefelé: újra fogom kalkulálni az átlagot
665     és ezt a limit értéket is úgy, hogy a kalkuláció során az ez fölé eső oszlop értékek
666     kevésbé számítsanak, ha minél több az előzőkben a limit érték alatti részek oszlopainak száma,
667     és ha ezen oszlopok magasságának összegei is minél kisebbek,
668     mert így tudjuk meg, hogy egyre kisebb területen van az értékes részlet.
669 
670     Ez így egy önfékező folyamatot eredményez a nagy üres területek átlaga okozta túl nagy limit értékhez,
671     és ezzel a túl nagy kontraszt levágáshoz, ahol is pont a részlet veszik el.
672 
673     Ezek után újra kalkulálom ezt a limit értéket az előző módon,
674     és ezzel lesz tovább kalkulálva a histogram szélek levágása.
675 
676     Hogy mennyire számítson a kis kép részlet, azt is analóg módon akarom eldönteni,
677     tehát úgy, hogy az eredeti limit érték módosulása ne szakaszos módon történjen,
678     viszont mivel úgy gondolom, hogy olyan görbére van szükségem, amely a 0-1 intervallumon
679     a feléig nagyon kicsit emelkedik, majd innét drasztikusabban,
680     ezért az 5. hatványt szorozva 3-mal találtam a megfelelőnek.
681 
682     f(x) = x^5*3
683     Wolphram Aplha link a szemléltetéshez:
684     http://www.wolframalpha.com/input/?i=x^5+*+3+from+0+to+1
685 
686     Ennek mentén, ha a kis és nagy részlet egyensúly felborul, akkor
687     a 0.5 től felfelé kezd a kontraszt számítás egyre kevésbé drasztikusba átmenni,
688     és ezzel érem el, hogy a kisebb értékek lehetőleg minél kevésbé,
689     míg a nagyobb értékek egyre jobban folyásolják be ezt.
690     -------------------------------------------------------------------------------------- */
691 
692 
693     /* azért csak a fekete és fehér pont közötti szakaszt vizsgálom
694        (ez a hisztogramm megmaradó szélessége a bal és jobb oldali levágás után)
695        mert a tervezett végleges eredményen akarom vizsgálni a részlet mennyiségének arányát
696        a teljes terjedelemhez képest (amennyi maradna belőle).
697     */
698 
699     hist_cut_columns = 0;
700     hist_cut_weight = 0;
701     for (i1=bp; i1<wp; i1++){
702         if (hist1[i1] < temp1){
703             hist_cut_columns++;
704             hist_cut_weight += hist1[i1];
705         }
706     }
707 
708 
709     /* temp1 mutatja az eredeti levágandó limit értéket,
710        hist_cut_columns mutatja a limit alatti oszlopok számát (ezt nevezem limit alatti részletnek),
711        hist_cut_weight mutatja ezen oszlopok értékének összegét (súlyát),
712 
713        temp2-t pedig úgy állítom be, hogy minél nagyobb súly oszlik el kevesebb oszlop számon
714        (vagyis minél kevesebb oszlop van a limit alatt és ezeknek a súlya minél nagyobb),
715        úgy ennek is annál nagyobb lesz az értéke - vagyis ha temp2-nek nagyobb az értéke,
716        az azt jelenti hogy annál több értékes részlet van a limit alatt.
717 
718        azért nevezem a limit alatti oszlopokat értékesebb részletnek, mert a teljes hisztogramm átlagot
719        elhúzzák felfelé a nagy egyszínű részek, amelyek kevés oszlopok nagy súllyal,
720        vagyis ezek nyilván nagyobb terjedelmű üres részek - tehát ezek maguk a "nem" részletek,
721        míg ezen átlag alattiakat veszem a részletnek.
722 
723        mivel a limit alatti oszlopokat nézzük, ezért leosztva magával a limit értékkel, egy
724        0..1 intervallumos arány értéket kapok.
725     */
726     if ((hist_cut_columns == 0) || (temp1 == 0)){ temp2 = 0; }
727     else { temp2 = (double)(hist_cut_weight) / hist_cut_columns / temp1; }
728 
729 
730     /* itt temp3 értékét úgy határozom meg, hogy az eredeti limit alatti oszlopok számát
731        osztom a histogram középső (levágás utáni) megmaradt szélességével (wp-bp)
732        (de csak a megmaradandó szakaszon, ezért az eredmény 0..1 közötti lesz),
733 
734        vagyis minél nagyobb rész esik le bal és jobb oldalt, annál kisebb értékkel osztunk,
735        és ha a limit alatti oszlopok száma egyre több, akkor ezt minél kisebb értékkel osztva
736        annál nagyobb számot kapunk, ezért annál drasztikusabbnak vehetjük az eredetileg alkalmazandó kontrasztot,
737        és ezért ezt az értéket az 5. hatványra emelve és szorozva 3-mal - olyan értéket eredményez,
738        mely 50% fölött egyre nagyobb értéket ad vissza, és itt minél nagyobb az érték,
739        annál jobban csökkentem az eredeti tervezett kontraszt (levágás) mértékét.
740     */
741     temp3 = (double)(hist_cut_columns) / (wp-bp);
742 
743     /* itt a lineáris értéket hatványra emeléssel görbítem, hogy a kisebb értékek kevésbé,
744     míg a nagyobb értékek egyre jobban befolyásolják az eredményt */
745     temp3 = temp3 * temp3 * temp3 * temp3 * temp3 * 3;
746     if (temp3 > 1){ temp3 = 1; }
747 
748     /* itt temp1 (eredeti limit érték) alatt keletkezett temp2 (új limit érték)
749        limit vonalat visszahúzom felfelé az eredeti temp1 felé a temp3-as görbe alapján.
750 
751        vagyis a drasztikus kontrasztot lecsökkentettem, majd vissza engedem a görbe alapján
752        (amelynél kb. 50% után görbül drasztikusan).
753     */
754     temp3 = temp1 - ((temp1 - temp2) * temp3);
755     /* itt nem engedem hogy az új csökkentett limit érték az eredeti 10% alá menjen,
756        ez csupán egy alsó korlát a kontraszt csökkentés mértékéhez */
757     if (temp3 < temp1 * 0.1){ temp1 = temp1 * 0.1; }
758     else{ temp1 = temp3; }
759 
760     hist_cut_limit = temp1;
761 
762 /* ------------------------------------------------------------ */
763 
764 
765     bp = 255;
766     flag1 = 0;
767 
768     /* histogram jobb oldaláról lépkedek és vágom majd le addig az értékig,
769     amely még kisebb mint az átlag * cont_max (átlag 10 %-a) */
770     for (i1=0; i1<256; i1++){
771         if (flag1 == 0){
772             if (hist1[i1] >= temp1){
773                 flag1 = 1;
774                 bp = i1;
775             }
776         }
777     }
778 
779     wp = 0;
780     flag1 = 0;
781     hist_cut_columns = 0;
782 
783     for (i1=255; i1>=0; i1--){
784         if (flag1 == 0){
785             if (hist1[i1] >= temp1){
786                 flag1 = 1;
787                 wp = i1;
788             }
789         }
790     }
791 
792     /* Határértékek beállítása és korrekciója */
793     if (bp > wp){
794         i1 = (long)(wp);
795         wp = bp;
796         bp = i1;
797     }
798     if (bp == wp){
799        bp = bp - 1;
800        wp = wp + 1;
801     }
802     if (bp < 0){ bp = 0; }
803     if (bp >= 255){ bp = 254; }
804     if (wp > 255){ wp = 255; }
805     if (wp <= 0){ wp = 1; }
806 
807     bp = bp / 255;
808     wp = wp / 255;
809 
810 
811 
812 /* ------------------------------------------------------------------------------ */
813 /* Get the average RGB values for the White and Black points */
814 /* ------------------------------------------------------------------------------ */
815 /* A színegyensúly beállításához az átlag RGB értékek kiszámítása */
816 /* a fekete és fehér pont értéke alapján */
817 
818 /* Itt keletkezik egy átlag RGB érték a fekete és fehér pontokhoz egyaránt */
819 /* Ez az érték azt adja meg, hogy az automatikus kontraszt állításakor */
820 /* minden egyes szín milyen irányba torzul lefelé (fekete pont RGB átlaga) */
821 /* és felfelé (fehér pont RGB átlaga) */
822 
823 /* A fehér pont feletti összes szín átlagának RGB-je lesz a viszonyítási pont */
824 /* a fehér írányába való torzításhoz, */
825 /* vagyis ez lesz kihúzva a tökéletes fehérbe */
826 
827 /* Ez valóságban a kép színegyensúlyát állítja be megfelelõen úgy, hogy a */
828 /* levágandó mértékû fehérek színátlaga lesz a tökéletes fehér, */
829 /* ezért ha ezek átlaga nem tökéletes fehér, akkor az ettõl eltérõ nagyságot */
830 /* minden színnél arányosan el kell tolni a tökéletes fehér irányába, */
831 /* ugyanez a fekete estében */
832 
833     bp_r = 0;
834     bp_g = 0;
835     bp_b = 0;
836     wp_r = 0;
837     wp_g = 0;
838     wp_b = 0;
839 
840     i3 = 0;
841     /* fekete pont alatti összes szín RGB átlagának kiszámítása */
842     #ifdef __OPENMP__
843     #pragma omp parallel for reduction(+:bp_r, bp_g, bp_b, i3) num_threads(max_threads2)
844     #endif
845     for (i1=(long)(bp * 255); i1>=0; i1--){
846         bp_r += col_r3[i1];
847         bp_g += col_g3[i1];
848         bp_b += col_b3[i1];
849         i3 += hist1[i1];
850     }
851 
852     if (i3 > 0){
853         bp_r = bp_r / i3;
854         bp_g = bp_g / i3;
855         bp_b = bp_b / i3;
856     }
857 
858     i3 = 0;
859     /* fehér pont feletti összes szín RGB átlagának kiszámítása */
860     #ifdef __OPENMP__
861     #pragma omp parallel for reduction(+:wp_r, wp_g, wp_b, i3) num_threads(max_threads2)
862     #endif
863     for (i1=(long)(wp * 255); i1<256; i1++){
864         wp_r += col_r3[i1];
865         wp_g += col_g3[i1];
866         wp_b += col_b3[i1];
867         i3 += hist1[i1];
868     }
869     if (i3 > 0){
870         wp_r = wp_r / i3;
871         wp_g = wp_g / i3;
872         wp_b = wp_b / i3;
873     }
874 
875     /* skálázás 255-ről a [0..1] intervallumra */
876     bp_r = bp_r / 255;
877     bp_g = bp_g / 255;
878     bp_b = bp_b / 255;
879     wp_r = wp_r / 255;
880     wp_g = wp_g / 255;
881     wp_b = wp_b / 255;
882 
883     /* A kapott átlag RGB érték fényerejének visszaállítása a fehér pont szintjére. */
884     /* Mivel ugye nem csak a fehér pont fényerejével azonos színeknek kalkuláltuk ki */
885     /* az átlag színét, hanem az attól világosabb összes színnek, ezért a kapott */
886     /* átlag szín fényereje nagyobb vagy egyenlő lesz, mint a kiindulási fehér pont */
887     /* ezért a korrekcióhoz visszaállítjuk az RGB érték fényerejét */
888     /* de az R, G és B komponensek arányának a megtartásával */
889     /* és ugyanez a fekete pont esetében */
890     RGB_TO_HSL (bp_r, bp_g, bp_b, &H, &S, &L);
891     L = bp;
892     HSL_TO_RGB (H, S, L, &bp_r, &bp_g, &bp_b);
893     RGB_TO_HSL (wp_r, wp_g, wp_b, &H, &S, &L);
894     L = wp;
895     HSL_TO_RGB (H, S, L, &wp_r, &wp_g, &wp_b);
896 
897     /* A fekete és fehér pont célpontjának kiszámítása. */
898     /* Ez mutatja meg, hogy a fekete és fehér pont átlag RGB-jét */
899     /* hova kell húzni úgy, hogy az RGB kockában a két csúcsot */
900     /* összekötő 'szürke' egyenessel párhuzamosan tolva a távolsága */
901     /* a 'szürke' egyenestől és a színiránya megmaradjon, */
902     /* de a lehető legsötétebb- vagy legvilágosabb legyen */
903     /* */
904     /* Másképpen fogalmazva eltoljuk a szürke egyenes mentén addig, */
905     /* amíg az RGB kocka falába nem ütközünk (mindkét iránynál) */
906     /* */
907     /* Ez  annyiban változtatás az előzőkhöz képest, hogy a fekete pontot */
908     /* most már nem a tökéletes feketébe húzzuk, hanem az annak megfelelő */
909     /* olyan legsötétebb pontba, ahol a maximum a színtelítettség */
910     /* és aminek színe megegyezik a fekete pontéval, */
911     /* ezzel a rossz színegyensúlyt és nem megfelelő kontrasztot küszöbölöm ki. */
912 
913     temp3 = bp_r;
914     if (temp3 > bp_g) { temp3 = bp_g; }
915     if (temp3 > bp_b) { temp3 = bp_b; }
916     /*bp_r_end = 1 - (1 - bp_r) / (1 - temp3); */
917     /*bp_g_end = 1 - (1 - bp_g) / (1 - temp3); */
918     /*bp_b_end = 1 - (1 - bp_b) / (1 - temp3); */
919     bp_r_end = bp_r - temp3;
920     bp_g_end = bp_g - temp3;
921     bp_b_end = bp_b - temp3;
922 
923     temp3 = wp_r;
924     if (temp3 < wp_g) { temp3 = wp_g; }
925     if (temp3 < wp_b) { temp3 = wp_b; }
926     if (temp3 > 0){
927         wp_r_end = wp_r / temp3;
928         wp_g_end = wp_g / temp3;
929         wp_b_end = wp_b / temp3;
930     }
931 
932 
933 
934 /* ----------------- */
935 /* ---- RGB TÉR ---- */
936 /* ----------------- */
937 /* A teljes RGB teret egy szabályos 3D-s kocka foglalja magába, */
938 /* amelynek 1-1 éle jelenti a R, a G és a B tengelyt */
939 /* és egyik csúcsában található a tökéletes fehér szín, */
940 /* a másik (ezzel szemköti) csúcsában pedig a tökéletes fekete */
941 /* és ezt a két csúcsot összekötő egyenes tartalmazza a */
942 /* feketétől fehérig terjedő teljes szürke skálát. */
943 /* A színeltolás mértéke pedig nem más, mint az adott szín */
944 /* távolsága merőleges írányban szürke skála egyenesétől */
945 /* (amit egy 0 és 1 közötti érték jellemezhet, ahol a 0 */
946 /* azt jelenti, hogy a szín szürke, vagyis az egyenesen található) */
947 /* */
948 /* ------------------------- */
949 /* ---- RGB SZÍN IRÁNYA ---- */
950 /* ------------------------- */
951 /* A fekete és fehér pont átlag eltolási RGB értékét összehasonlítom, */
952 /* hogy megállapítsam, vajon megegyező irányban vannak-e eltolva, */
953 /* mivel ha nem jó a kép színegyensúlya, akkor feltételezem, hogy */
954 /* a kép összes színe a színegyensúly felborulását okozó tényező miatt */
955 /* megegyező irányban tolódik el. Ha nem megegyező irányba mutat */
956 /* az eltolásuk értéke, akkor feltételezem, hogy ez nem azért van, */
957 /* mert a színegyensúly felborult. Ekkor a kontraszt műveletnél nem */
958 /* alkalmazok színegyensúly kiegyenlítést (vagyis a kép színeinek */
959 /* a tökéletes fehér és tökéletes fekete irányába való RGB korrekcióját). */
960 /* */
961 /* Egy adott szín irányán az RGB kockában található pontjából kiinduló */
962 /* merőleges szakasz körülforgási szögét értem a szürke egyenesre nézve. */
963 /* Ennek értéke -180 és 180 fok közé kell hogy essen. */
964 /* Így a fekete és fehér pont átlag RGB színeinek iránya megad két szöget. */
965 /* Ennek különbsége adja meg, hogy milyen mértékkel kell színegyensúly */
966 /* kompenzációt végezni. Minél jobban egyírányba mutatnak, annál erősebb */
967 /* színkompenzáció szükséges. */
968 
969 
970 
971 /* ------------------------------------------------------------------------------------ */
972 /* Get RGB color directions of the White and Black points and change average RGB colors */
973 /* ------------------------------------------------------------------------------------ */
974 /* Megállapítjuk a fekete és fehér pont átlag RGB értékeinek irányát */
975 /* Ez két szöget ad vissza, és ennek a különbségét vizsgáljuk, */
976 /* minél kevésbé eltérő, az átlag RGB értékeket annál jobban lecseréljük */
977 /* a tökéletes fekete és fehér értékre, így a kontraszt állításnál */
978 /* jobban keletkezik színegyensúly korrekció */
979 /* */
980 /* Mivel az irányuk egy 360˚-os szöget zár be, és az eltérő színek 60˚-onként vannak, */
981 /* ezért a 60˚-nál nagyobb eltérést teljesen különbözőnek vesszük. */
982 /* Vagyis a 60˚-nál kisebb eltérésnél toljuk csak el arányosan a fekete és */
983 /* fehér pont célpontját a tökéletes fekete és a tökéletes fehér írányába */
984 /* (vagyis egyező irány esetén teljes színkorrekció lép fel) */
985 
986     RGB_TO_HSL (bp_r_end, bp_g_end, bp_b_end, &H, &S, &L);
987     temp1 = H;
988     RGB_TO_HSL (wp_r_end, wp_g_end, wp_b_end, &H, &S, &L);
989     temp2 = H;
990     temp2 = temp2 - temp1;
991 
992     /* change value to positive */
993     if (temp2 < 0)   { temp2 = 0 - temp2; }
994     /* if angle of direction is larger than 180 degree, then take the smaller section of the circle,
995        it means it'll always be less or equal than 180 deg */
996     if (temp2 > 0.5) { temp2 = 1 - temp2; }
997     /* if the angle is greater then 60 degree, that means the colors are totally different,
998        so i check the amount of difference on this 1/6 intervall only from 0 to 60 degrees. */
999     temp2 = temp2 * 6;
1000     if (temp2 > 1){ temp2 = 1; }
1001 
1002     /* raise the value (0..1) of angle difference to 3th power to make color balance a bit more aggressive */
1003     temp2 = temp2 * temp2 * temp2;
1004 
1005     /* Ezzel megvan az iránykülönbség értéke egy [0..1] intervallumon, */
1006     /* ahol a 0 a teljes egyezést mutatja */
1007     /* most az egész 'kör' hatod részét vizsgálom csak és */
1008     /* abból alakítok ki egy értéket a [0..1] intervallumon, */
1009     /* hogy majd ezzel szorozni tudjam a fekete pont fényerejét, */
1010     /* vagyis ha egyeznek az írányok, akkor tökéletes feketébe megy el */
1011     /* ugyanez a fehér pont esetében */
1012     if (temp2 < 1) {
1013         RGB_TO_HSL (bp_r_end, bp_g_end, bp_b_end, &H, &S, &L);
1014         L = L * temp2;
1015         HSL_TO_RGB (H, S, L, &bp_r_end, &bp_g_end, &bp_b_end);
1016         RGB_TO_HSL (wp_r_end, wp_g_end, wp_b_end, &H, &S, &L);
1017         L = 1 - (1 - L) * temp2;
1018         HSL_TO_RGB (H, S, L, &wp_r_end, &wp_g_end, &wp_b_end);
1019     }
1020     wp_end = (wp_r_end + wp_g_end + wp_b_end) / 3;
1021     bp_end = (bp_r_end + bp_g_end + bp_b_end) / 3;
1022 
1023 
1024 
1025 /* ------------------------------------------------------------------------------ */
1026 /* Convert original Histogram using White and Black point values */
1027 /* ------------------------------------------------------------------------------ */
1028 /* Eredeti hisztogramból a fekete és fehér pont alapján megváltoztatott */
1029 /* hisztogram létrehozása */
1030 
1031 /* Nem az egész kép újraanalizálása, hanem csak az eredeti hisztogramé, */
1032 /* mert így csak 256 értéket kell feldolgozni a kép összes pontjai számának */
1033 /* helyett. Ez a hisztogram az automatikus kontraszt állítás utáni állapotát */
1034 /* mutatja a képnek */
1035 
1036 /* Ez a hisztogram lesz felhasználva a gamma súlypont megállapításához */
1037 
1038     #ifdef __OPENMP__
1039     #pragma omp parallel for private(temp2, temp3, cc, N) num_threads(max_threads2)
1040     #endif
1041     for (i1=0; i1<256; i1++){
1042 
1043 	temp2 = (double)(i1) / 255;
1044 
1045         /* bp-től és wp-től viszonyított nullára húzással a kontraszt számolás az alábbi */
1046         /*temp2 = bp + ((temp2 - bp) * (1 - bp) / (wp - bp)); */
1047         /*temp2 = 1 - (1 - temp2) * 1 / (1 - bp); */
1048 
1049         /* teljes intervallumon számolt húzással a kontraszt számolás az alábbi */
1050         /*temp2 = temp2 * wp_end / wp; */
1051         /* ---> bp = bp * wp_end / wp; */
1052         /* ---> bp_end = bp_end * wp_end / wp; */
1053         /*temp2 = 1 - (1 - temp2) * (1 - bp_end * wp_end / wp) / (1 - bp * wp_end / wp); */
1054 
1055         /* bp_end-től és wp_end-től viszonyított bp-ből és wp-ből húzással a kontraszt számolás az alábbi */
1056         if ((temp2 > bp_end) && (wp > bp_end)) {
1057 		temp2 = bp_end + (temp2 - bp_end) * (wp_end - bp_end) / (wp - bp_end); }
1058         /* itt a bp fekete pontot is fel kell szorozni a következő számításhoz, */
1059         /* mert a bp_end -től viszonyítva nyújtjuk a skálát jobbra a fehér irányába */
1060         /* és ezért elmászik a bp */
1061 	temp3 = 0;
1062         if (wp > bp_end) {
1063 		temp3 = bp_end + (bp - bp_end) * (wp_end - bp_end) / (wp - bp_end); }
1064         if ((temp2 < wp_end) && (wp_end != temp3)) {
1065 		temp2 = wp_end - (wp_end - temp2) * (wp_end - bp_end) / (wp_end - temp3); }
1066         /*az 'if' utasításoknál mindenhol vizsgálom hogy ne lehessen nullával való osztás */
1067 
1068         if (temp2 > 1){ temp2 = 1; }
1069         if (temp2 < 0){ temp2 = 0; }
1070         cc = (long)(temp2 * 255);
1071 #ifdef __OPENMP__
1072 	N = omp_get_thread_num();
1073 #else
1074 	N = 0;
1075 #endif
1076         hist2n[cc + N*256] += hist1[i1];
1077     }
1078 
1079     /* this is a replacement code for arrays for multi processing */
1080     #ifdef __OPENMP__
1081     #pragma omp parallel for private(i1, i2) num_threads(max_threads2)
1082     #endif
1083     for (i1=0; i1<256; i1++){
1084         for (i2=0; i2<max_threads2; i2++){ hist2[i1] += hist2n[i1 + i2*256]; } }
1085 
1086 
1087 
1088 /* ------------------------------------------------------------------------------ */
1089 /* Gamma value calculating */
1090 /* ------------------------------------------------------------------------------ */
1091 /* Gamma súlypont megállapítása a második hisztogram alapján, ami már az */
1092 /* állított kontraszt utáni helyzetet mutatja */
1093 /* A végeredmény azt adja meg, hogy mennyire kell világosítani, vagy éppen */
1094 /* sötétíteni a képet, hogy az össz fényereje a képnek egyensúlyban legyen */
1095 
1096 /* A gamma súlypont az az érték, amely a hisztogramban azt mutatja, */
1097 /* hogy tõle balra és jobbra egyaránt egyforma számú képpont található */
1098 /* (vagyis fele a kép összes pontjainak) */
1099 
1100 /* Ezt úgy kapjuk meg, hogy elkezdjük olvasni a hisztogram értékeit az */
1101 /* egyik oldalról befelé, és közben össze adjuk a kapott értékeket */
1102 /* Ha ez az érték elérte vagy túllépte a kép összes pontjainak a számának */
1103 /* felét, akkor megállunk és a tömb aktuális indexe adja meg */
1104 /* a gamma súlypont megfelelõ értékét */
1105 
1106 /*
1107     gamma_weight_mid_all = 0;
1108     for (i1=0;   i1<256; i1++){ gamma_weight_mid_all  += hist2[i1]; }
1109     i3 = 0;
1110     flag1 = 0;
1111     gamma_weight_mid = 0;
1112     for (i1=0; i1<256; i1++){
1113         i3 = i3 + hist2[i1];
1114         if (flag1 == 0){
1115             if (i3 > gamma_weight_mid_all / 2){
1116                 flag1 = 1;
1117                 gamma_weight_mid = i1;
1118             }
1119         }
1120     }
1121     gamma_weight_mid = gamma_weight_low / 255;
1122     gamma_mid = 1;
1123     gamma_mid = log(gamma_interval_mid) / log(gamma_weight_mid);
1124     if (gamma_mid < (1/gamma_max)){ gamma_mid = (1/gamma_max); }
1125     if (gamma_mid > gamma_max){ gamma_mid = gamma_max; }
1126 */
1127     /* Convert CONTRAST Histogram using MID GAMMA VALUE */ /*
1128     for (i1=0; i1<256; i1++){
1129         temp2 = i1;
1130         temp2 = pow(temp2 / 255, gamma_mid) * 255;
1131         i2 = (long)temp2;
1132         if (i2 > 255){ i2 = 255; }
1133         if (i2 < 0){ i2 = 0; }
1134         hist2b[i2] = hist2b[i2] + hist2[i1];
1135     }
1136 */
1137 
1138     /* Hisztogramm súlyának megállapítása */
1139     gamma_weight_low_all = 0;
1140     gamma_weight_high_all = 0;
1141 
1142     #ifdef __OPENMP__
1143     #pragma omp parallel for reduction(+:gamma_weight_low_all) num_threads(max_threads2)
1144     #endif
1145     for (i1=0;   i1<128; i1++){ gamma_weight_low_all  += hist2[i1]; }
1146     #ifdef __OPENMP__
1147     #pragma omp parallel for reduction(+:gamma_weight_high_all) num_threads(max_threads2)
1148     #endif
1149     for (i1=128; i1<256; i1++){ gamma_weight_high_all += hist2[i1]; }
1150 
1151     /* Hisztogramm súlypont megállapítása */
1152     i3 = 0;
1153     flag1 = 0;
1154     gamma_weight_low = 0;
1155     for (i1=0; i1<128; i1++){
1156         i3 = i3 + hist2[i1];
1157         if (flag1 == 0){
1158             if (i3 > gamma_weight_low_all / 2){
1159                 flag1 = 1;
1160                 gamma_weight_low = i1;
1161             }
1162         }
1163     }
1164     i3 = 0;
1165     flag1 = 0;
1166     gamma_weight_high = 0;
1167     for (i1=128; i1<256; i1++){
1168         i3 = i3 + hist2[i1];
1169         if (flag1 == 0){
1170             if (i3 > gamma_weight_high_all / 2){
1171                 flag1 = 1;
1172                 gamma_weight_high = i1;
1173             }
1174         }
1175     }
1176     gamma_weight_low = gamma_weight_low / 255;
1177     gamma_weight_high = gamma_weight_high / 255;
1178 
1179     /* Súlypont eltolás szükségességének megállapítása */
1180     gamma_low = 1;
1181     gamma_high = 1;
1182 
1183     /* gammát csak egyírányban toljuk el, */
1184     /* vagyis csak világosítunk ha szükséges, de soha sem sötétítünk */
1185     if (gamma_weight_low < gamma_interval_low){
1186         gamma_low = log(gamma_interval_low) / log(gamma_weight_low);
1187     }
1188     if (gamma_weight_high > gamma_interval_high){
1189         gamma_high = log(gamma_interval_high) / log(gamma_weight_high);
1190     }
1191 
1192     if (gamma_low < (1/gamma_max)){ gamma_low = (1/gamma_max); }
1193     if (gamma_low > gamma_max){ gamma_low = gamma_max; }
1194     if (gamma_high < (1/gamma_max)){ gamma_high = (1/gamma_max); }
1195     if (gamma_high > gamma_max){ gamma_high = gamma_max; }
1196 
1197 
1198 
1199 /* ------------------------------------------------------------------------------ */
1200 /* Recalculate the RGB values by setting the CONTRAST, COLOR BALANCE and GAMMA */
1201 /* ------------------------------------------------------------------------------ */
1202 /* Kép színeinek újrakalkulálása (kontraszt, színegyensúly és gamma korrekció) */
1203 /* A kép összes pontja újrakalkulálódik és visszaíródik a pufferba */
1204 
1205 /* A gamma állításnál a kép színének RGB-jét a gammához mérten nem külön */
1206 /* színcsatornánként, hanem a fényerejükhöz mérten egyben vannnak állítva */
1207 /* A gamma úgy állítódik, hogy a súlypont el van tolva 128-ba */
1208 /* (tehát ha kisebb az értéke akkor növekszik, ha nagyobb, akkor meg csökken) */
1209 /* és ez magával húzza nyújtásos módon arányosan a közép színeket */
1210 /* a 128 irányába */
1211 
1212 
1213     #ifdef __OPENMP__
1214     #pragma omp parallel for private(x, y, addr, addr2, col_r, col_g, col_b, col_r2, col_g2, col_b2, temp2, temp3, cc, H, S, L, N) num_threads(max_threads2)
1215     #endif
1216     for (y=0; y<=bh-1; y++){
1217         addr2 = y * bw * 3 + y * addr_offset;
1218         for (x=0; x<=bw-1; x++){
1219             addr = addr2 + x * 3;
1220 
1221             /* apply changes ONLY on selected area of the image */
1222             if ((apply_on_selection == 0) || ((apply_on_selection) &&
1223                 (x >= x1 &&
1224                 x <= x2 &&
1225                 y >= y1 &&
1226                 y <= y2))) {
1227 
1228             col_r2 = image_buffer[addr + 0];
1229             col_g2 = image_buffer[addr + 1];
1230             col_b2 = image_buffer[addr + 2];
1231 
1232             col_r2 /= 255;
1233             col_g2 /= 255;
1234             col_b2 /= 255;
1235 
1236 
1237             /* CONTRAST SHIFT AND COLOR BALANCE */
1238             /* bp_end-től és wp_end-től viszonyított bp-ből és wp-ből húzással a kontraszt számolás az alábbi */
1239             if ((col_r2 > bp_r_end) && (wp_r > bp_r_end)) {
1240                 col_r2 = bp_r_end + (col_r2 - bp_r_end) * (wp_r_end - bp_r_end) / (wp_r - bp_r_end); }
1241             if ((col_g2 > bp_g_end) && (wp_g > bp_g_end)) {
1242                 col_g2 = bp_g_end + (col_g2 - bp_g_end) * (wp_g_end - bp_g_end) / (wp_g - bp_g_end); }
1243             if ((col_b2 > bp_b_end) && (wp_b > bp_b_end)) {
1244                 col_b2 = bp_b_end + (col_b2 - bp_b_end) * (wp_b_end - bp_b_end) / (wp_b - bp_b_end); }
1245 
1246             /* itt a bp fekete pontot is fel kell szorozni a következő számításhoz, */
1247             /* mert a bp_end -től viszonyítva nyújtjuk a skálát jobbra a fehér irányába */
1248             /* és ezért elmászik a bp */
1249 	    temp3 = 0;
1250             if (wp_r > bp_r_end) {
1251                 temp3 = bp_r_end + (bp_r - bp_r_end) * (wp_r_end - bp_r_end) / (wp_r - bp_r_end); }
1252             if ((col_r2 < wp_r_end) && (wp_r_end != temp3)) {
1253                 col_r2 = wp_r_end - (wp_r_end - col_r2) * (wp_r_end - bp_r_end) / (wp_r_end - temp3); }
1254 
1255 	    temp3 = 0;
1256             if (wp_g > bp_g_end) {
1257                 temp3 = bp_g_end + (bp_g - bp_g_end) * (wp_g_end - bp_g_end) / (wp_g - bp_g_end); }
1258             if ((col_g2 < wp_g_end) && (wp_g_end != temp3)) {
1259                 col_g2 = wp_g_end - (wp_g_end - col_g2) * (wp_g_end - bp_g_end) / (wp_g_end - temp3); }
1260 
1261 	    temp3 = 0;
1262             if (wp_b > bp_b_end) {
1263                 temp3 = bp_b_end + (bp_b - bp_b_end) * (wp_b_end - bp_b_end) / (wp_b - bp_b_end); }
1264             if ((col_b2 < wp_b_end) && (wp_b_end != temp3)) {
1265                 col_b2 = wp_b_end - (wp_b_end - col_b2) * (wp_b_end - bp_b_end) / (wp_b_end - temp3); }
1266 
1267             /* határérték ellenőrzés és visszaírás */
1268             if (col_r2 > 1){ col_r2 = 1; }
1269             if (col_g2 > 1){ col_g2 = 1; }
1270             if (col_b2 > 1){ col_b2 = 1; }
1271             if (col_r2 < 0){ col_r2 = 0; }
1272             if (col_g2 < 0){ col_g2 = 0; }
1273             if (col_b2 < 0){ col_b2 = 0; }
1274 
1275 
1276             /* GAMMA CORRECTION */
1277             /* megjegyzés: ez a gamma felhúzásos módszer színesebb végeredményt ad */
1278             /* mint amelyiknél külön - külön toljuk a színeket, nem arányosan */
1279             temp2 = (col_r2 + col_g2 + col_b2) / 3;
1280             cc = (long)(temp2 * 255);
1281 
1282             /*temp2 = pow(temp2 / 255, gamma_mid) * 255; */
1283             if (temp2 <= 0.5){ temp3 = pow(temp2 * 2, gamma_low) / 2; }
1284             else{ temp3 = pow((temp2 - 0.5) * 2, gamma_high) / 2 + 0.5; }
1285 
1286             /*temp3 = pow(temp2 / 255, gamma_exp) * 255; */
1287             if (temp2 < temp3){
1288                 if (temp2 < 1){
1289                     if (temp2 > 0){
1290                         col_r2 = ((1 - (1 - col_r2) * (1 - temp3)
1291                             / (1 - temp2)) + (col_r2 * temp3 / temp2)) / 2;
1292                         col_g2 = ((1 - (1 - col_g2) * (1 - temp3)
1293                             / (1 - temp2)) + (col_g2 * temp3 / temp2)) / 2;
1294                         col_b2 = ((1 - (1 - col_b2) * (1 - temp3)
1295                             / (1 - temp2)) + (col_b2 * temp3 / temp2)) / 2;
1296                     }
1297                 }
1298             }
1299             else{
1300                 if (temp2 > 0){
1301                     col_r2 = col_r2 * temp3 / temp2;
1302                     col_g2 = col_g2 * temp3 / temp2;
1303                     col_b2 = col_b2 * temp3 / temp2;
1304                 }
1305             }
1306 
1307             /* határérték ellenőrzés és visszaírás */
1308             if (col_r2 > 1){ col_r2 = 1; }
1309             if (col_g2 > 1){ col_g2 = 1; }
1310             if (col_b2 > 1){ col_b2 = 1; }
1311             if (col_r2 < 0){ col_r2 = 0; }
1312             if (col_g2 < 0){ col_g2 = 0; }
1313             if (col_b2 < 0){ col_b2 = 0; }
1314 
1315 
1316             col_r = (long)(col_r2 * 255);
1317             col_g = (long)(col_g2 * 255);
1318             col_b = (long)(col_b2 * 255);
1319             image_buffer[addr + 0] = col_r & 0xff;
1320             image_buffer[addr + 1] = col_g & 0xff;
1321             image_buffer[addr + 2] = col_b & 0xff;
1322 
1323             /* Build up Histogram for SATURATION */
1324             if (x >= x1 &&
1325                 x <= x2 &&
1326                 y >= y1 &&
1327                 y <= y2) {
1328                     double H, S, L;
1329                     RGB_TO_HSL (col_r2, col_g2, col_b2, &H, &S, &L);
1330                     /* Az 'S' értékét a szürke egyenes közepétől távolodva kisebbnek veszem itt, */
1331                     /* mert az optikailag egyre kevésbé tűnik színesnek, */
1332                     /* és ennél a résznél optikailag vizsgálok */
1333                     if (L > 0.5) { L = 1 - L; }
1334                     S = S * L * 2;
1335                     /* Ha S = 0, vagyis szürke a szín, akkor nem adom hozzá */
1336                     /* a színtelítettség hisztogramjához értelemszerűen */
1337                     if (S > 0) {
1338 
1339                         cc = (long)(S * 255);
1340 #ifdef __OPENMP__
1341 			N = omp_get_thread_num();
1342 #else
1343 			N = 0;
1344 #endif
1345                         hist_saturn[cc + N*256]++;
1346                     }
1347             }
1348 
1349             }
1350         }
1351     }
1352 
1353     /* this is a replacement code for arrays for multi processing */
1354     #ifdef __OPENMP__
1355     #pragma omp parallel for private(i1, i2) num_threads(max_threads2)
1356     #endif
1357     for (i1=0; i1<256; i1++){
1358         for (i2=0; i2<max_threads2; i2++){ hist_satur[i1] += hist_saturn[i1 + i2*256]; } }
1359 
1360 
1361 /* ------------------------------------------------------------------------------ */
1362 /* Recalculate the RGB values by setting the SATURAION */
1363 /* ------------------------------------------------------------------------------ */
1364 
1365     /* Hisztogram átlag értékének megállapítása */
1366     hist_satur_avg = 0;
1367 
1368     #ifdef __OPENMP__
1369     #pragma omp parallel for reduction(+:hist_satur_avg) num_threads(max_threads2)
1370     #endif
1371     for (i1=255; i1>=0; i1--){
1372         hist_satur_avg += hist_satur[i1];
1373     }
1374     hist_satur_avg = hist_satur_avg / 255;
1375     /* levágási limit megállapítása, ez az átlag 10%-a bevált a kontrasztnál is,
1376     ezzel az értékkel megfelelően állítja be önmagát a hisztogram,
1377     és a megfelelő nagyságú szélek esnek le */
1378     temp1 = hist_satur_avg * 0.1;
1379 
1380     /* Hisztogram szélének keresése a színek felhúzásához */
1381     i3 = 0;
1382     flag1 = 0;
1383     for (i1=255; i1>=0; i1--){
1384         if (flag1 == 0){
1385             if (hist_satur[i1] >= temp1){
1386                 flag1 = 1;
1387                 i3 = i1;
1388             }
1389         }
1390     }
1391     hist_satur_low = (double)(i3) / 255;
1392 
1393     /* Határérték ellenőrzés */
1394     hist_satur_ok = 1;
1395     if (hist_satur_low > satur_max){ hist_satur_low = satur_max; }
1396     if (hist_satur_low > 0){ hist_satur_ok = log(satur_max) / log(hist_satur_low); }
1397 
1398   /* run saturation recalculation only if necessary */
1399   if (hist_satur_ok != 1){
1400 
1401     #ifdef __OPENMP__
1402     #pragma omp parallel for private(x, y, addr, addr2, col_r, col_g, col_b, col_r2, col_g2, col_b2, H, S, L, cc, N) num_threads(max_threads2)
1403     #endif
1404     for (y=0; y<=bh-1; y++){
1405         addr2 = y * bw * 3 + y * addr_offset;
1406         for (x=0; x<=bw-1; x++){
1407             double S_new;
1408             double S_diff;
1409 
1410             addr = addr2 + x * 3;
1411 
1412             /* apply changes ONLY on selected area of the image */
1413             if ((apply_on_selection == 0) || ((apply_on_selection) &&
1414                 (x >= x1 &&
1415                 x <= x2 &&
1416                 y >= y1 &&
1417                 y <= y2))) {
1418 
1419             col_r2 = image_buffer[addr + 0];
1420             col_g2 = image_buffer[addr + 1];
1421             col_b2 = image_buffer[addr + 2];
1422 
1423             col_r2 = col_r2 / 255;
1424             col_g2 = col_g2 / 255;
1425             col_b2 = col_b2 / 255;
1426 
1427             RGB_TO_HSL (col_r2, col_g2, col_b2, &H, &S, &L);
1428 
1429             /* szín telítettségének hatványos emelése a gammához hasonlóan,
1430                vagyis hatványra emelem az eredeti színtelítettség értékét,
1431                és beszorzom a 0.5-től való távolságának kétszeresével,
1432                hogy a 0.5 pontban lévők maximálisan nővekedjenek, míg az ettől
1433                távolabbra lévők egyre kevesebb mértékben, a 0 és 1 helyen lévők pedig semennyire,
1434 
1435                másképpen fogalmazva, exponenciálisan állítom, de úgy, hogy a közepéhez
1436                közelebb lévők jobban állítódjanak, míg az ettől egyre távolabb esők kevésbé -
1437                erre azért van így szükség, mert a sima hatványra emelésnél túl drasztikus
1438                a görbe és az alsóbb részei a hisztogramnak is túl nagyot ugranak,
1439                így viszont megfelelő lesz a változás, mindegy mekkora az.
1440             */
1441 
1442             if (hist_satur_ok != 1){
1443             	S_new = pow(S, hist_satur_ok);
1444             	S_diff = 1 - (fabs(0.5 - S) * 2);
1445             	S = (S_new - S) * S_diff + S;
1446             }
1447 
1448             HSL_TO_RGB (H, S, L, &col_r2, &col_g2, &col_b2);
1449 
1450             col_r = (long)(col_r2 * 255);
1451             col_g = (long)(col_g2 * 255);
1452             col_b = (long)(col_b2 * 255);
1453             image_buffer[addr + 0] = col_r & 0xff;
1454             image_buffer[addr + 1] = col_g & 0xff;
1455             image_buffer[addr + 2] = col_b & 0xff;
1456 
1457             /*Mellékesen a legvégső Hisztogram létrehozása is */
1458             cc = (long)((double)(col_r + col_g + col_b) / 3);
1459 
1460             /*hist3[cc]++; */
1461 	    /* this is a replacement code for arrays for multi processing */
1462 #ifdef __OPENMP__
1463 	    N = omp_get_thread_num();
1464 #else
1465 	    N = 0;
1466 #endif
1467             hist3n[cc + N*256]++;
1468 
1469             }
1470         }
1471     }
1472 
1473     /* this is a replacement code for arrays for multi processing */
1474     #ifdef __OPENMP__
1475     #pragma omp parallel for private(i1, i2) num_threads(max_threads2)
1476     #endif
1477     for (i1=0; i1<256; i1++){
1478         for (i2=0; i2<max_threads2; i2++){ hist3[i1] += hist3n[i1 + i2*256]; } }
1479 
1480   }
1481   /* just copy the former histogram with no change because there was no saturation processing */
1482   else {
1483     for (i1=0; i1<256; i1++){ hist3[i1] = hist2[i1]; }
1484   }
1485 
1486 
1487 /* a test rész csak akkor működik, ha van math library, mert itt használok szögfüggvényeket */
1488 
1489 /* ------------------------------------------------------------------------------ */
1490 /* TEST: Show Histograms by Drawing them on Image */
1491 /* ------------------------------------------------------------------------------ */
1492 /* */
1493     /* csak normál RGB tömbnél élhet a tesztelés */
1494     if ((format_flag == 0) && (test_flag == 1)) {
1495         /* a max érték kezdõértéke 1, hogy 0-val való osztás ne fordulhasson elõ */
1496         long hist1_max = 1;
1497         long hist2_max = 1;
1498         long hist3_max = 1;
1499         long histS_max = 1;
1500 
1501         /* Figyelem! Többszöri lefuttatása a rutinnak ugyanazon a képen */
1502         /* nem várt eredményt produkál ha a hisztogrammok is ki vannak rajzolva, */
1503         /* mert akkor már a teszt képet is beleveszi a számításba */
1504         for (i1=0; i1<256; i1++){ if (hist1_max < hist1[i1]) { hist1_max = hist1[i1]; } }
1505         for (i1=0; i1<256; i1++){ if (hist2_max < hist2[i1]) { hist2_max = hist2[i1]; } }
1506         for (i1=0; i1<256; i1++){ if (hist3_max < hist3[i1]) { hist3_max = hist3[i1]; } }
1507         for (i1=0; i1<256; i1++){ if (histS_max < hist_satur[i1]) { histS_max = hist_satur[i1]; } }
1508 
1509         for (y=0; y<=bh-1; y++){
1510             addr2 = y * bw * 3 + y * addr_offset;
1511             for (x=0; x<=bw-1; x++){
1512                 addr = addr2 + x * 3;
1513                 xm = x;
1514                 ym = y;
1515                 if (format_flag == 1) { ym = bh - 1 - ym; }
1516                 if (format_flag == 2) { ym = bh - 1 - ym; }
1517 
1518                 /* Keret rajzolása a hisztogrammok köré 1 pixel szélességben */
1519                 if (((xm == 256) && (ym <= 601)) || ((ym == 601) && (xm <= 256))) {
1520                         col = color_black;
1521                         image_buffer[addr + 2] = (col >> 0)  & 0xff;
1522                         image_buffer[addr + 1] = (col >> 8)  & 0xff;
1523                         image_buffer[addr + 0] = (col >> 16) & 0xff;
1524                 }
1525 
1526                 /* Hisztogrammok kirajzolása */
1527                 if ((xm >= 0) && (xm <= 255)) {
1528 			double rad, outline, pi;
1529 
1530                     /* 1. hisztogramm: EREDETI KÉP ÁLLAPOTA KONTRASZT ÁLLÍTÁSSAL*/
1531                     if (ym <= 99) {
1532                         i2 = hist1[xm] * 99 / hist1_max;
1533                         xma1 = (long)(bp * 255);
1534                         xmb1 = (long)(wp * 255);
1535                         xma2 = (long)(bp_end * 255);
1536                         xmb2 = (long)(wp_end * 255);
1537                         /* show the average limit with a horizontal line */
1538                         if (y == (99 - (long)(hist_cut_limit) * 99 / hist_max)){
1539                             col = color_yellow;
1540                         }
1541                         else{
1542                             if (99 - ym >= i2) {
1543                                 if (((xm > xma2) && (xm < xma1)) || ((xm < xmb2) && (xm > xmb1))) {
1544                                     col = color_brown;
1545                                 }
1546                                 else {
1547                                     col = color_black;
1548                                 }
1549                             }
1550                             else {
1551                                 col = color_green;
1552                             }
1553                         }
1554                         if (xm == xma1) { col = color_white; }
1555                         if (xm == xmb1) { col = color_white; }
1556                         image_buffer[addr + 2] = (col >> 0)  & 0xff;
1557                         image_buffer[addr + 1] = (col >> 8)  & 0xff;
1558                         image_buffer[addr + 0] = (col >> 16) & 0xff;
1559                     }
1560 
1561                     /* 2. hisztogramm: KONTRASZT UTÁN GAMMA ÁLLÍTÁSSAL */
1562                     if ((ym >= 100) && (ym <= 199)) {
1563                         i2 = hist2[xm] * 99 / hist2_max;
1564                         xma1 = (long)(gamma_weight_low * 255);
1565                         xmb1 = (long)(gamma_weight_high * 255);
1566                         xma2 = (long)(gamma_interval_low * 255);
1567                         xmb2 = (long)(gamma_interval_high * 255);
1568                         if (199 - ym >= i2) {
1569                             if ((xm < xma2) && (xm > xma1))
1570                             {
1571                                 col = color_brown;
1572                             }
1573                             else{
1574 			        /* vörössel jelölöm barna helyett, hogy ez vissza irányú gamma állítás lenne,
1575 			        ez viszont nem kerül számításra */
1576                                 if ((xm > xma2) && (xm < xma1))
1577                                 {
1578                                     col = color_red;
1579                                 }
1580                                 else{
1581                                     col = color_black;
1582                                 }
1583                             }
1584                         }
1585                         else {
1586                             col = color_green;
1587                         }
1588                         /* Gamma alsó súlypont */
1589                         if (xm == xma1) {
1590                             col = color_white;
1591                         }
1592                         /* Gamma felső súlypont */
1593 /*                        if (xm == (long)(gamma_weight_high * 255)) {
1594                             col = color_white;
1595                         }*/
1596                         image_buffer[addr + 2] = (col >> 0)  & 0xff;
1597                         image_buffer[addr + 1] = (col >> 8)  & 0xff;
1598                         image_buffer[addr + 0] = (col >> 16) & 0xff;
1599                     }
1600 
1601                     /* 3. hisztogramm SZÍNTELÍTETTSÉG ÁLLÍTÁSSAL */
1602                     if ((ym >= 200) && (ym <= 299)) {
1603                         i2 = hist_satur[xm] * 99 / histS_max;
1604                         xma1 = (long)((hist_satur_low)* 255);
1605                         xma2 = (long)(satur_max * 255);
1606                         if (299 - ym >= i2) {
1607                             if (((xm < xma2) && (xm > xma1)) || ((xm > xma2) && (xm < xma1)))
1608                             {
1609                                 col = color_brown;
1610                             }
1611                             else{
1612                                 col = color_black;
1613                             }
1614                         }
1615                         else {
1616                             col = color_blue;
1617                         }
1618                         if (xm == xma1) { col = color_white; }
1619                         image_buffer[addr + 2] = (col >> 0)  & 0xff;
1620                         image_buffer[addr + 1] = (col >> 8)  & 0xff;
1621                         image_buffer[addr + 0] = (col >> 16) & 0xff;
1622                     }
1623 
1624                     /* 4. hisztogramm: KONTRASZT, GAMMA és SZÍNTELÍTETTSÉG UTÁN (VÉGSŐ) */
1625                     if ((ym >= 300) && (ym <= 399)) {
1626                         i2 = hist3[xm] * 99 / hist3_max;
1627                         if (399 - ym >= i2) {
1628                             col = color_black;
1629                         }
1630                         else {
1631                             col = color_green;
1632                         }
1633                         image_buffer[addr + 2] = (col >> 0)  & 0xff;
1634                         image_buffer[addr + 1] = (col >> 8)  & 0xff;
1635                         image_buffer[addr + 0] = (col >> 16) & 0xff;
1636                     }
1637 
1638                     /* 5. Fekete és fehér pont színirányának kirajzolása egy körbe */
1639                     /* konstans a kör sugarához */
1640                     rad = 100;
1641                     /* konstans a körvonal vastagságához */
1642                     outline = 10;
1643                     /* pi értéke */
1644                     pi = 3.1415926535897932;
1645                     if ((ym >= 400) && (ym <= 400+rad*2)) {
1646                         double rr, rx, ry;
1647 
1648                         rx = xm - rad;
1649                         ry = ym - 400 - rad;
1650                         rr = sqrt(rx*rx + ry*ry);
1651 
1652                         /* KÖRÍV MEGRAJZOLÁSA */
1653                         if ((rr <= rad) && (rr >= rad-outline)) {
1654                                 H = 0;
1655                                 if ((rx >= 0) && (ry <  0)) { H = asin( rx / rr) / pi / 2 + 0.00; }
1656                                 if ((rx >= 0) && (ry >= 0)) { H = asin( ry / rr) / pi / 2 + 0.25; }
1657                                 if ((rx <  0) && (ry >= 0)) { H = asin(-rx / rr) / pi / 2 + 0.50; }
1658                                 if ((rx <  0) && (ry <  0)) { H = asin(-ry / rr) / pi / 2 + 0.75; }
1659                                 S = 1;
1660                                 L = 0.5;
1661                                 L = rad - rr;
1662                                 if (L > outline / 2) { L = outline - L; }
1663                                 L = L / outline;
1664                                 HSL_TO_RGB (H, S, L, &col_r2, &col_g2, &col_b2);
1665                                 col_r = (long)(col_r2 * 255);
1666                                 col_g = (long)(col_g2 * 255);
1667                                 col_b = (long)(col_b2 * 255);
1668                                 image_buffer[addr + 0] = col_r & 0xff;
1669                                 image_buffer[addr + 1] = col_g & 0xff;
1670                                 image_buffer[addr + 2] = col_b & 0xff;
1671                         }
1672                         else {
1673                             double px, py, lx, ly, d;
1674 
1675                             col = color_black;
1676                             px = 0; py = 0;
1677                             lx = 0; ly = 0;
1678 
1679                             /* FEKETE PONT SZÍNIRÁNYA EGYENESÉNEK MEGHÚZÁSA */
1680                             /* Szürke pontnál nem jelenik meg egyenes a körben */
1681                             RGB_TO_HSL (bp_r, bp_g, bp_b, &H, &S, &L);
1682 
1683                             if ((H >= 0.00) && (H < 0.25)) { lx =  sin((H - 0.00) * 2 * pi) * rr; ly =  cos((H - 0.00) * 2 * pi) * rr; }
1684                             if ((H >= 0.25) && (H < 0.50)) { lx =  cos((H - 0.25) * 2 * pi) * rr; ly = -sin((H - 0.25) * 2 * pi) * rr; }
1685                             if ((H >= 0.50) && (H < 0.75)) { lx = -sin((H - 0.50) * 2 * pi) * rr; ly = -cos((H - 0.50) * 2 * pi) * rr; }
1686                             if ((H >= 0.75) && (H < 1.00)) { lx = -cos((H - 0.75) * 2 * pi) * rr; ly =  sin((H - 0.75) * 2 * pi) * rr; }
1687                             px = lx * S;
1688                             py = ly * S;
1689 
1690                             d = ly * rx + lx * ry;
1691                             d = d / sqrt(lx * lx + ly * ly);
1692                             if (d < 0) { d = 0 - d; }
1693 
1694                             if ((d < 1) && (rr < rad) && (sgn(rx) == sgn(px)) && (sgn(ry) == -sgn(py))) {
1695                                 if (rr < rad * S) { col = color_white; }
1696                                 else { col = color_gray; }
1697                             }
1698 
1699                             /* FEHÉR PONT SZÍNIRÁNYA EGYENESÉNEK MEGHÚZÁSA */
1700                             RGB_TO_HSL (wp_r, wp_g, wp_b, &H, &S, &L);
1701 
1702                             if ((H >= 0.00) && (H < 0.25)) { lx =  sin((H - 0.00) * 2 * pi) * rr; ly =  cos((H - 0.00) * 2 * pi) * rr; }
1703                             if ((H >= 0.25) && (H < 0.50)) { lx =  cos((H - 0.25) * 2 * pi) * rr; ly = -sin((H - 0.25) * 2 * pi) * rr; }
1704                             if ((H >= 0.50) && (H < 0.75)) { lx = -sin((H - 0.50) * 2 * pi) * rr; ly = -cos((H - 0.50) * 2 * pi) * rr; }
1705                             if ((H >= 0.75) && (H < 1.00)) { lx = -cos((H - 0.75) * 2 * pi) * rr; ly =  sin((H - 0.75) * 2 * pi) * rr; }
1706                             px = lx * S;
1707                             py = ly * S;
1708 
1709                             d = ly * rx + lx * ry;
1710                             d = d / sqrt(lx * lx + ly * ly);
1711                             if (d < 0) { d = 0 - d; }
1712 
1713                             if ((d < 1) && (rr < rad) && (sgn(rx) == sgn(px)) && (sgn(ry) == -sgn(py))) {
1714                                 if (rr < rad * S) { col = color_white; }
1715                                 else { col = color_gray; }
1716                             }
1717 
1718                             image_buffer[addr + 2] = (col >> 0)  & 0xff;
1719                             image_buffer[addr + 1] = (col >> 8)  & 0xff;
1720                             image_buffer[addr + 0] = (col >> 16) & 0xff;
1721 
1722                         }
1723                     }
1724                 }
1725             }
1726         }
1727     }
1728 
1729 
1730 exit:
1731 
1732     if (hist_saturn){ free (hist_saturn); }
1733     if (hist1n)     { free (hist1n);      }
1734     if (hist2n)     { free (hist2n);      }
1735     if (hist3n)     { free (hist3n);      }
1736     if (col_r3n)    { free (col_r3n);     }
1737     if (col_g3n)    { free (col_g3n);     }
1738     if (col_b3n)    { free (col_b3n);     }
1739 
1740 }
1741 
1742 
1743 
1744 /* ------------------------------ */
1745 /* ----- MAIN AARGB ENTRIES ----- */
1746 /* ------------------------------ */
1747 
AARGB_NORMAL(unsigned char * image_buffer,int image_width,int image_height)1748 void AARGB_NORMAL(
1749     unsigned char *image_buffer,
1750     int image_width,
1751     int image_height)
1752 {
1753     AARGB_MAIN(
1754         image_buffer,
1755         image_width,
1756         image_height,
1757         0,
1758         0,
1759         image_width-1,
1760         image_height-1,
1761         0,
1762         0,
1763         0);
1764 }
1765 
AARGB_NORMAL_SEL(unsigned char * image_buffer,int image_width,int image_height,int x1,int y1,int x2,int y2,int apply_on_selection)1766 void AARGB_NORMAL_SEL(
1767     unsigned char *image_buffer,
1768     int image_width,
1769     int image_height,
1770     int x1,
1771     int y1,
1772     int x2,
1773     int y2,
1774     int apply_on_selection)
1775 {
1776     AARGB_MAIN(
1777         image_buffer,
1778         image_width,
1779         image_height,
1780         x1,
1781         y1,
1782         x2,
1783         y2,
1784         0,
1785         apply_on_selection,
1786         0);
1787 }
1788 
AARGB_DIB(unsigned char * image_buffer,int image_width,int image_height)1789 void AARGB_DIB(
1790     unsigned char *image_buffer,
1791     int image_width,
1792     int image_height)
1793 {
1794     AARGB_MAIN(
1795         image_buffer,
1796         image_width,
1797         image_height,
1798         0,
1799         0,
1800         image_width-1,
1801         image_height-1,
1802         1,
1803         0,
1804         0);
1805 }
1806 
AARGB_DIB_SEL(unsigned char * image_buffer,int image_width,int image_height,int x1,int y1,int x2,int y2,int apply_on_selection)1807 void AARGB_DIB_SEL(
1808     unsigned char *image_buffer,
1809     int image_width,
1810     int image_height,
1811     int x1,
1812     int y1,
1813     int x2,
1814     int y2,
1815     int apply_on_selection)
1816 {
1817     AARGB_MAIN(
1818         image_buffer,
1819         image_width,
1820         image_height,
1821         x1,
1822         y1,
1823         x2,
1824         y2,
1825         1,
1826         apply_on_selection,
1827         0);
1828 }
1829 
AARGB_BMP(unsigned char * image_buffer)1830 void AARGB_BMP(
1831     unsigned char *image_buffer)
1832 {
1833 	long f_bm;
1834 	long f_bitcount;
1835 	long f_compressed;
1836 	long f_offs;
1837 	long f_width;
1838 	long f_height;
1839 
1840 	f_bm = 0;
1841 	f_bm += image_buffer[0] << 0;
1842 	f_bm += image_buffer[1] << 8;
1843 
1844 	f_bitcount = 0;
1845 	f_bitcount += image_buffer[28] << 0;
1846 	f_bitcount += image_buffer[29] << 8;
1847 
1848 	f_compressed = 0;
1849 	f_compressed += image_buffer[30] << 0;
1850 	f_compressed += image_buffer[31] << 8;
1851 	f_compressed += image_buffer[32] << 16;
1852 	f_compressed += image_buffer[33] << 24;
1853 
1854 	if ((f_bm == 0x00004d42) && (f_bitcount == 24) && (f_compressed == 0)) {
1855 
1856 		f_offs = 0;
1857 		f_offs += image_buffer[10] << 0;
1858 		f_offs += image_buffer[11] << 8;
1859 		f_offs += image_buffer[12] << 16;
1860 		f_offs += image_buffer[13] << 24;
1861 
1862 		f_width = 0;
1863 		f_width += image_buffer[18] << 0;
1864 		f_width += image_buffer[19] << 8;
1865 		f_width += image_buffer[20] << 16;
1866 		f_width += image_buffer[21] << 24;
1867 
1868 		f_height = 0;
1869 		f_height += image_buffer[22] << 0;
1870 		f_height += image_buffer[23] << 8;
1871 		f_height += image_buffer[24] << 16;
1872 		f_height += image_buffer[25] << 24;
1873 
1874 		AARGB_MAIN(
1875 			image_buffer + f_offs,
1876 			f_width,
1877 			f_height,
1878 			0,
1879 			0,
1880 			f_width-1,
1881 			f_height-1,
1882             		2,
1883 			0,
1884             		0);
1885 	}
1886 }
1887 
AARGB_BMP_SEL(unsigned char * image_buffer,int x1,int y1,int x2,int y2,int apply_on_selection)1888 void AARGB_BMP_SEL(
1889     unsigned char *image_buffer,
1890     int x1,
1891     int y1,
1892     int x2,
1893     int y2,
1894     int apply_on_selection)
1895 {
1896 	long f_bm;
1897 	long f_bitcount;
1898 	long f_compressed;
1899 	long f_offs;
1900 	long f_width;
1901 	long f_height;
1902 
1903 	f_bm = 0;
1904 	f_bm += image_buffer[0] << 0;
1905 	f_bm += image_buffer[1] << 8;
1906 
1907 	f_bitcount = 0;
1908 	f_bitcount += image_buffer[28] << 0;
1909 	f_bitcount += image_buffer[29] << 8;
1910 
1911 	f_compressed = 0;
1912 	f_compressed += image_buffer[30] << 0;
1913 	f_compressed += image_buffer[31] << 8;
1914 	f_compressed += image_buffer[32] << 16;
1915 	f_compressed += image_buffer[33] << 24;
1916 
1917 	if ((f_bm == 0x00004d42) && (f_bitcount == 24) && (f_compressed == 0)) {
1918 
1919 		f_offs = 0;
1920 		f_offs += image_buffer[10] << 0;
1921 		f_offs += image_buffer[11] << 8;
1922 		f_offs += image_buffer[12] << 16;
1923 		f_offs += image_buffer[13] << 24;
1924 
1925 		f_width = 0;
1926 		f_width += image_buffer[18] << 0;
1927 		f_width += image_buffer[19] << 8;
1928 		f_width += image_buffer[20] << 16;
1929 		f_width += image_buffer[21] << 24;
1930 
1931 		f_height = 0;
1932 		f_height += image_buffer[22] << 0;
1933 		f_height += image_buffer[23] << 8;
1934 		f_height += image_buffer[24] << 16;
1935 		f_height += image_buffer[25] << 24;
1936 
1937 		AARGB_MAIN(
1938 			image_buffer + f_offs,
1939 			f_width,
1940 			f_height,
1941 			x1,
1942 			y1,
1943 			x2,
1944 			y2,
1945             		2,
1946 			apply_on_selection,
1947             		0);
1948 	}
1949 }
1950 
1951 
1952 
1953 
1954 /*
1955 int main (){
1956 	return 0;
1957 }
1958 */
1959